remove camutils
This commit is contained in:
@@ -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 <camutils/Bookmark.h>
|
||||
#include <camutils/Manipulator.h>
|
||||
|
||||
#include <math/scalar.h>
|
||||
#include <math/vec3.h>
|
||||
|
||||
using namespace filament::math;
|
||||
|
||||
namespace filament {
|
||||
namespace camutils {
|
||||
|
||||
template <typename FLOAT>
|
||||
Bookmark<FLOAT> Bookmark<FLOAT>::interpolate(Bookmark<FLOAT> a, Bookmark<FLOAT> b, double t) {
|
||||
Bookmark<FLOAT> result;
|
||||
using float3 = filament::math::vec3<FLOAT>;
|
||||
|
||||
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<FLOAT> 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 <typename FLOAT>
|
||||
double Bookmark<FLOAT>::duration(Bookmark<FLOAT> a, Bookmark<FLOAT> 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<float>;
|
||||
|
||||
} // namespace camutils
|
||||
} // namespace filament
|
||||
@@ -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 <camutils/Manipulator.h>
|
||||
|
||||
#include <math/scalar.h>
|
||||
#include <math/mat3.h>
|
||||
#include <math/mat4.h>
|
||||
#include <math/quat.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace filament {
|
||||
namespace camutils {
|
||||
|
||||
using namespace filament::math;
|
||||
|
||||
template<typename FLOAT>
|
||||
class FreeFlightManipulator : public Manipulator<FLOAT> {
|
||||
public:
|
||||
using vec2 = filament::math::vec2<FLOAT>;
|
||||
using vec3 = filament::math::vec3<FLOAT>;
|
||||
using vec4 = filament::math::vec4<FLOAT>;
|
||||
using Bookmark = filament::camutils::Bookmark<FLOAT>;
|
||||
using Base = Manipulator<FLOAT>;
|
||||
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 */
|
||||
@@ -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 <math/scalar.h>
|
||||
|
||||
#include <camutils/Manipulator.h>
|
||||
|
||||
#include "FreeFlightManipulator.h"
|
||||
#include "MapManipulator.h"
|
||||
#include "OrbitManipulator.h"
|
||||
|
||||
using namespace filament::math;
|
||||
|
||||
namespace filament
|
||||
{
|
||||
namespace camutils
|
||||
{
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::viewport(int width, int height)
|
||||
{
|
||||
details.viewport[0] = width;
|
||||
details.viewport[1] = height;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::targetPosition(FLOAT x, FLOAT y, FLOAT z)
|
||||
{
|
||||
details.targetPosition = {x, y, z};
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::upVector(FLOAT x, FLOAT y, FLOAT z)
|
||||
{
|
||||
details.upVector = {x, y, z};
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::zoomSpeed(FLOAT val)
|
||||
{
|
||||
details.zoomSpeed = val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::orbitHomePosition(FLOAT x, FLOAT y, FLOAT z)
|
||||
{
|
||||
details.orbitHomePosition = {x, y, z};
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::orbitSpeed(FLOAT x, FLOAT y)
|
||||
{
|
||||
details.orbitSpeed = {x, y};
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::fovDirection(Fov fov)
|
||||
{
|
||||
details.fovDirection = fov;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::fovDegrees(FLOAT degrees)
|
||||
{
|
||||
details.fovDegrees = degrees;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::farPlane(FLOAT distance)
|
||||
{
|
||||
details.farPlane = distance;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::mapExtent(FLOAT worldWidth, FLOAT worldHeight)
|
||||
{
|
||||
details.mapExtent = {worldWidth, worldHeight};
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::mapMinDistance(FLOAT mindist)
|
||||
{
|
||||
details.mapMinDistance = mindist;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::flightStartPosition(FLOAT x, FLOAT y, FLOAT z)
|
||||
{
|
||||
details.flightStartPosition = {x, y, z};
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::flightStartOrientation(FLOAT pitch, FLOAT yaw)
|
||||
{
|
||||
details.flightStartPitch = pitch;
|
||||
details.flightStartYaw = yaw;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::flightMaxMoveSpeed(FLOAT maxSpeed)
|
||||
{
|
||||
details.flightMaxSpeed = maxSpeed;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::flightSpeedSteps(int steps)
|
||||
{
|
||||
details.flightSpeedSteps = steps;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::flightPanSpeed(FLOAT x, FLOAT y)
|
||||
{
|
||||
details.flightPanSpeed = {x, y};
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::flightMoveDamping(FLOAT damping)
|
||||
{
|
||||
details.flightMoveDamping = damping;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::groundPlane(FLOAT a, FLOAT b, FLOAT c, FLOAT d)
|
||||
{
|
||||
details.groundPlane = {a, b, c, d};
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
typename Manipulator<FLOAT>::Builder &Manipulator<FLOAT>::Builder::raycastCallback(RayCallback cb, void *userdata)
|
||||
{
|
||||
details.raycastCallback = cb;
|
||||
details.raycastUserdata = userdata;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
Manipulator<FLOAT> *Manipulator<FLOAT>::Builder::build(Mode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case Mode::FREE_FLIGHT:
|
||||
return new FreeFlightManipulator<FLOAT>(mode, details);
|
||||
case Mode::MAP:
|
||||
return new MapManipulator<FLOAT>(mode, details);
|
||||
case Mode::ORBIT:
|
||||
return new OrbitManipulator<FLOAT>(mode, details);
|
||||
}
|
||||
// just to make MSVC happy
|
||||
return new OrbitManipulator<FLOAT>(mode, details);
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
Manipulator<FLOAT>::Manipulator(Mode mode, const Config &props) : mMode(mode)
|
||||
{
|
||||
setProperties(props);
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
void Manipulator<FLOAT>::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 <typename FLOAT>
|
||||
void Manipulator<FLOAT>::setViewport(int width, int height)
|
||||
{
|
||||
Config props = mProps;
|
||||
props.viewport[0] = width;
|
||||
props.viewport[1] = height;
|
||||
setProperties(props);
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
void Manipulator<FLOAT>::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 <typename FLOAT>
|
||||
static bool raycastPlane(const filament::math::vec3<FLOAT> &origin,
|
||||
const filament::math::vec3<FLOAT> &dir, FLOAT *t, void *userdata)
|
||||
{
|
||||
using vec3 = filament::math::vec3<FLOAT>;
|
||||
using vec4 = filament::math::vec4<FLOAT>;
|
||||
auto props = (const typename Manipulator<FLOAT>::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 <typename FLOAT>
|
||||
void Manipulator<FLOAT>::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 <typename FLOAT>
|
||||
bool Manipulator<FLOAT>::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<FLOAT>;
|
||||
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 <typename FLOAT>
|
||||
filament::math::vec3<FLOAT> Manipulator<FLOAT>::raycastFarPlane(int x, int y) const
|
||||
{
|
||||
const filament::math::vec3<FLOAT> 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 <typename FLOAT>
|
||||
void Manipulator<FLOAT>::keyDown(Manipulator<FLOAT>::Key key) {}
|
||||
|
||||
template <typename FLOAT>
|
||||
void Manipulator<FLOAT>::keyUp(Manipulator<FLOAT>::Key key) {}
|
||||
|
||||
template <typename FLOAT>
|
||||
void Manipulator<FLOAT>::update(FLOAT deltaTime) {}
|
||||
|
||||
template class Manipulator<float>;
|
||||
template class Manipulator<double>;
|
||||
|
||||
} // namespace camutils
|
||||
} // namespace filament
|
||||
@@ -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 <math/scalar.h>
|
||||
|
||||
#include <camutils/Manipulator.h>
|
||||
|
||||
#include <math/vec3.h>
|
||||
|
||||
namespace filament
|
||||
{
|
||||
namespace camutils
|
||||
{
|
||||
|
||||
template <typename FLOAT>
|
||||
class MapManipulator : public Manipulator<FLOAT>
|
||||
{
|
||||
public:
|
||||
using vec2 = math::vec2<FLOAT>;
|
||||
using vec3 = math::vec3<FLOAT>;
|
||||
using vec4 = math::vec4<FLOAT>;
|
||||
using Bookmark = filament::camutils::Bookmark<FLOAT>;
|
||||
using Base = Manipulator<FLOAT>;
|
||||
using Config = typename Manipulator<FLOAT>::Config;
|
||||
|
||||
MapManipulator(Mode mode, const Config &props) : Manipulator<FLOAT>(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 */
|
||||
@@ -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 <camutils/Manipulator.h>
|
||||
|
||||
#include <math/scalar.h>
|
||||
|
||||
#define MAX_PHI (F_PI / 2.0 - 0.001)
|
||||
|
||||
namespace filament {
|
||||
namespace camutils {
|
||||
|
||||
using namespace filament::math;
|
||||
|
||||
template<typename FLOAT>
|
||||
class OrbitManipulator : public Manipulator<FLOAT> {
|
||||
public:
|
||||
using vec2 = filament::math::vec2<FLOAT>;
|
||||
using vec3 = filament::math::vec3<FLOAT>;
|
||||
using vec4 = filament::math::vec4<FLOAT>;
|
||||
using Bookmark = filament::camutils::Bookmark<FLOAT>;
|
||||
using Base = Manipulator<FLOAT>;
|
||||
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 */
|
||||
Reference in New Issue
Block a user