From 7297bc5c177f6019237e058ec8ede9cf7f4ac40f Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 3 Aug 2014 18:33:09 -0700 Subject: [PATCH] Add Camera::LookAt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is identical to the POV-Ray look_at keyword for cameras. In fact, I stole the code almost directly from them… It's super handy for panning and tilting the camera towards a particular point, and saves me having to do dubiously accurate direction vector calculations by hand. I still need to figure out what exactly this math is doing. --- src/camera.cc | 25 +++++++++++++++++++++++++ src/camera.h | 2 ++ src/yaml/cameraParser.cc | 23 +++++++++++++++++++++++ src/yaml/cameraParser.hh | 2 ++ 4 files changed, 52 insertions(+) diff --git a/src/camera.cc b/src/camera.cc index 3d1b54e..de53ecf 100644 --- a/src/camera.cc +++ b/src/camera.cc @@ -93,6 +93,31 @@ Camera::SetUp(const Vector3& up) mUp = up; } + +void +Camera::LookAt(const Vector3& pt) +{ + const Double directionLength = mDirection.length(); + const Double rightLength = mRight.length(); + const Double upLength = mUp.length(); + /* TODO: What does this actually do? */ + const Double handedness = mUp.cross(mDirection).dot(mRight); + + mDirection = (pt - mOrigin).normalize(); + /* TODO: Check for zero length direction vector. */ + + mRight = Vector3::Y.cross(mDirection).normalize(); + mUp = mDirection.cross(mRight); + mDirection *= directionLength; + + if (handedness > 0.0) { + mRight *= rightLength; + } else { + mRight *= -rightLength; + } + mUp *= upLength; +} + #pragma mark - Perspective Camera PerspectiveCamera::PerspectiveCamera() diff --git a/src/camera.h b/src/camera.h index 6adf856..a18e461 100644 --- a/src/camera.h +++ b/src/camera.h @@ -35,6 +35,8 @@ struct Camera const Vector3& GetUp() const; void SetUp(const Vector3& up); + void LookAt(const Vector3& pt); + virtual Ray compute_primary_ray(const int x, const int width, const int y, const int height) const = 0; diff --git a/src/yaml/cameraParser.cc b/src/yaml/cameraParser.cc index 9b9086e..2ae49fa 100644 --- a/src/yaml/cameraParser.cc +++ b/src/yaml/cameraParser.cc @@ -32,6 +32,7 @@ CameraParser::HandleKeyEvent(const std::string& key) { static const std::map sSections = { {"direction", DirectionSection}, + {"lookAt", LookAtSection}, {"origin", OriginSection}, {"right", RightSection}, {"type", TypeSection}, @@ -54,6 +55,9 @@ CameraParser::HandleValueEvent(yaml_event_t& event) case DirectionSection: HandleDirectionEvent(event); break; + case LookAtSection: + HandleLookAtEvent(event); + break; case OriginSection: HandleOriginEvent(event); break; @@ -92,6 +96,25 @@ CameraParser::HandleDirectionEvent(yaml_event_t& event) } +void +CameraParser::HandleLookAtEvent(yaml_event_t& event) +{ + if (event.type != YAML_SEQUENCE_START_EVENT) { + /* TODO: Clean this up. */ + assert(event.type != YAML_SEQUENCE_START_EVENT); + return; + } + + auto onDone = [this](Vector3 lookAt) { + mCamera->LookAt(lookAt); + mSection = NoSection; + SetShouldExpectKey(true); + }; + + GetParsers().push(new Vector3Parser(GetScene(), GetParsers(), onDone)); +} + + void CameraParser::HandleOriginEvent(yaml_event_t& event) { diff --git a/src/yaml/cameraParser.hh b/src/yaml/cameraParser.hh index 12e0acd..6724b16 100644 --- a/src/yaml/cameraParser.hh +++ b/src/yaml/cameraParser.hh @@ -28,6 +28,7 @@ private: enum Section { NoSection, DirectionSection, + LookAtSection, OriginSection, RightSection, TypeSection, @@ -40,6 +41,7 @@ private: }; void HandleDirectionEvent(yaml_event_t& event); + void HandleLookAtEvent(yaml_event_t& event); void HandleOriginEvent(yaml_event_t& event); void HandleRightEvent(yaml_event_t& event); void HandleTypeEvent(yaml_event_t& event);