From a534e9450a409276a23004d01529ec1400479468 Mon Sep 17 00:00:00 2001 From: Glenn Waldron Date: Fri, 1 Nov 2024 11:43:43 -0400 Subject: [PATCH] Add missing files --- src/rocky/vsg/Motion.h | 84 +++++++++++++++++++++++++++++++++++++++ src/rocky/vsg/Transform.h | 82 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 src/rocky/vsg/Motion.h create mode 100644 src/rocky/vsg/Transform.h diff --git a/src/rocky/vsg/Motion.h b/src/rocky/vsg/Motion.h new file mode 100644 index 00000000..83d51552 --- /dev/null +++ b/src/rocky/vsg/Motion.h @@ -0,0 +1,84 @@ +/** + * rocky c++ + * Copyright 2023 Pelican Mapping + * MIT License + */ +#pragma once +#include +#include + +namespace ROCKY_NAMESPACE +{ + /** + * ECS Component applying simple motion to an object + */ + struct Motion + { + glm::dvec3 velocity; + glm::dvec3 acceleration; + }; + + /** + * ECS System to process Motion components + */ + class MotionSystem : public ECS::System + { + public: + MotionSystem(entt::registry& r) : ECS::System(r) { } + + std::vector updated; + + //! Called periodically to update the transforms + void update(Runtime& runtime) override + { + updated.clear(); + + auto time = runtime.viewer->getFrameStamp()->time; + + if (last_time != ECS::time_point::min()) + { + // delta seconds since last tick: + double dt = 1e-9 * (double)(time - last_time).count(); + + // Join query all motions + transform pairs: + auto view = registry.group(); + + for (auto&& [entity, motion, transform] : view.each()) + { + const glm::dvec3 zero{ 0.0, 0.0, 0.0 }; + + if (motion.velocity != zero) + { + GeoPoint& pos = transform.position; + double save_z = pos.z; + + auto pos_to_world = pos.srs.to(pos.srs.geocentricSRS()); + + // move the entity using a velocity vector in the local tangent plane + glm::dvec3 world; + pos_to_world((glm::dvec3)pos, world); + auto l2w = pos.srs.ellipsoid().geocentricToLocalToWorld(world); + + world = l2w * (motion.velocity * dt); + + vsg::dvec3 coord(world.x, world.y, world.z); + pos_to_world.inverse(coord, coord); + + pos.x = coord.x, pos.y = coord.y; + pos.z = save_z; + transform.dirty(); + + updated.emplace_back(entity); + } + + motion.velocity += motion.acceleration * dt; + }; + } + last_time = time; + } + + private: + //! Constructor + ECS::time_point last_time = ECS::time_point::min(); + }; +} diff --git a/src/rocky/vsg/Transform.h b/src/rocky/vsg/Transform.h new file mode 100644 index 00000000..09bacacd --- /dev/null +++ b/src/rocky/vsg/Transform.h @@ -0,0 +1,82 @@ +/** + * rocky c++ + * Copyright 2023 Pelican Mapping + * MIT License + */ +#pragma once +#include + +namespace ROCKY_NAMESPACE +{ + /** + * Spatial transformation component. + * Create with + * auto& transform = registry.emplace(entity); + * + * A Transform may be safely updated asynchronously. + */ + struct Transform + { + //! Georeferenced position + GeoPoint position; + + //! Local transform matrix (for rotation and scale, e.g.) + vsg::dmat4 localMatrix; + + //! Whether the localMatrix is relative to a local tangent plane at + //! "position", versus a simple translated reference frame. + bool localTangentPlane = true; + + //! Parent transform to apply before applying this one + Transform* parent = nullptr; + + //! Underlying geotransform logic + vsg::ref_ptr node; // todo. move this to a separate component...? + + Transform() + { + } + + void setPosition(const GeoPoint& p) + { + position = p; + dirty(); + } + + void dirty() + { + if (!node) + node = GeoTransform::create(); + + node->setPosition(position); + node->localTangentPlane = localTangentPlane; + } + + //! Returns true if the push succeeded (and a pop will be required) + inline bool push(vsg::RecordTraversal& rt, const vsg::dmat4& m) + { + if (node) + { + return node->push(rt, m * localMatrix); + } + else if (parent) + { + return parent->push(rt, m * localMatrix); + } + else return false; + } + + //! Pops a transform applied if push() returned true. + inline void pop(vsg::RecordTraversal& rt) + { + if (node) + { + node->pop(rt); + } + else if (parent) + { + parent->pop(rt); + } + } + }; +}