载入中...
搜索中...
未找到
PcgCarCameraSetup.cpp
浏览该文件的文档.
2
7
8#include <simplesquirrel/simplesquirrel.hpp>
9
10#include <algorithm>
11#include <cmath>
12
13namespace eve::camera {
14namespace {
15bool finite(float value) { return std::isfinite(value); }
16float shortestAngle(float from, float to) {
17 float delta = std::fmod(to - from + 180.f, 360.f);
18 if (delta < 0.f) delta += 360.f;
19 return delta - 180.f;
20}
21}
22
24 if (!finite(p.targetHeight) || !finite(p.distance) || !finite(p.offsetFromWall) ||
25 !finite(p.maximumDistance) || !finite(p.minimumDistance) || !finite(p.horizontalSpeed) ||
26 !finite(p.verticalSpeed) || !finite(p.minimumPitch) || !finite(p.maximumPitch) ||
27 !finite(p.zoomRate) || !finite(p.rotationDamping) || !finite(p.zoomDamping) ||
28 p.targetHeight < 0.f || p.minimumDistance <= 0.f || p.maximumDistance < p.minimumDistance ||
29 p.distance < p.minimumDistance || p.distance > p.maximumDistance || p.offsetFromWall < 0.f ||
30 p.horizontalSpeed < 0.f || p.verticalSpeed < 0.f || p.maximumPitch < p.minimumPitch ||
31 p.minimumPitch < -89.f || p.maximumPitch > 89.f || p.zoomRate < 0.f ||
32 p.rotationDamping < 0.f || p.zoomDamping < 0.f)
33 return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "invalid Pcg vehicle camera profile", "camera.pcgCar.configure"));
34 profile_ = p;
35 configured_ = true;
36 return Result<void>::success();
37}
38
40 scene::SceneNodeRef* focus, float initialYaw, float initialPitch) {
41 if (!c || !camera || !focus) return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "controller, camera and focus are required", "camera.pcgCar.apply"));
42 if (!finite(initialYaw) || !finite(initialPitch)) return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "initial angles must be finite", "camera.pcgCar.apply"));
43 if (!configured_) {
44 auto result = configure(profile_);
45 if (!result) return result;
46 }
47 auto limits = c->setRadiusLimits(profile_.minimumDistance, profile_.maximumDistance);
48 if (!limits) return limits;
49 yaw_ = initialYaw;
50 pitch_ = std::clamp(initialPitch, profile_.minimumPitch, profile_.maximumPitch);
51 c->setCamera(camera);
52 c->setTargetNode(focus);
53 c->setMode("orbit");
54 c->setLookAhead(0.f, profile_.targetHeight, 0.f);
55 c->setRadius(profile_.distance);
56 c->setAzimuth(yaw_);
57 c->setElevation(pitch_);
58 c->setTargetSmooth(profile_.rotationDamping);
59 c->setPositionSmooth(profile_.zoomDamping);
60 c->setCollisionEnabled(true);
61 c->setCollisionRadius(profile_.offsetFromWall);
62 c->setCollisionRecovery(profile_.zoomDamping);
63 c->setCollisionMask(profile_.collisionLayers);
64 return Result<void>::success();
65}
66
68 float scroll, float dt, bool targetIsMoving, float targetYaw) {
69 if (!c) return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "controller is required", "camera.pcgCar.update"));
70 if (!finite(mouseX) || !finite(mouseY) || !finite(scroll) || !finite(dt) || !finite(targetYaw) || dt < 0.f)
71 return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "camera input and dt must be finite", "camera.pcgCar.update"));
72 if (!configured_) return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "camera setup has not been configured", "camera.pcgCar.update"));
73 if (profile_.allowMouseHorizontal) yaw_ += mouseX * profile_.horizontalSpeed * 0.02f;
74 if (profile_.allowMouseVertical)
75 pitch_ = std::clamp(pitch_ - mouseY * profile_.verticalSpeed * 0.02f,
76 profile_.minimumPitch, profile_.maximumPitch);
77 if ((profile_.lockToRearOfTarget || targetIsMoving) && std::abs(mouseX) <= 1e-6f) {
78 const float blend = 1.f - std::exp(-profile_.rotationDamping * dt);
79 yaw_ += shortestAngle(yaw_, targetYaw) * blend;
80 }
81 c->setAzimuth(yaw_);
82 c->setElevation(pitch_);
83 const float zoomDelta = -scroll * dt * profile_.zoomRate * std::abs(c->getRadius());
84 c->addInput(0.f, 0.f, zoomDelta);
85 return Result<void>::success();
86}
87
89 auto p = t.addClass("PcgCarCameraProfile", ssq::Class::Ctor<PcgCarCameraProfile()>());
90 p.addVar("targetHeight", &PcgCarCameraProfile::targetHeight); p.addVar("distance", &PcgCarCameraProfile::distance);
91 p.addVar("offsetFromWall", &PcgCarCameraProfile::offsetFromWall); p.addVar("maximumDistance", &PcgCarCameraProfile::maximumDistance);
92 p.addVar("minimumDistance", &PcgCarCameraProfile::minimumDistance); p.addVar("horizontalSpeed", &PcgCarCameraProfile::horizontalSpeed);
93 p.addVar("verticalSpeed", &PcgCarCameraProfile::verticalSpeed); p.addVar("minimumPitch", &PcgCarCameraProfile::minimumPitch);
94 p.addVar("maximumPitch", &PcgCarCameraProfile::maximumPitch); p.addVar("zoomRate", &PcgCarCameraProfile::zoomRate);
95 p.addVar("rotationDamping", &PcgCarCameraProfile::rotationDamping); p.addVar("zoomDamping", &PcgCarCameraProfile::zoomDamping);
96 p.addVar("collisionLayers", &PcgCarCameraProfile::collisionLayers); p.addVar("lockToRearOfTarget", &PcgCarCameraProfile::lockToRearOfTarget);
97 p.addVar("allowMouseHorizontal", &PcgCarCameraProfile::allowMouseHorizontal); p.addVar("allowMouseVertical", &PcgCarCameraProfile::allowMouseVertical);
98 auto s = t.addClass("PcgCarCameraSetup", ssq::Class::Ctor<PcgCarCameraSetup()>()); auto vm = t.getHandle();
99 s.addFunc("configure", [vm](PcgCarCameraSetup* self, const PcgCarCameraProfile* profile) { return eve::script::projectResult(vm, profile ? self->configure(*profile) : Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "profile is required", "camera.pcgCar.configure"))); });
100 s.addFunc("apply", [vm](PcgCarCameraSetup* self, CameraController* c, graphics::Camera3D* camera, scene::SceneNodeRef* focus, float yaw, float pitch) { return eve::script::projectResult(vm, self->apply(c, camera, focus, yaw, pitch)); });
101 s.addFunc("update", [vm](PcgCarCameraSetup* self, CameraController* c, float mx, float my, float scroll, float dt, bool moving, float targetYaw) { return eve::script::projectResult(vm, self->update(c, mx, my, scroll, dt, moving, targetYaw)); });
102 s.addFunc("getYaw", [](const PcgCarCameraSetup* self) { return self->getYaw(); });
103 s.addFunc("getPitch", [](const PcgCarCameraSetup* self) { return self->getPitch(); });
104}
105}
double value
std::string from
const std::string & s
glm::vec4 p[6]
HSQUIRRELVM vm
Definition ECS.cpp:20
float camera[2]
std::int32_t c
float blend
HexCoordinates to
Cell the unit walks towards on this segment.
Definition HexUnits.cpp:64
bool finite
float t
The single Squirrel projection for common Result, Status and Value.
const AssetImportLimits & limits
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
3D 摄像机控制器(eve.Camera / eve.CameraController)。
Caller-owned Pcg vehicle orbit-camera setup and input adapter.
Result< void > apply(CameraController *controller, graphics::Camera3D *camera, scene::SceneNodeRef *focus, float initialYaw, float initialPitch)
Apply the profile to a live native controller and its stable target.
float getPitch() const noexcept
Return current orbit pitch.
Result< void > update(CameraController *controller, float mouseX, float mouseY, float scroll, float dt, bool targetIsMoving, float targetYaw)
Apply one device-independent mouse/scroll frame.
float getYaw() const noexcept
Return current orbit yaw.
Result< void > configure(const PcgCarCameraProfile &profile)
Validate and copy a complete profile without partial mutation.
EVENGINE_API_BACKENDS public API.
Script handle to a scene node (hostName + nodeId). Deliberately holds strings rather than arena point...
void exposePcgCarCameraSetupBindings(ssq::Table &t)
Register Pcg vehicle camera bindings.
ssq::Table projectResult(HSQUIRRELVM vm, Result< void > &&result)
Consume and project a void native Result using the common schema.
Serializable values matching Pcg CarControllerSetup camera defaults.