A scene link keeps an external object in step with the node it hangs off. The kinds were a closed enum with a switch in TransformSystem, so scene had to include graphics, physics and audio to do the casts, and no other module could ever attach to the tree without editing SceneHost.h -- particles, voxel, spritestack, avatar and weather all had to stay outside it. Kinds are registered now (scene/SceneLink.h). The module owning the target type supplies pushWorld / pullWorld / alive, keeps the casts on its own side where the type is complete, and scene never learns what a Renderable3D is. Dispatch is a function-pointer table rather than virtual calls, since link sync runs for every dirty node every frame. The six typed helpers (linkRenderable2D and friends) stay as conveniences and now resolve their kind by name, so they return false rather than crash when the module that registers it was trimmed out. The script API already named kinds with strings, which is exactly the registry key, so it is unchanged. Direction is now the right way round: graphics, physics and audio depend on scene rather than scene on them, and scene drops from L5 to L1. What remains is scene -> graphics from pickScreenAt / collectFrustumIdsAt, which take a Camera3D and read its projection; that is recorded in the back-edge whitelist as the next thing to move. Each provider lives in a SceneLinks.cpp, sharing the basename so the three come out of the build together when scene is disabled. Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
70 lines
2.0 KiB
C++
70 lines
2.0 KiB
C++
// Registers the scene link kinds backed by physics: 2D and 3D rigid bodies.
|
|
//
|
|
// These are the only kinds that can drive a node instead of following it
|
|
// (syncMode 1), so they are also the only ones supplying pullWorld.
|
|
|
|
#include "physics/Body.h"
|
|
#include "physics/Body3D.h"
|
|
#include "scene/SceneHost.h"
|
|
#include "scene/SceneLink.h"
|
|
|
|
#include <glm/gtc/quaternion.hpp>
|
|
|
|
namespace eve::physics {
|
|
namespace {
|
|
|
|
using eve::scene::LinkOps;
|
|
using eve::scene::SceneNode;
|
|
|
|
void pushBody2D(const SceneNode &n, void *target) {
|
|
auto *b = static_cast<Body *>(target);
|
|
b->setPosition(n.x, n.y);
|
|
b->setAngle(n.roll);
|
|
}
|
|
|
|
void pullBody2D(SceneNode &n, void *target) {
|
|
auto *b = static_cast<Body *>(target);
|
|
n.x = b->getX();
|
|
n.y = b->getY();
|
|
n.roll = b->getAngle();
|
|
}
|
|
|
|
bool aliveBody2D(const void *target) {
|
|
return static_cast<const Body *>(target)->raw() != nullptr;
|
|
}
|
|
|
|
void pushBody3D(const SceneNode &n, void *target) {
|
|
auto *b = static_cast<Body3D *>(target);
|
|
b->setPosition(n.x, n.y, n.z);
|
|
glm::quat q = glm::angleAxis(n.yaw, glm::vec3(0.f, 1.f, 0.f)) *
|
|
glm::angleAxis(n.pitch, glm::vec3(1.f, 0.f, 0.f)) *
|
|
glm::angleAxis(n.roll, glm::vec3(0.f, 0.f, 1.f));
|
|
b->setRotation(q.x, q.y, q.z, q.w);
|
|
}
|
|
|
|
void pullBody3D(SceneNode &n, void *target) {
|
|
auto *b = static_cast<Body3D *>(target);
|
|
n.x = b->getX();
|
|
n.y = b->getY();
|
|
n.z = b->getZ();
|
|
glm::quat q(b->getRotW(), b->getRotX(), b->getRotY(), b->getRotZ());
|
|
glm::vec3 e = glm::eulerAngles(q); // pitch(x), yaw(y), roll(z)
|
|
n.pitch = e.x;
|
|
n.yaw = e.y;
|
|
n.roll = e.z;
|
|
}
|
|
|
|
bool aliveBody3D(const void *target) {
|
|
return static_cast<const Body3D *>(target)->isValid();
|
|
}
|
|
|
|
struct Register {
|
|
Register() {
|
|
eve::scene::registerLinkKind({"physics2d", &pushBody2D, &pullBody2D, &aliveBody2D});
|
|
eve::scene::registerLinkKind({"physics3d", &pushBody3D, &pullBody3D, &aliveBody3D});
|
|
}
|
|
} g_register;
|
|
|
|
} // namespace
|
|
} // namespace eve::physics
|