From 9d4fd4d6d496dd5aed8f7e3df4d49a63923d9760 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Wed, 2 Apr 2025 22:19:42 +0800 Subject: [PATCH] remove camutils --- .../native/src/camutils/Bookmark.cpp | 98 ----- .../src/camutils/FreeFlightManipulator.h | 206 ---------- .../native/src/camutils/Manipulator.cpp | 372 ------------------ .../native/src/camutils/MapManipulator.h | 218 ---------- .../native/src/camutils/OrbitManipulator.h | 201 ---------- 5 files changed, 1095 deletions(-) delete mode 100644 thermion_dart/native/src/camutils/Bookmark.cpp delete mode 100644 thermion_dart/native/src/camutils/FreeFlightManipulator.h delete mode 100644 thermion_dart/native/src/camutils/Manipulator.cpp delete mode 100644 thermion_dart/native/src/camutils/MapManipulator.h delete mode 100644 thermion_dart/native/src/camutils/OrbitManipulator.h diff --git a/thermion_dart/native/src/camutils/Bookmark.cpp b/thermion_dart/native/src/camutils/Bookmark.cpp deleted file mode 100644 index 9c16177b..00000000 --- a/thermion_dart/native/src/camutils/Bookmark.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include -#include - -using namespace filament::math; - -namespace filament { -namespace camutils { - -template -Bookmark Bookmark::interpolate(Bookmark a, Bookmark b, double t) { - Bookmark result; - using float3 = filament::math::vec3; - - if (a.mode == Mode::MAP) { - assert(b.mode == Mode::MAP); - const double rho = sqrt(2.0); - const double rho2 = 2, rho4 = 4; - const double ux0 = a.map.center.x, uy0 = a.map.center.y, w0 = a.map.extent; - const double ux1 = b.map.center.x, uy1 = b.map.center.y, w1 = b.map.extent; - const double dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = sqrt(d2); - const double b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2.0 * w0 * rho2 * d1); - const double b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2.0 * w1 * rho2 * d1); - const double r0 = log(sqrt(b0 * b0 + 1.0) - b0); - const double r1 = log(sqrt(b1 * b1 + 1) - b1); - const double dr = r1 - r0; - const int valid = !std::isnan(dr) && dr != 0; - const double S = (valid ? dr : log(w1 / w0)) / rho; - const double s = t * S; - - // This performs Van Wijk interpolation to animate between two waypoints on a map. - if (valid) { - const double coshr0 = cosh(r0); - const double u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0)); - Bookmark result; - result.map.center.x = ux0 + u * dx; - result.map.center.y = uy0 + u * dy; - result.map.extent = w0 * coshr0 / cosh(rho * s + r0); - return result; - } - - // For degenerate cases, fall back to a simplified interpolation method. - result.map.center.x = ux0 + t * dx; - result.map.center.y = uy0 + t * dy; - result.map.extent = w0 * exp(rho * s); - return result; -} - - assert(b.mode == Mode::ORBIT); - result.orbit.phi = lerp(a.orbit.phi, b.orbit.phi, FLOAT(t)); - result.orbit.theta = lerp(a.orbit.theta, b.orbit.theta, FLOAT(t)); - result.orbit.distance = lerp(a.orbit.distance, b.orbit.distance, FLOAT(t)); - result.orbit.pivot = lerp(a.orbit.pivot, b.orbit.pivot, float3(t)); - return result; -} - -// Uses the Van Wijk method to suggest a duration for animating between two waypoints on a map. -// This does not have units, so just use it as a multiplier. -template -double Bookmark::duration(Bookmark a, Bookmark b) { - assert(a.mode == Mode::ORBIT && b.mode == Mode::ORBIT); - const double rho = sqrt(2.0); - const double rho2 = 2, rho4 = 4; - const double ux0 = a.map.center.x, uy0 = a.map.center.y, w0 = a.map.extent; - const double ux1 = b.map.center.x, uy1 = b.map.center.y, w1 = b.map.extent; - const double dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = sqrt(d2); - const double b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2.0 * w0 * rho2 * d1); - const double b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2.0 * w1 * rho2 * d1); - const double r0 = log(sqrt(b0 * b0 + 1.0) - b0); - const double r1 = log(sqrt(b1 * b1 + 1) - b1); - const double dr = r1 - r0; - const int valid = !std::isnan(dr) && dr != 0; - const double S = (valid ? dr : log(w1 / w0)) / rho; - return fabs(S); -} - -template class Bookmark; - -} // namespace camutils -} // namespace filament diff --git a/thermion_dart/native/src/camutils/FreeFlightManipulator.h b/thermion_dart/native/src/camutils/FreeFlightManipulator.h deleted file mode 100644 index 1df4dd56..00000000 --- a/thermion_dart/native/src/camutils/FreeFlightManipulator.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef CAMUTILS_FREEFLIGHT_MANIPULATOR_H -#define CAMUTILS_FREEFLIGHT_MANIPULATOR_H - -#include - -#include -#include -#include -#include - -#include - -namespace filament { -namespace camutils { - -using namespace filament::math; - -template -class FreeFlightManipulator : public Manipulator { -public: - using vec2 = filament::math::vec2; - using vec3 = filament::math::vec3; - using vec4 = filament::math::vec4; - using Bookmark = filament::camutils::Bookmark; - using Base = Manipulator; - using Config = typename Base::Config; - - FreeFlightManipulator(Mode mode, const Config& props) : Base(mode, props) { - setProperties(props); - Base::mEye = Base::mProps.flightStartPosition; - const auto pitch = Base::mProps.flightStartPitch; - const auto yaw = Base::mProps.flightStartYaw; - mTargetEuler = {pitch, yaw}; - updateTarget(pitch, yaw); - } - - void setProperties(const Config& props) override { - Config resolved = props; - - if (resolved.flightPanSpeed == vec2(0, 0)) { - resolved.flightPanSpeed = vec2(0.01, 0.01); - } - if (resolved.flightMaxSpeed == 0.0) { - resolved.flightMaxSpeed = 10.0; - } - if (resolved.flightSpeedSteps == 0) { - resolved.flightSpeedSteps = 80; - } - - Base::setProperties(resolved); - } - - void updateTarget(FLOAT pitch, FLOAT yaw) { - Base::mTarget = Base::mEye + (mat3::eulerZYX(0, yaw, pitch) * vec3(0.0, 0.0, -1.0)); - } - - void grabBegin(int x, int y, bool strafe) override { - mGrabWin = {x, y}; - mGrabbing = true; - mGrabEuler = mTargetEuler; - } - - void grabUpdate(int x, int y) override { - if (!mGrabbing) { - return; - } - - const vec2 del = mGrabWin - vec2{x, y}; - - const auto& grabPitch = mGrabEuler.x; - const auto& grabYaw = mGrabEuler.y; - auto& pitch = mTargetEuler.x; - auto& yaw = mTargetEuler.y; - - constexpr double EPSILON = 0.001; - - auto panSpeed = Base::mProps.flightPanSpeed; - constexpr FLOAT minPitch = (-F_PI_2 + EPSILON); - constexpr FLOAT maxPitch = ( F_PI_2 - EPSILON); - pitch = clamp(grabPitch + del.y * -panSpeed.y, minPitch, maxPitch); - yaw = fmod(grabYaw + del.x * panSpeed.x, 2.0 * F_PI); - - updateTarget(pitch, yaw); - } - - void grabEnd() override { - mGrabbing = false; - } - - void keyDown(typename Base::Key key) override { - mKeyDown[(int) key] = true; - } - - void keyUp(typename Base::Key key) override { - mKeyDown[(int) key] = false; - } - - void scroll(int x, int y, FLOAT scrolldelta) override { - const FLOAT halfSpeedSteps = Base::mProps.flightSpeedSteps / 2; - mScrollWheel = clamp(mScrollWheel + scrolldelta, -halfSpeedSteps, halfSpeedSteps); - // Normalize the scroll position from -1 to 1 and calculate the move speed, in world - // units per second. - mScrollPositionNormalized = (mScrollWheel + halfSpeedSteps) / halfSpeedSteps - 1.0; - mMoveSpeed = pow(Base::mProps.flightMaxSpeed, mScrollPositionNormalized); - } - - void update(FLOAT deltaTime) override { - vec3 forceLocal { 0.0, 0.0, 0.0 }; - - if (mKeyDown[(int) Base::Key::FORWARD]) { - forceLocal += vec3{ 0.0, 0.0, -1.0 }; - } - if (mKeyDown[(int) Base::Key::LEFT]) { - forceLocal += vec3{ -1.0, 0.0, 0.0 }; - } - if (mKeyDown[(int) Base::Key::BACKWARD]) { - forceLocal += vec3{ 0.0, 0.0, 1.0 }; - } - if (mKeyDown[(int) Base::Key::RIGHT]) { - forceLocal += vec3{ 1.0, 0.0, 0.0 }; - } - - const mat4 orientation = mat4::lookAt(Base::mEye, Base::mTarget, Base::mProps.upVector); - vec3 forceWorld = (orientation * vec4{ forceLocal, 0.0f }).xyz; - - if (mKeyDown[(int) Base::Key::UP]) { - forceWorld += vec3{ 0.0, 1.0, 0.0 }; - } - if (mKeyDown[(int) Base::Key::DOWN]) { - forceWorld += vec3{ 0.0, -1.0, 0.0 }; - } - - forceWorld *= mMoveSpeed; - - const auto dampingFactor = Base::mProps.flightMoveDamping; - if (dampingFactor == 0.0) { - // Without damping, we simply treat the force as our velocity. - mEyeVelocity = forceWorld; - } else { - // The dampingFactor acts as "friction", which acts upon the camera in the direction - // opposite its velocity. - // Force is also multiplied by the dampingFactor, to "make up" for the friction. - // This ensures that the max velocity still approaches mMoveSpeed; - vec3 velocityDelta = (forceWorld - mEyeVelocity) * dampingFactor; - mEyeVelocity += velocityDelta * deltaTime; - } - - const vec3 positionDelta = mEyeVelocity * deltaTime; - - Base::mEye += positionDelta; - Base::mTarget += positionDelta; - } - - Bookmark getCurrentBookmark() const override { - Bookmark bookmark; - bookmark.flight.position = Base::mEye; - bookmark.flight.pitch = mTargetEuler.x; - bookmark.flight.yaw = mTargetEuler.y; - return bookmark; - } - - Bookmark getHomeBookmark() const override { - Bookmark bookmark; - bookmark.flight.position = Base::mProps.flightStartPosition; - bookmark.flight.pitch = Base::mProps.flightStartPitch; - bookmark.flight.yaw = Base::mProps.flightStartYaw; - return bookmark; - } - - void jumpToBookmark(const Bookmark& bookmark) override { - Base::mEye = bookmark.flight.position; - updateTarget(bookmark.flight.pitch, bookmark.flight.yaw); - } - -private: - vec2 mGrabWin; - vec2 mTargetEuler; // (pitch, yaw) - vec2 mGrabEuler; // (pitch, yaw) - bool mKeyDown[(int) Base::Key::COUNT] = {false}; - bool mGrabbing = false; - FLOAT mScrollWheel = 0.0f; - FLOAT mScrollPositionNormalized = 0.0f; - FLOAT mMoveSpeed = 1.0f; - vec3 mEyeVelocity; -}; - -} // namespace camutils -} // namespace filament - -#endif /* CAMUTILS_FREEFLIGHT_MANIPULATOR_H */ diff --git a/thermion_dart/native/src/camutils/Manipulator.cpp b/thermion_dart/native/src/camutils/Manipulator.cpp deleted file mode 100644 index 7f92bcfb..00000000 --- a/thermion_dart/native/src/camutils/Manipulator.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include - -#include "FreeFlightManipulator.h" -#include "MapManipulator.h" -#include "OrbitManipulator.h" - -using namespace filament::math; - -namespace filament -{ - namespace camutils - { - - template - typename Manipulator::Builder &Manipulator::Builder::viewport(int width, int height) - { - details.viewport[0] = width; - details.viewport[1] = height; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::targetPosition(FLOAT x, FLOAT y, FLOAT z) - { - details.targetPosition = {x, y, z}; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::upVector(FLOAT x, FLOAT y, FLOAT z) - { - details.upVector = {x, y, z}; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::zoomSpeed(FLOAT val) - { - details.zoomSpeed = val; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::orbitHomePosition(FLOAT x, FLOAT y, FLOAT z) - { - details.orbitHomePosition = {x, y, z}; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::orbitSpeed(FLOAT x, FLOAT y) - { - details.orbitSpeed = {x, y}; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::fovDirection(Fov fov) - { - details.fovDirection = fov; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::fovDegrees(FLOAT degrees) - { - details.fovDegrees = degrees; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::farPlane(FLOAT distance) - { - details.farPlane = distance; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::mapExtent(FLOAT worldWidth, FLOAT worldHeight) - { - details.mapExtent = {worldWidth, worldHeight}; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::mapMinDistance(FLOAT mindist) - { - details.mapMinDistance = mindist; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::flightStartPosition(FLOAT x, FLOAT y, FLOAT z) - { - details.flightStartPosition = {x, y, z}; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::flightStartOrientation(FLOAT pitch, FLOAT yaw) - { - details.flightStartPitch = pitch; - details.flightStartYaw = yaw; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::flightMaxMoveSpeed(FLOAT maxSpeed) - { - details.flightMaxSpeed = maxSpeed; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::flightSpeedSteps(int steps) - { - details.flightSpeedSteps = steps; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::flightPanSpeed(FLOAT x, FLOAT y) - { - details.flightPanSpeed = {x, y}; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::flightMoveDamping(FLOAT damping) - { - details.flightMoveDamping = damping; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::groundPlane(FLOAT a, FLOAT b, FLOAT c, FLOAT d) - { - details.groundPlane = {a, b, c, d}; - return *this; - } - - template - typename Manipulator::Builder &Manipulator::Builder::raycastCallback(RayCallback cb, void *userdata) - { - details.raycastCallback = cb; - details.raycastUserdata = userdata; - return *this; - } - - template - Manipulator *Manipulator::Builder::build(Mode mode) - { - switch (mode) - { - case Mode::FREE_FLIGHT: - return new FreeFlightManipulator(mode, details); - case Mode::MAP: - return new MapManipulator(mode, details); - case Mode::ORBIT: - return new OrbitManipulator(mode, details); - } - // just to make MSVC happy - return new OrbitManipulator(mode, details); - } - - template - Manipulator::Manipulator(Mode mode, const Config &props) : mMode(mode) - { - setProperties(props); - } - - template - void Manipulator::setProperties(const Config &props) - { - mProps = props; - - if (mProps.zoomSpeed == FLOAT(0)) - { - mProps.zoomSpeed = 0.01; - } - - if (mProps.upVector == vec3(0)) - { - mProps.upVector = vec3(0, 1, 0); - } - - if (mProps.fovDegrees == FLOAT(0)) - { - mProps.fovDegrees = 33; - } - - if (mProps.farPlane == FLOAT(0)) - { - mProps.farPlane = 5000; - } - - if (mProps.mapExtent == vec2(0)) - { - mProps.mapExtent = vec2(512); - } - } - - template - void Manipulator::setViewport(int width, int height) - { - Config props = mProps; - props.viewport[0] = width; - props.viewport[1] = height; - setProperties(props); - } - - template - void Manipulator::getLookAt(vec3 *eyePosition, vec3 *targetPosition, vec3 *upward) const - { - *targetPosition = mTarget; - *eyePosition = mEye; - const vec3 gaze = normalize(mTarget - mEye); - const vec3 right = cross(gaze, mProps.upVector); - *upward = cross(right, gaze); - } - - template - static bool raycastPlane(const filament::math::vec3 &origin, - const filament::math::vec3 &dir, FLOAT *t, void *userdata) - { - using vec3 = filament::math::vec3; - using vec4 = filament::math::vec4; - auto props = (const typename Manipulator::Config *)userdata; - const vec4 plane = props->groundPlane; - const vec3 n = vec3(plane[0], plane[1], plane[2]); - const vec3 p0 = n * plane[3]; - const FLOAT denom = -dot(n, dir); - if (denom > 1e-6) - { - const vec3 p0l0 = p0 - origin; - *t = dot(p0l0, n) / -denom; - return *t >= 0; - } - return false; - } - - template - void Manipulator::getRay(int x, int y, vec3 *porigin, vec3 *pdir) const - { - const vec3 gaze = normalize(mTarget - mEye); - const vec3 right = normalize(cross(gaze, mProps.upVector)); - const vec3 upward = cross(right, gaze); - const FLOAT width = mProps.viewport[0]; - const FLOAT height = mProps.viewport[1]; - const FLOAT fov = mProps.fovDegrees * F_PI / 180.0; - - // Remap the grid coordinate into [-1, +1] and shift it to the pixel center. - const FLOAT u = 2.0 * (0.5 + x) / width - 1.0; - const FLOAT v = 2.0 * (0.5 + y) / height - 1.0; - - // Compute the tangent of the field-of-view angle as well as the aspect ratio. - const FLOAT tangent = tan(fov / 2.0); - const FLOAT aspect = width / height; - - // Adjust the gaze so it goes through the pixel of interest rather than the grid center. - vec3 dir = gaze; - if (mProps.fovDirection == Fov::VERTICAL) - { - dir += right * tangent * u * aspect; - dir += upward * tangent * v; - } - else - { - dir += right * tangent * u; - dir += upward * tangent * v / aspect; - } - dir = normalize(dir); - - *porigin = mEye; - *pdir = dir; - } - - template - bool Manipulator::raycast(int x, int y, vec3 *result) const - { - vec3 origin, dir; - getRay(x, y, &origin, &dir); - - // Choose either the user's callback function or the plane intersector. - auto callback = mProps.raycastCallback; - auto fallback = raycastPlane; - void *userdata = mProps.raycastUserdata; - if (!callback) - { - callback = fallback; - userdata = (void *)&mProps; - } - - // If the ray misses, then try the fallback function. - FLOAT t; - if (!callback(mEye, dir, &t, userdata)) - { - if (callback == fallback || !fallback(mEye, dir, &t, (void *)&mProps)) - { - return false; - } - } - - *result = mEye + dir * t; - return true; - } - - template - filament::math::vec3 Manipulator::raycastFarPlane(int x, int y) const - { - const filament::math::vec3 gaze = normalize(mTarget - mEye); - const vec3 right = cross(gaze, mProps.upVector); - const vec3 upward = cross(right, gaze); - const FLOAT width = mProps.viewport[0]; - const FLOAT height = mProps.viewport[1]; - const FLOAT fov = mProps.fovDegrees * math::F_PI / 180.0; - - // Remap the grid coordinate into [-1, +1] and shift it to the pixel center. - const FLOAT u = 2.0 * (0.5 + x) / width - 1.0; - const FLOAT v = 2.0 * (0.5 + y) / height - 1.0; - - // Compute the tangent of the field-of-view angle as well as the aspect ratio. - const FLOAT tangent = tan(fov / 2.0); - const FLOAT aspect = width / height; - - // Adjust the gaze so it goes through the pixel of interest rather than the grid center. - vec3 dir = gaze; - if (mProps.fovDirection == Fov::VERTICAL) - { - dir += right * tangent * u * aspect; - dir += upward * tangent * v; - } - else - { - dir += right * tangent * u; - dir += upward * tangent * v / aspect; - } - return mEye + dir * mProps.farPlane; - } - - template - void Manipulator::keyDown(Manipulator::Key key) {} - - template - void Manipulator::keyUp(Manipulator::Key key) {} - - template - void Manipulator::update(FLOAT deltaTime) {} - - template class Manipulator; - template class Manipulator; - - } // namespace camutils -} // namespace filament diff --git a/thermion_dart/native/src/camutils/MapManipulator.h b/thermion_dart/native/src/camutils/MapManipulator.h deleted file mode 100644 index f3d40848..00000000 --- a/thermion_dart/native/src/camutils/MapManipulator.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef CAMUTILS_MAP_MANIPULATOR_H -#define CAMUTILS_MAP_MANIPULATOR_H - -#include - -#include - -#include - -namespace filament -{ - namespace camutils - { - - template - class MapManipulator : public Manipulator - { - public: - using vec2 = math::vec2; - using vec3 = math::vec3; - using vec4 = math::vec4; - using Bookmark = filament::camutils::Bookmark; - using Base = Manipulator; - using Config = typename Manipulator::Config; - - MapManipulator(Mode mode, const Config &props) : Manipulator(mode, props) - { - const FLOAT width = Base::mProps.mapExtent.x; - const FLOAT height = Base::mProps.mapExtent.y; - const bool horiz = Base::mProps.fovDirection == Fov::HORIZONTAL; - const vec3 targetToEye = Base::mProps.groundPlane.xyz; - const FLOAT halfExtent = (horiz ? width : height) / 2.0; - const FLOAT fov = Base::mProps.fovDegrees * math::F_PI / 180.0; - const FLOAT distance = halfExtent / tan(fov / 2.0); - Base::mTarget = Base::mProps.targetPosition; - Base::mEye = Base::mTarget + distance * targetToEye; - } - - void grabBegin(int x, int y, bool strafe) override - { - if (strafe || !Base::raycast(x, y, &mGrabScene)) - { - return; - } - mGrabFar = Base::raycastFarPlane(x, y); - mGrabEye = Base::mEye; - mGrabTarget = Base::mTarget; - mGrabbing = true; - } - - void grabUpdate(int x, int y) override - { - if (mGrabbing) - { - const FLOAT ulen = distance(mGrabScene, mGrabEye); - const FLOAT vlen = distance(mGrabFar, mGrabScene); - const vec3 translation = (mGrabFar - Base::raycastFarPlane(x, y)) * ulen / vlen; - const vec3 eyePosition = mGrabEye + translation; - const vec3 targetPosition = mGrabTarget + translation; - moveWithConstraints(eyePosition, targetPosition); - } - } - - void grabEnd() override - { - mGrabbing = false; - } - - void scroll(int x, int y, FLOAT scrolldelta) override - { - vec3 grabScene; - if (!Base::raycast(x, y, &grabScene)) - { - return; - } - - // Find the direction of travel for the dolly. We do not normalize since it - // is desirable to move faster when further away from the targetPosition. - vec3 u = grabScene - Base::mEye; - - // Prevent getting stuck when zooming in. - if (scrolldelta < 0) - { - const FLOAT distanceToSurface = length(u); - if (distanceToSurface < Base::mProps.zoomSpeed) - { - return; - } - } - - u *= -scrolldelta * Base::mProps.zoomSpeed; - - const vec3 eyePosition = Base::mEye + u; - const vec3 targetPosition = Base::mTarget + u; - moveWithConstraints(eyePosition, targetPosition); - } - - Bookmark getCurrentBookmark() const override - { - const vec3 dir = normalize(Base::mTarget - Base::mEye); - - FLOAT distance; - raycastPlane(Base::mEye, dir, &distance); - - const FLOAT fov = Base::mProps.fovDegrees * math::F_PI / 180.0; - const FLOAT halfExtent = distance * tan(fov / 2.0); - - vec3 targetPosition = Base::mEye + dir * distance; - - const vec3 targetToEye = Base::mProps.groundPlane.xyz; - const vec3 uvec = cross(Base::mProps.upVector, targetToEye); - const vec3 vvec = cross(targetToEye, uvec); - const vec3 centerToTarget = targetPosition - Base::mProps.targetPosition; - - Bookmark bookmark; - bookmark.mode = Mode::MAP; - bookmark.map.extent = halfExtent * 2.0; - bookmark.map.center.x = dot(uvec, centerToTarget); - bookmark.map.center.y = dot(vvec, centerToTarget); - - bookmark.orbit.theta = 0; - bookmark.orbit.phi = 0; - bookmark.orbit.pivot = Base::mProps.targetPosition + - uvec * bookmark.map.center.x + - vvec * bookmark.map.center.y; - bookmark.orbit.distance = halfExtent / tan(fov / 2.0); - - return bookmark; - } - - Bookmark getHomeBookmark() const override - { - const FLOAT fov = Base::mProps.fovDegrees * math::F_PI / 180.0; - const FLOAT width = Base::mProps.mapExtent.x; - const FLOAT height = Base::mProps.mapExtent.y; - const bool horiz = Base::mProps.fovDirection == Fov::HORIZONTAL; - - Bookmark bookmark; - bookmark.mode = Mode::MAP; - bookmark.map.extent = horiz ? width : height; - bookmark.map.center.x = 0; - bookmark.map.center.y = 0; - - bookmark.orbit.theta = 0; - bookmark.orbit.phi = 0; - bookmark.orbit.pivot = Base::mTarget; - bookmark.orbit.distance = 0.5 * bookmark.map.extent / tan(fov / 2.0); - - // TODO: Add optional boundary constraints here. - - return bookmark; - } - - void jumpToBookmark(const Bookmark &bookmark) override - { - const vec3 targetToEye = Base::mProps.groundPlane.xyz; - const FLOAT halfExtent = bookmark.map.extent / 2.0; - const FLOAT fov = Base::mProps.fovDegrees * math::F_PI / 180.0; - const FLOAT distance = halfExtent / tan(fov / 2.0); - vec3 uvec = cross(Base::mProps.upVector, targetToEye); - vec3 vvec = cross(targetToEye, uvec); - uvec = normalize(uvec) * bookmark.map.center.x; - vvec = normalize(vvec) * bookmark.map.center.y; - Base::mTarget = Base::mProps.targetPosition + uvec + vvec; - Base::mEye = Base::mTarget + distance * targetToEye; - } - - private: - bool raycastPlane(const vec3 &origin, const vec3 &dir, FLOAT *t) const - { - const vec4 plane = Base::mProps.groundPlane; - const vec3 n = vec3(plane[0], plane[1], plane[2]); - const vec3 p0 = n * plane[3]; - const FLOAT denom = -dot(n, dir); - if (denom > 1e-6) - { - const vec3 p0l0 = p0 - origin; - *t = dot(p0l0, n) / -denom; - return *t >= 0; - } - return false; - } - - void moveWithConstraints(vec3 eye, vec3 targetPosition) - { - Base::mEye = eye; - Base::mTarget = targetPosition; - // TODO: Add optional boundary constraints here. - } - - private: - bool mGrabbing = false; - vec3 mGrabScene; - vec3 mGrabFar; - vec3 mGrabEye; - vec3 mGrabTarget; - }; - - } // namespace camutils -} // namespace filament - -#endif /* CAMUTILS_MAP_MANIPULATOR_H */ diff --git a/thermion_dart/native/src/camutils/OrbitManipulator.h b/thermion_dart/native/src/camutils/OrbitManipulator.h deleted file mode 100644 index 54e325cc..00000000 --- a/thermion_dart/native/src/camutils/OrbitManipulator.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef CAMUTILS_ORBIT_MANIPULATOR_H -#define CAMUTILS_ORBIT_MANIPULATOR_H - -#include - -#include - -#define MAX_PHI (F_PI / 2.0 - 0.001) - -namespace filament { -namespace camutils { - -using namespace filament::math; - -template -class OrbitManipulator : public Manipulator { -public: - using vec2 = filament::math::vec2; - using vec3 = filament::math::vec3; - using vec4 = filament::math::vec4; - using Bookmark = filament::camutils::Bookmark; - using Base = Manipulator; - using Config = typename Base::Config; - - enum GrabState { INACTIVE, ORBITING, PANNING }; - - OrbitManipulator(Mode mode, const Config& props) : Base(mode, props) { - setProperties(props); - Base::mEye = Base::mProps.orbitHomePosition; - mPivot = Base::mTarget = Base::mProps.targetPosition; - } - - void setProperties(const Config& props) override { - Config resolved = props; - - if (resolved.orbitHomePosition == vec3(0)) { - resolved.orbitHomePosition = vec3(0, 0, 1); - } - - if (resolved.orbitSpeed == vec2(0)) { - resolved.orbitSpeed = vec2(0.01); - } - - // By default, place the ground plane so that it aligns with the targetPosition position. - // This is used only when PANNING. - if (resolved.groundPlane == vec4(0)) { - const FLOAT d = length(resolved.targetPosition); - const vec3 n = normalize(resolved.orbitHomePosition - resolved.targetPosition); - resolved.groundPlane = vec4(n, -d); - } - - Base::setProperties(resolved); - } - - void grabBegin(int x, int y, bool strafe) override { - mGrabState = strafe ? PANNING : ORBITING; - mGrabPivot = mPivot; - mGrabEye = Base::mEye; - mGrabTarget = Base::mTarget; - mGrabBookmark = getCurrentBookmark(); - mGrabWinX = x; - mGrabWinY = y; - mGrabFar = Base::raycastFarPlane(x, y); - Base::raycast(x, y, &mGrabScene); - } - - void grabUpdate(int x, int y) override { - const int delx = mGrabWinX - x; - const int dely = mGrabWinY - y; - - if (mGrabState == ORBITING) { - Bookmark bookmark = getCurrentBookmark(); - - const FLOAT theta = delx * Base::mProps.orbitSpeed.x; - const FLOAT phi = dely * Base::mProps.orbitSpeed.y; - const FLOAT maxPhi = MAX_PHI; - - bookmark.orbit.phi = clamp(mGrabBookmark.orbit.phi + phi, -maxPhi, +maxPhi); - bookmark.orbit.theta = mGrabBookmark.orbit.theta + theta; - - jumpToBookmark(bookmark); - } - - if (mGrabState == PANNING) { - const FLOAT ulen = distance(mGrabScene, mGrabEye); - const FLOAT vlen = distance(mGrabFar, mGrabScene); - const vec3 translation = (mGrabFar - Base::raycastFarPlane(x, y)) * ulen / vlen; - mPivot = mGrabPivot + translation; - Base::mEye = mGrabEye + translation; - Base::mTarget = mGrabTarget + translation; - } - } - - void grabEnd() override { - mGrabState = INACTIVE; - } - - void scroll(int x, int y, FLOAT scrolldelta) override { - const vec3 gaze = normalize(Base::mTarget - Base::mEye); - const vec3 movement = gaze * Base::mProps.zoomSpeed * -scrolldelta; - const vec3 v0 = mPivot - Base::mEye; - Base::mEye += movement; - Base::mTarget += movement; - const vec3 v1 = mPivot - Base::mEye; - - // Check if the camera has moved past the point of interest. - if (dot(v0, v1) < 0) { - mFlipped = !mFlipped; - } - } - - Bookmark getCurrentBookmark() const override { - Bookmark bookmark; - bookmark.mode = Mode::ORBIT; - const vec3 pivotToEye = Base::mEye - mPivot; - const FLOAT d = length(pivotToEye); - const FLOAT x = pivotToEye.x / d; - const FLOAT y = pivotToEye.y / d; - const FLOAT z = pivotToEye.z / d; - - bookmark.orbit.phi = asin(y); - bookmark.orbit.theta = atan2(x, z); - bookmark.orbit.distance = mFlipped ? -d : d; - bookmark.orbit.pivot = mPivot; - - const FLOAT fov = Base::mProps.fovDegrees * math::F_PI / 180.0; - const FLOAT halfExtent = d * tan(fov / 2.0); - const vec3 targetToEye = Base::mProps.groundPlane.xyz; - const vec3 uvec = cross(Base::mProps.upVector, targetToEye); - const vec3 vvec = cross(targetToEye, uvec); - const vec3 centerToTarget = mPivot - Base::mProps.targetPosition; - - bookmark.map.extent = halfExtent * 2; - bookmark.map.center.x = dot(uvec, centerToTarget); - bookmark.map.center.y = dot(vvec, centerToTarget); - - return bookmark; - } - - Bookmark getHomeBookmark() const override { - Bookmark bookmark; - bookmark.mode = Mode::ORBIT; - bookmark.orbit.phi = FLOAT(0); - bookmark.orbit.theta = FLOAT(0); - bookmark.orbit.pivot = Base::mProps.targetPosition; - bookmark.orbit.distance = distance(Base::mProps.targetPosition, Base::mProps.orbitHomePosition); - - const FLOAT fov = Base::mProps.fovDegrees * math::F_PI / 180.0; - const FLOAT halfExtent = bookmark.orbit.distance * tan(fov / 2.0); - - bookmark.map.extent = halfExtent * 2; - bookmark.map.center.x = 0; - bookmark.map.center.y = 0; - - return bookmark; - } - - void jumpToBookmark(const Bookmark& bookmark) override { - mPivot = bookmark.orbit.pivot; - const FLOAT x = sin(bookmark.orbit.theta) * cos(bookmark.orbit.phi); - const FLOAT y = sin(bookmark.orbit.phi); - const FLOAT z = cos(bookmark.orbit.theta) * cos(bookmark.orbit.phi); - Base::mEye = mPivot + vec3(x, y, z) * abs(bookmark.orbit.distance); - mFlipped = bookmark.orbit.distance < 0; - Base::mTarget = Base::mEye + vec3(x, y, z) * (mFlipped ? 1.0 : -1.0); - } - -private: - GrabState mGrabState = INACTIVE; - bool mFlipped = false; - vec3 mGrabPivot; - vec3 mGrabScene; - vec3 mGrabFar; - vec3 mGrabEye; - vec3 mGrabTarget; - Bookmark mGrabBookmark; - int mGrabWinX; - int mGrabWinY; - vec3 mPivot; -}; - -} // namespace camutils -} // namespace filament - -#endif /* CAMUTILS_ORBIT_MANIPULATOR_H */