summaryrefslogtreecommitdiffstats
path: root/dev/a6-harold/billboards.cc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dev/a6-harold/billboards.cc206
1 files changed, 0 insertions, 206 deletions
diff --git a/dev/a6-harold/billboards.cc b/dev/a6-harold/billboards.cc
deleted file mode 100644
index 5ec508a..0000000
--- a/dev/a6-harold/billboards.cc
+++ /dev/null
@@ -1,206 +0,0 @@
-/** CSci-4611 Assignment 6: Harold
- */
-
-#include "billboards.h"
-
-Billboards::Billboards() {
-
-}
-
-
-Billboards::~Billboards() {
-
-}
-
-
-void Billboards::Init(ShaderProgram *stroke3d_shaderprog) {
- stroke3d_shaderprog_ = stroke3d_shaderprog;
-}
-
-
-/// Projects a 2D normalized screen point (e.g., the mouse position in normalized
-/// device coordinates) to a 3D point on a plane defined by an "origin", which can
-/// really be any point coincident with the plane, and the plane normal. Returns
-/// true if the screen point projects onto the plane and stores the result in
-/// plane_point. Returns false if the screen point does not project onto the plane.
-bool Billboards::ScreenPtHitsPlane(const Matrix4 &view_matrix, const Matrix4 &proj_matrix,
- const Point3 &plane_origin, const Vector3 &plane_normal,
- const Point2 &normalized_screen_pt, Point3 *plane_point)
-{
- Matrix4 camera_matrix = view_matrix.Inverse();
- Point3 eye = camera_matrix.ColumnToPoint3(3);
-
- Point3 pt3d = GfxMath::ScreenToNearPlane(view_matrix, proj_matrix, normalized_screen_pt);
- Ray ray(eye, (pt3d - eye).ToUnit());
- float t;
- return ray.IntersectPlane(plane_origin, plane_normal, &t, plane_point);
-}
-
-
-/// Checks to see if a ray starting at the eye point and passing through 2D
-/// normalized screen point projects onto any of the billboards in the scene. If
-/// so, returns the id of the closest billboard intersected. If not, returns -1.
-int Billboards::IntersectBillboard(const Matrix4 &view_matrix, const Matrix4 &proj_matrix,
- const Point2 &normalized_screen_pt)
-{
- Matrix4 camera_matrix = view_matrix.Inverse();
- Point3 eye = camera_matrix.ColumnToPoint3(3);
-
- int id = -1;
- float best_i_time = -1.0;
-
- Point3 pt3d = GfxMath::ScreenToNearPlane(view_matrix, proj_matrix, normalized_screen_pt);
- Ray ray(eye, (pt3d - eye).ToUnit());
-
- Point3 i_point;
- float i_time;
- int i_tri_id;
- for (int i=0; i<billboards_.size(); i++) {
- Matrix4 to_billboard_space = billboards_[i].transform.Inverse();
- Ray ray_billboard_space = to_billboard_space * ray;
- if ((ray_billboard_space.IntersectAABB(billboards_[i].bounding_box, &i_time)) &&
- (ray_billboard_space.IntersectMesh(billboards_[i].mesh, &i_time, &i_point, &i_tri_id)) &&
- ((best_i_time == -1.0) || (i_time < best_i_time))) {
- id = i;
- }
- }
-
- return id;
-}
-
-
-/// Adds a new stroke as a billboard by projecting it onto a plane parallel
-/// to the filmplane that intersects with the base point, which should lie
-/// on the ground.
-void Billboards::AddBillboardStroke(const Matrix4 &view_matrix, const Matrix4 &proj_matrix,
- const std::vector<Point2> &stroke2d, const Mesh &stroke2d_mesh,
- const Color &stroke_color, Ground *ground_ptr)
-{
- Matrix4 camera_matrix = view_matrix.Inverse();
- Point3 eye = camera_matrix.ColumnToPoint3(3);
-
- // Create a new billboard
- Billboard b;
- b.color = stroke_color;
- b.transform = Matrix4();
- b.mesh = stroke2d_mesh;
-
- // find the base point for the billboard
- ground_ptr->ScreenPtHitsGround(view_matrix, proj_matrix, stroke2d[0], &b.anchor_pt);
- Vector3 norm = (eye - b.anchor_pt);
- norm[1] = 0.0; // with 0 change in Y so the billboard does not tilt
- norm.Normalize(); // convert to a unit vector
-
- // project the stroke into 3D to lie on the projection plane
- std::vector<Point3> verts;
- for (int i=0; i<b.mesh.num_vertices(); i++) {
- Point2 pscreen = Point2(b.mesh.read_vertex_data(i)[0], b.mesh.read_vertex_data(i)[1]);
- Point3 pplane;
- ScreenPtHitsPlane(view_matrix, proj_matrix, b.anchor_pt, norm, pscreen, &pplane);
- verts.push_back(pplane);
- }
-
- Matrix4 to_canonical_billboard = Matrix4::Align(b.anchor_pt, Vector3::UnitY(), norm,
- Point3::Origin(), Vector3::UnitY(), Vector3::UnitZ());
-
- for (int i=0; i<verts.size(); i++) {
- verts[i] = to_canonical_billboard * verts[i];
- }
-
- b.mesh.SetVertices(verts);
-
- for (int i=0; i<b.mesh.num_vertices(); i++) {
- b.bounding_box = b.bounding_box + AABB(b.mesh.read_vertex_data(i));
- }
- b.bounding_box.set_user_data((int)billboards_.size());
-
- billboards_.push_back(b);
-}
-
-
-/// Edits an existing billboard by adding an additional stroke to it.
-void Billboards::AddToBillboard(const Matrix4 &view_matrix, const Matrix4 &proj_matrix,
- int billboard_id, const Mesh &stroke2d_mesh,
- const Color &stroke_color)
-{
- Matrix4 camera_matrix = view_matrix.Inverse();
- Point3 eye = camera_matrix.ColumnToPoint3(3);
-
- // Really what this does is add a new billboard that lies in the same plane
- // as the one we are "editing" and has the same anchor point so that they
- // will both rotate the same way.
- Billboard b;
- b.color = stroke_color;
- b.transform = Matrix4();
- b.mesh = stroke2d_mesh;
-
- b.anchor_pt = billboards_[billboard_id].anchor_pt;
-
-
- Vector3 norm = (eye - b.anchor_pt);
- norm[1] = 0.0; // with 0 change in Y so the billboard does not tilt
- norm.Normalize(); // convert to a unit vector
-
- // project the stroke into 3D to lie on the projection plane
- std::vector<Point3> verts;
- for (int i=0; i<b.mesh.num_vertices(); i++) {
- Point2 pscreen = Point2(b.mesh.read_vertex_data(i)[0], b.mesh.read_vertex_data(i)[1]);
- Point3 pplane;
- ScreenPtHitsPlane(view_matrix, proj_matrix, b.anchor_pt, norm, pscreen, &pplane);
- verts.push_back(pplane);
- }
-
- Matrix4 to_canonical_billboard = Matrix4::Align(b.anchor_pt, Vector3::UnitY(), norm,
- Point3::Origin(), Vector3::UnitY(), Vector3::UnitZ());
-
- for (int i=0; i<verts.size(); i++) {
- verts[i] = to_canonical_billboard * verts[i];
- }
-
- b.mesh.SetVertices(verts);
-
- for (int i=0; i<b.mesh.num_vertices(); i++) {
- b.bounding_box = b.bounding_box + AABB(b.mesh.read_vertex_data(i));
- }
- b.bounding_box.set_user_data((int)billboards_.size());
-
- billboards_.push_back(b);
-}
-
-
-void Billboards::UpdateBillboardRotations(const Point3 &current_eye_point) {
- // Whenver the camera moves, we also need to rotate the billboards so
- // that they always face the viewer.
- for (int i=0; i<billboards_.size(); i++) {
- // billboards are stored in a coordinate system where the base is
- // at (0,0,0), rotation happens about the Y axis, and the billboard's
- // normal is +Z.
- Point3 a_p = Point3(0,0,0); // 'anchor point' in billboard coordinates
- Vector3 a_v1 = Vector3::UnitY(); // 'up' in billboard coordinates
- Vector3 a_v2 = Vector3::UnitZ(); // 'normal' in billboard coordinates
-
- Point3 b_p = billboards_[i].anchor_pt; // 'anchor point' in world coordinates
- Vector3 b_v1 = Vector3::UnitY(); // 'up' in world coordinates
- Vector3 b_v2 = (current_eye_point - b_p); // 'normal' in world coordinates
- b_v2[1] = 0.0; // force 0 change in Y so the billboard does not tilt
- b_v2.Normalize(); // convert to a unit vector
-
- billboards_[i].transform = Matrix4::Align(a_p,a_v1,a_v2, b_p,b_v1,b_v2);
- }
-}
-
-
-void Billboards::Draw(const Matrix4 &view_matrix, const Matrix4 &proj_matrix) {
- // Draw billboard meshes
- stroke3d_shaderprog_->UseProgram();
- stroke3d_shaderprog_->SetUniform("projectionMatrix", proj_matrix);
- for (int i=0; i<billboards_.size(); i++) {
- Matrix4 model_matrix = billboards_[i].transform;
- Matrix4 modelview_matrix = view_matrix * model_matrix;
- stroke3d_shaderprog_->SetUniform("modelViewMatrix", modelview_matrix);
- stroke3d_shaderprog_->SetUniform("strokeColor", billboards_[i].color);
- billboards_[i].mesh.Draw();
- }
- stroke3d_shaderprog_->StopProgram();
-}
-