diff options
author | Matt Strapp <matt@mattstrapp.net> | 2021-09-20 18:15:14 -0500 |
---|---|---|
committer | Matt Strapp <matt@mattstrapp.net> | 2021-09-20 18:15:14 -0500 |
commit | 342403a02f8063903d0f38327430721d4d0ae331 (patch) | |
tree | 29d020a27bc16939c568dd4b29166566d1c0e658 /dev/MinGfx/src/unicam.cc | |
parent | Fix parenthesis (diff) | |
download | csci4611-342403a02f8063903d0f38327430721d4d0ae331.tar csci4611-342403a02f8063903d0f38327430721d4d0ae331.tar.gz csci4611-342403a02f8063903d0f38327430721d4d0ae331.tar.bz2 csci4611-342403a02f8063903d0f38327430721d4d0ae331.tar.lz csci4611-342403a02f8063903d0f38327430721d4d0ae331.tar.xz csci4611-342403a02f8063903d0f38327430721d4d0ae331.tar.zst csci4611-342403a02f8063903d0f38327430721d4d0ae331.zip |
do ass1submission-p1.0
Diffstat (limited to '')
-rw-r--r-- | dev/MinGfx/src/unicam.cc | 634 |
1 files changed, 317 insertions, 317 deletions
diff --git a/dev/MinGfx/src/unicam.cc b/dev/MinGfx/src/unicam.cc index 0acb9c9..7b2fad4 100644 --- a/dev/MinGfx/src/unicam.cc +++ b/dev/MinGfx/src/unicam.cc @@ -1,317 +1,317 @@ -/* - Copyright (c) 2017,2018 Regents of the University of Minnesota. - All Rights Reserved. - See corresponding header file for details. - */ - -#include "unicam.h" - -#include "gfxmath.h" - -namespace mingfx { - - -UniCam::UniCam() : state_(UniCamState::START), defaultDepth_(4.0), boundingSphereRad_(1.0), - dollyFactor_(1.0), dollyInitialized_(false), elapsedTime_(0.0), hitGeometry_(false), - rotAngularVel_(0.0), rotInitialized_(false), rotLastTime_(0.0), showIcon_(false) -{ -} - -UniCam::UniCam(const Matrix4 &initialViewMatrix) : - state_(UniCamState::START), defaultDepth_(4.0), V_(initialViewMatrix), boundingSphereRad_(1.0), - dollyFactor_(1.0), dollyInitialized_(false), elapsedTime_(0.0), hitGeometry_(false), - rotAngularVel_(0.0), rotInitialized_(false), rotLastTime_(0.0), showIcon_(false) -{ -} - -UniCam::~UniCam() -{ -} - - -void UniCam::recalc_angular_vel() { - // update angular velocity - float cutoff = (float)elapsedTime_ - 0.2f; // look just at the last 0.2 secs - while ((rotAngularVelBuffer_.size()) && (rotAngularVelBuffer_[0].first < cutoff)) { - rotAngularVelBuffer_.erase(rotAngularVelBuffer_.begin()); - } - rotAngularVel_ = 0.0; - if (rotAngularVelBuffer_.size()) { - for (int i=0; i<rotAngularVelBuffer_.size(); i++) { - rotAngularVel_ += rotAngularVelBuffer_[i].second; - } - rotAngularVel_ /= rotAngularVelBuffer_.size(); - } - //std::cout << rotAngularVelBuffer_.size() << " " << rotAngularVel_ << std::endl; -} - - -void UniCam::OnButtonDown(const Point2 &mousePos, float mouseZ) { - if (state_ == UniCamState::START) { - initialClickPos_ = mousePos; - mouseLast_ = mousePos; - elapsedTime_ = 0.0; - rotInitialized_ = false; - dollyInitialized_ = false; - - hitGeometry_ = (mouseZ < 1.0); - if (hitGeometry_) { - hitPoint_ = GfxMath::ScreenToWorld(V_, Pdraw_, mousePos, mouseZ); - } - else { - hitPoint_ = GfxMath::ScreenToDepthPlane(V_, Pdraw_, Point2(0,0), defaultDepth_); - } - showIcon_ = true; - state_ = UniCamState::PAN_DOLLY_ROT_DECISION; - } - else if (state_ == UniCamState::ROT_WAIT_FOR_SECOND_CLICK) { - // we have the second click now, and we will start the trackball rotate interaction - state_ = UniCamState::ROT; - } - else if (state_ == UniCamState::SPINNING) { - // this click is to "catch" the model, stopping it from spinning. - state_ = UniCamState::START; - } - else { - std::cerr << "UniCam::OnButtonDown() unexpected state." << std::endl; - } -} - -void UniCam::OnDrag(const Point2 &mousePos) { - if (state_ == UniCamState::PAN_DOLLY_ROT_DECISION) { - const double panMovementThreshold = 0.01; - const double dollyMovementThreshold = 0.01; - if (fabs(mousePos[0] - initialClickPos_[0]) > panMovementThreshold) { - // already lots of horizontal movement, we can go right to pan - state_ = UniCamState::PAN; - showIcon_ = false; - } - else if (fabs(mousePos[1] - initialClickPos_[1]) > dollyMovementThreshold) { - // already lots of vertical movement, we can go right to dolly - state_ = UniCamState::DOLLY; - showIcon_ = false; - } - else if (elapsedTime_ > 1.0) { - // timeout, this was not a quick click to set a center of rotation, - // so there is no intent to rotate. instead we will be doing either - // pan or dolly. - state_ = UniCamState::PAN_DOLLY_DECISION; - showIcon_ = false; - } - } - else if (state_ == UniCamState::PAN_DOLLY_DECISION) { - const double panMovementThreshold = 0.01; - const double dollyMovementThreshold = 0.01; - if (fabs(mousePos[0] - initialClickPos_[0]) > panMovementThreshold) { - // lots of horizontal movement, go to pan - state_ = UniCamState::PAN; - } - else if (fabs(mousePos[1] - initialClickPos_[1]) > dollyMovementThreshold) { - // lots of vertical movement, go to dolly - state_ = UniCamState::DOLLY; - } - } - else if (state_ == UniCamState::PAN) { - Matrix4 camMat = V_.Inverse(); - Point3 eye = camMat.ColumnToPoint3(3); - Vector3 look = -camMat.ColumnToVector3(2); - float depth = (hitPoint_ - eye).Dot(look); - Point3 pWorld1 = GfxMath::ScreenToDepthPlane(V_, Pdraw_, mouseLast_, depth); - Point3 pWorld2 = GfxMath::ScreenToDepthPlane(V_, Pdraw_, mousePos, depth); - V_ = V_ * Matrix4::Translation(pWorld2 - pWorld1); - } - else if (state_ == UniCamState::DOLLY) { - if (!dollyInitialized_) { - // Setup dollyFactor so that if you move the mouse to the bottom of the screen, the point - // you clicked on will be right on top of the camera. - Matrix4 camMat = V_.Inverse(); - Point3 eye = camMat.ColumnToPoint3(3); - Vector3 look = -camMat.ColumnToVector3(2); - float depth = (hitPoint_ - eye).Dot(look); - float deltaYToBottom = initialClickPos_[1] + 1; - dollyFactor_ = depth / deltaYToBottom; - dollyInitialized_ = true; - } - Vector3 d(0, 0, -dollyFactor_ * (mousePos[1] - mouseLast_[1])); - V_ = Matrix4::Translation(d) * V_ ; - } - else if (state_ == UniCamState::ROT) { - if (!rotInitialized_) { - float depth = 0.0; - if (hitGeometry_) { - // if we hit some geometry, then make that the center of rotation - boundingSphereCtr_ = hitPoint_; - Matrix4 camMat = V_.Inverse(); - Point3 eye = camMat.ColumnToPoint3(3); - Vector3 look = -camMat.ColumnToVector3(2); - depth = (hitPoint_ - eye).Dot(look); - } - else { - // if we did not hit any geometry, then center the bounding sphere in front of - // the camera at a distance that can be configured by the user. - boundingSphereCtr_ = GfxMath::ScreenToDepthPlane(V_, Pdraw_, Point2(0,0), defaultDepth_); - depth = defaultDepth_; - } - - // determine the size of the bounding sphere by projecting a screen-space - // distance of 0.75 units to the depth of the sphere center - Point3 pWorld1 = GfxMath::ScreenToDepthPlane(V_, Pdraw_, Point2(0,0), depth); - Point3 pWorld2 = GfxMath::ScreenToDepthPlane(V_, Pdraw_, Point2(0.75,0), depth); - boundingSphereRad_ = (pWorld2-pWorld1).Length(); - - rotLastTime_ = elapsedTime_; - rotAngularVelBuffer_.clear(); - rotInitialized_ = true; - } - else { - // Do a trackball rotation based on the mouse movement and the bounding sphere - // setup earlier. - - Matrix4 camMat = V_.Inverse(); - Point3 eye = camMat.ColumnToPoint3(3); - - // last mouse pos - bool hit1 = false; - Point3 mouse3D1 = GfxMath::ScreenToNearPlane(V_, Pdraw_, mouseLast_); - Ray ray1(eye, mouse3D1 - eye); - float t1; - Point3 iPoint1; - if (ray1.IntersectSphere(boundingSphereCtr_, boundingSphereRad_, &t1, &iPoint1)) { - hit1 = true; - } - - // current mouse pos - bool hit2 = false; - Point3 mouse3D2 = GfxMath::ScreenToNearPlane(V_, Pdraw_, mousePos); - Ray ray2(eye, mouse3D2 - eye); - float t2; - Point3 iPoint2; - if (ray2.IntersectSphere(boundingSphereCtr_, boundingSphereRad_, &t2, &iPoint2)) { - hit2 = true; - } - rotLastIPoint_ = iPoint2; - - if (hit1 && hit2) { - Vector3 v1 = (iPoint1 - boundingSphereCtr_).ToUnit(); - Vector3 v2 = (iPoint2 - boundingSphereCtr_).ToUnit(); - - rotAxis_ = v1.Cross(v2).ToUnit(); - float angle = std::acos(v1.Dot(v2)); - - if (std::isfinite(angle)) { - Matrix4 R = Matrix4::Rotation(boundingSphereCtr_, rotAxis_, angle); - R = R.Orthonormal(); - V_ = V_ * R; - //V_ = V_.orthonormal(); - - // add a sample to the angular vel vector - double dt = elapsedTime_ - rotLastTime_; - double avel = angle / dt; - if (std::isfinite(avel)) { - rotAngularVelBuffer_.push_back(std::make_pair(elapsedTime_, avel)); - } - rotLastTime_ = elapsedTime_; - } - } - - recalc_angular_vel(); - } - } - else if (state_ == UniCamState::START) { - // picked up a little mouse movement after "catching" a spinning model - // nothing to do, just wait for the button up. - } - else { - std::cerr << "UniCam::OnDrag() unexpected state." << std::endl; - } - mouseLast_ = mousePos; -} - -void UniCam::OnButtonUp(const Point2 &mousePos) { - if (state_ == UniCamState::PAN_DOLLY_ROT_DECISION) { - // here, we got a quick click of the mouse to indicate a center of rotation - // so we now go into a mode of waiting for a second click to start rotating - // around that point. - state_ = UniCamState::ROT_WAIT_FOR_SECOND_CLICK; - } - else if (state_ == UniCamState::ROT) { - showIcon_ = false; - // if we are leaving the rotation state and the angular velocity is - // greater than some thresold, then the user has "thrown" the model - // keep rotating the same way by entering the spinning state. - - recalc_angular_vel(); - //std::cout << "check for spin: " << n-start << " " << rotAngularVel_ << " " << avel2 << std::endl; - - const float threshold = 0.2f; - if (std::fabs(rotAngularVel_) > threshold) { - state_ = UniCamState::SPINNING; - } - else { - state_ = UniCamState::START; - } - } - else { - showIcon_ = false; - // all other cases go back to the start state - state_ = UniCamState::START; - } -} - -void UniCam::AdvanceAnimation(double dt) { - elapsedTime_ += dt; - - if (state_ == UniCamState::SPINNING) { - double deltaT = elapsedTime_ - rotLastTime_; - rotLastTime_ = elapsedTime_; - double angle = (double)rotAngularVel_ * deltaT; - Matrix4 R = Matrix4::Rotation(boundingSphereCtr_, rotAxis_, (float)angle); - //R = R.orthonormal(); - V_ = V_ * R; - } -} - - -void UniCam::Draw(const Matrix4 &projectionMatrix) { - Pdraw_ = projectionMatrix; - - if (showIcon_) { - Matrix4 camMat = V_.Inverse(); - Point3 eye = camMat.ColumnToPoint3(3); - Vector3 look = -camMat.ColumnToVector3(2); - float depth = (hitPoint_ - eye).Dot(look); - Point3 pWorld1 = GfxMath::ScreenToDepthPlane(V_, Pdraw_, Point2(0.f,0.f), depth); - Point3 pWorld2 = GfxMath::ScreenToDepthPlane(V_, Pdraw_, Point2(0.015f,0.f), depth); - float rad = (pWorld2 - pWorld1).Length(); - Matrix4 M = Matrix4::Translation(hitPoint_ - Point3::Origin()) * Matrix4::Scale(Vector3(rad, rad, rad)); - quickShapes_.DrawSphere(M, V_, Pdraw_, Color(0,0,0)); - } -} - - -Matrix4 UniCam::view_matrix() { - return V_; -} - -void UniCam::set_view_matrix(Matrix4 viewMatrix) { - V_ = viewMatrix; -} - -void UniCam::set_default_depth(float d) { - defaultDepth_ = d; -} - -Point3 UniCam::eye() { - Matrix4 camMat = V_.Inverse(); - return camMat.ColumnToPoint3(3); -} - -Vector3 UniCam::look() { - Matrix4 camMat = V_.Inverse(); - return -camMat.ColumnToVector3(2); -} - - - - -} // end namespace +/*
+ Copyright (c) 2017,2018 Regents of the University of Minnesota.
+ All Rights Reserved.
+ See corresponding header file for details.
+ */
+
+#include "unicam.h"
+
+#include "gfxmath.h"
+
+namespace mingfx {
+
+
+UniCam::UniCam() : state_(UniCamState::START), defaultDepth_(4.0), boundingSphereRad_(1.0),
+ dollyFactor_(1.0), dollyInitialized_(false), elapsedTime_(0.0), hitGeometry_(false),
+ rotAngularVel_(0.0), rotInitialized_(false), rotLastTime_(0.0), showIcon_(false)
+{
+}
+
+UniCam::UniCam(const Matrix4 &initialViewMatrix) :
+ state_(UniCamState::START), defaultDepth_(4.0), V_(initialViewMatrix), boundingSphereRad_(1.0),
+ dollyFactor_(1.0), dollyInitialized_(false), elapsedTime_(0.0), hitGeometry_(false),
+ rotAngularVel_(0.0), rotInitialized_(false), rotLastTime_(0.0), showIcon_(false)
+{
+}
+
+UniCam::~UniCam()
+{
+}
+
+
+void UniCam::recalc_angular_vel() {
+ // update angular velocity
+ float cutoff = (float)elapsedTime_ - 0.2f; // look just at the last 0.2 secs
+ while ((rotAngularVelBuffer_.size()) && (rotAngularVelBuffer_[0].first < cutoff)) {
+ rotAngularVelBuffer_.erase(rotAngularVelBuffer_.begin());
+ }
+ rotAngularVel_ = 0.0;
+ if (rotAngularVelBuffer_.size()) {
+ for (int i=0; i<rotAngularVelBuffer_.size(); i++) {
+ rotAngularVel_ += rotAngularVelBuffer_[i].second;
+ }
+ rotAngularVel_ /= rotAngularVelBuffer_.size();
+ }
+ //std::cout << rotAngularVelBuffer_.size() << " " << rotAngularVel_ << std::endl;
+}
+
+
+void UniCam::OnButtonDown(const Point2 &mousePos, float mouseZ) {
+ if (state_ == UniCamState::START) {
+ initialClickPos_ = mousePos;
+ mouseLast_ = mousePos;
+ elapsedTime_ = 0.0;
+ rotInitialized_ = false;
+ dollyInitialized_ = false;
+
+ hitGeometry_ = (mouseZ < 1.0);
+ if (hitGeometry_) {
+ hitPoint_ = GfxMath::ScreenToWorld(V_, Pdraw_, mousePos, mouseZ);
+ }
+ else {
+ hitPoint_ = GfxMath::ScreenToDepthPlane(V_, Pdraw_, Point2(0,0), defaultDepth_);
+ }
+ showIcon_ = true;
+ state_ = UniCamState::PAN_DOLLY_ROT_DECISION;
+ }
+ else if (state_ == UniCamState::ROT_WAIT_FOR_SECOND_CLICK) {
+ // we have the second click now, and we will start the trackball rotate interaction
+ state_ = UniCamState::ROT;
+ }
+ else if (state_ == UniCamState::SPINNING) {
+ // this click is to "catch" the model, stopping it from spinning.
+ state_ = UniCamState::START;
+ }
+ else {
+ std::cerr << "UniCam::OnButtonDown() unexpected state." << std::endl;
+ }
+}
+
+void UniCam::OnDrag(const Point2 &mousePos) {
+ if (state_ == UniCamState::PAN_DOLLY_ROT_DECISION) {
+ const double panMovementThreshold = 0.01;
+ const double dollyMovementThreshold = 0.01;
+ if (fabs(mousePos[0] - initialClickPos_[0]) > panMovementThreshold) {
+ // already lots of horizontal movement, we can go right to pan
+ state_ = UniCamState::PAN;
+ showIcon_ = false;
+ }
+ else if (fabs(mousePos[1] - initialClickPos_[1]) > dollyMovementThreshold) {
+ // already lots of vertical movement, we can go right to dolly
+ state_ = UniCamState::DOLLY;
+ showIcon_ = false;
+ }
+ else if (elapsedTime_ > 1.0) {
+ // timeout, this was not a quick click to set a center of rotation,
+ // so there is no intent to rotate. instead we will be doing either
+ // pan or dolly.
+ state_ = UniCamState::PAN_DOLLY_DECISION;
+ showIcon_ = false;
+ }
+ }
+ else if (state_ == UniCamState::PAN_DOLLY_DECISION) {
+ const double panMovementThreshold = 0.01;
+ const double dollyMovementThreshold = 0.01;
+ if (fabs(mousePos[0] - initialClickPos_[0]) > panMovementThreshold) {
+ // lots of horizontal movement, go to pan
+ state_ = UniCamState::PAN;
+ }
+ else if (fabs(mousePos[1] - initialClickPos_[1]) > dollyMovementThreshold) {
+ // lots of vertical movement, go to dolly
+ state_ = UniCamState::DOLLY;
+ }
+ }
+ else if (state_ == UniCamState::PAN) {
+ Matrix4 camMat = V_.Inverse();
+ Point3 eye = camMat.ColumnToPoint3(3);
+ Vector3 look = -camMat.ColumnToVector3(2);
+ float depth = (hitPoint_ - eye).Dot(look);
+ Point3 pWorld1 = GfxMath::ScreenToDepthPlane(V_, Pdraw_, mouseLast_, depth);
+ Point3 pWorld2 = GfxMath::ScreenToDepthPlane(V_, Pdraw_, mousePos, depth);
+ V_ = V_ * Matrix4::Translation(pWorld2 - pWorld1);
+ }
+ else if (state_ == UniCamState::DOLLY) {
+ if (!dollyInitialized_) {
+ // Setup dollyFactor so that if you move the mouse to the bottom of the screen, the point
+ // you clicked on will be right on top of the camera.
+ Matrix4 camMat = V_.Inverse();
+ Point3 eye = camMat.ColumnToPoint3(3);
+ Vector3 look = -camMat.ColumnToVector3(2);
+ float depth = (hitPoint_ - eye).Dot(look);
+ float deltaYToBottom = initialClickPos_[1] + 1;
+ dollyFactor_ = depth / deltaYToBottom;
+ dollyInitialized_ = true;
+ }
+ Vector3 d(0, 0, -dollyFactor_ * (mousePos[1] - mouseLast_[1]));
+ V_ = Matrix4::Translation(d) * V_ ;
+ }
+ else if (state_ == UniCamState::ROT) {
+ if (!rotInitialized_) {
+ float depth = 0.0;
+ if (hitGeometry_) {
+ // if we hit some geometry, then make that the center of rotation
+ boundingSphereCtr_ = hitPoint_;
+ Matrix4 camMat = V_.Inverse();
+ Point3 eye = camMat.ColumnToPoint3(3);
+ Vector3 look = -camMat.ColumnToVector3(2);
+ depth = (hitPoint_ - eye).Dot(look);
+ }
+ else {
+ // if we did not hit any geometry, then center the bounding sphere in front of
+ // the camera at a distance that can be configured by the user.
+ boundingSphereCtr_ = GfxMath::ScreenToDepthPlane(V_, Pdraw_, Point2(0,0), defaultDepth_);
+ depth = defaultDepth_;
+ }
+
+ // determine the size of the bounding sphere by projecting a screen-space
+ // distance of 0.75 units to the depth of the sphere center
+ Point3 pWorld1 = GfxMath::ScreenToDepthPlane(V_, Pdraw_, Point2(0,0), depth);
+ Point3 pWorld2 = GfxMath::ScreenToDepthPlane(V_, Pdraw_, Point2(0.75,0), depth);
+ boundingSphereRad_ = (pWorld2-pWorld1).Length();
+
+ rotLastTime_ = elapsedTime_;
+ rotAngularVelBuffer_.clear();
+ rotInitialized_ = true;
+ }
+ else {
+ // Do a trackball rotation based on the mouse movement and the bounding sphere
+ // setup earlier.
+
+ Matrix4 camMat = V_.Inverse();
+ Point3 eye = camMat.ColumnToPoint3(3);
+
+ // last mouse pos
+ bool hit1 = false;
+ Point3 mouse3D1 = GfxMath::ScreenToNearPlane(V_, Pdraw_, mouseLast_);
+ Ray ray1(eye, mouse3D1 - eye);
+ float t1;
+ Point3 iPoint1;
+ if (ray1.IntersectSphere(boundingSphereCtr_, boundingSphereRad_, &t1, &iPoint1)) {
+ hit1 = true;
+ }
+
+ // current mouse pos
+ bool hit2 = false;
+ Point3 mouse3D2 = GfxMath::ScreenToNearPlane(V_, Pdraw_, mousePos);
+ Ray ray2(eye, mouse3D2 - eye);
+ float t2;
+ Point3 iPoint2;
+ if (ray2.IntersectSphere(boundingSphereCtr_, boundingSphereRad_, &t2, &iPoint2)) {
+ hit2 = true;
+ }
+ rotLastIPoint_ = iPoint2;
+
+ if (hit1 && hit2) {
+ Vector3 v1 = (iPoint1 - boundingSphereCtr_).ToUnit();
+ Vector3 v2 = (iPoint2 - boundingSphereCtr_).ToUnit();
+
+ rotAxis_ = v1.Cross(v2).ToUnit();
+ float angle = std::acos(v1.Dot(v2));
+
+ if (std::isfinite(angle)) {
+ Matrix4 R = Matrix4::Rotation(boundingSphereCtr_, rotAxis_, angle);
+ R = R.Orthonormal();
+ V_ = V_ * R;
+ //V_ = V_.orthonormal();
+
+ // add a sample to the angular vel vector
+ double dt = elapsedTime_ - rotLastTime_;
+ double avel = angle / dt;
+ if (std::isfinite(avel)) {
+ rotAngularVelBuffer_.push_back(std::make_pair(elapsedTime_, avel));
+ }
+ rotLastTime_ = elapsedTime_;
+ }
+ }
+
+ recalc_angular_vel();
+ }
+ }
+ else if (state_ == UniCamState::START) {
+ // picked up a little mouse movement after "catching" a spinning model
+ // nothing to do, just wait for the button up.
+ }
+ else {
+ std::cerr << "UniCam::OnDrag() unexpected state." << std::endl;
+ }
+ mouseLast_ = mousePos;
+}
+
+void UniCam::OnButtonUp(const Point2 &mousePos) {
+ if (state_ == UniCamState::PAN_DOLLY_ROT_DECISION) {
+ // here, we got a quick click of the mouse to indicate a center of rotation
+ // so we now go into a mode of waiting for a second click to start rotating
+ // around that point.
+ state_ = UniCamState::ROT_WAIT_FOR_SECOND_CLICK;
+ }
+ else if (state_ == UniCamState::ROT) {
+ showIcon_ = false;
+ // if we are leaving the rotation state and the angular velocity is
+ // greater than some thresold, then the user has "thrown" the model
+ // keep rotating the same way by entering the spinning state.
+
+ recalc_angular_vel();
+ //std::cout << "check for spin: " << n-start << " " << rotAngularVel_ << " " << avel2 << std::endl;
+
+ const float threshold = 0.2f;
+ if (std::fabs(rotAngularVel_) > threshold) {
+ state_ = UniCamState::SPINNING;
+ }
+ else {
+ state_ = UniCamState::START;
+ }
+ }
+ else {
+ showIcon_ = false;
+ // all other cases go back to the start state
+ state_ = UniCamState::START;
+ }
+}
+
+void UniCam::AdvanceAnimation(double dt) {
+ elapsedTime_ += dt;
+
+ if (state_ == UniCamState::SPINNING) {
+ double deltaT = elapsedTime_ - rotLastTime_;
+ rotLastTime_ = elapsedTime_;
+ double angle = (double)rotAngularVel_ * deltaT;
+ Matrix4 R = Matrix4::Rotation(boundingSphereCtr_, rotAxis_, (float)angle);
+ //R = R.orthonormal();
+ V_ = V_ * R;
+ }
+}
+
+
+void UniCam::Draw(const Matrix4 &projectionMatrix) {
+ Pdraw_ = projectionMatrix;
+
+ if (showIcon_) {
+ Matrix4 camMat = V_.Inverse();
+ Point3 eye = camMat.ColumnToPoint3(3);
+ Vector3 look = -camMat.ColumnToVector3(2);
+ float depth = (hitPoint_ - eye).Dot(look);
+ Point3 pWorld1 = GfxMath::ScreenToDepthPlane(V_, Pdraw_, Point2(0.f,0.f), depth);
+ Point3 pWorld2 = GfxMath::ScreenToDepthPlane(V_, Pdraw_, Point2(0.015f,0.f), depth);
+ float rad = (pWorld2 - pWorld1).Length();
+ Matrix4 M = Matrix4::Translation(hitPoint_ - Point3::Origin()) * Matrix4::Scale(Vector3(rad, rad, rad));
+ quickShapes_.DrawSphere(M, V_, Pdraw_, Color(0,0,0));
+ }
+}
+
+
+Matrix4 UniCam::view_matrix() {
+ return V_;
+}
+
+void UniCam::set_view_matrix(Matrix4 viewMatrix) {
+ V_ = viewMatrix;
+}
+
+void UniCam::set_default_depth(float d) {
+ defaultDepth_ = d;
+}
+
+Point3 UniCam::eye() {
+ Matrix4 camMat = V_.Inverse();
+ return camMat.ColumnToPoint3(3);
+}
+
+Vector3 UniCam::look() {
+ Matrix4 camMat = V_.Inverse();
+ return -camMat.ColumnToVector3(2);
+}
+
+
+
+
+} // end namespace
|