feat: replace position and rotation with cframe

This commit is contained in:
maelstrom 2025-02-05 22:19:18 +01:00
parent c7ea5c5563
commit 5ee493dc97
12 changed files with 207 additions and 23 deletions

View file

@ -118,15 +118,15 @@ void processInput(GLFWwindow* window) {
float shiftFactor = (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) ? -0.5 : 0.5;
shiftFactor *= deltaTime;
if (glfwGetKey(window, GLFW_KEY_X) == GLFW_PRESS) {
lastPart->rotation *= glm::angleAxis(shiftFactor, glm::vec3(1, 0, 0));
// lastPart->rotation *= glm::angleAxis(shiftFactor, glm::vec3(1, 0, 0));
syncPartPhysics(lastPart);
}
if (glfwGetKey(window, GLFW_KEY_Y) == GLFW_PRESS) {
lastPart->rotation *= glm::angleAxis(shiftFactor, glm::vec3(0, 1, 0));
// lastPart->rotation *= glm::angleAxis(shiftFactor, glm::vec3(0, 1, 0));
syncPartPhysics(lastPart);
}
if (glfwGetKey(window, GLFW_KEY_Z) == GLFW_PRESS) {
lastPart->rotation *= glm::angleAxis(shiftFactor, glm::vec3(0, 0, 1));
// lastPart->rotation *= glm::angleAxis(shiftFactor, glm::vec3(0, 0, 1));
syncPartPhysics(lastPart);
}
}
@ -178,15 +178,15 @@ void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods
float shiftFactor = (mods & GLFW_MOD_SHIFT) ? -0.2 : 0.2;
if (mode == 0) {
if (key == GLFW_KEY_X && action == GLFW_PRESS) {
lastPart->position.x += shiftFactor;
// lastPart->position.x += shiftFactor;
syncPartPhysics(lastPart);
}
if (key == GLFW_KEY_Y && action == GLFW_PRESS) {
lastPart->position.y += shiftFactor;
// lastPart->position.y += shiftFactor;
syncPartPhysics(lastPart);
}
if (key == GLFW_KEY_Z && action == GLFW_PRESS) {
lastPart->position.z += shiftFactor;
// lastPart->position.z += shiftFactor;
syncPartPhysics(lastPart);
}
} else if (mode == 1) {

View file

@ -74,8 +74,9 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) {
});
if (!rayHit) return;
draggingObject->lock()->position = rpToGlm(rayHit->worldPoint);
draggingObject->lock()->position += rpToGlm(rayHit->worldNormal) * draggingObject->lock()->scale / 2.f;
Data::Vector3 vec = rayHit->worldPoint;
vec = vec + Data::Vector3(rpToGlm(rayHit->worldNormal) * draggingObject->lock()->scale / 2.f);
draggingObject->lock()->cframe = draggingObject->lock()->cframe.Rotation() + vec;
syncPartPhysics(draggingObject->lock());
}

82
src/datatypes/cframe.cpp Normal file
View file

@ -0,0 +1,82 @@
#include "cframe.h"
#include "datatypes/vector.h"
#include "physics/util.h"
#include <glm/ext/matrix_transform.hpp>
#include <reactphysics3d/mathematics/Transform.h>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/euler_angles.hpp>
Data::CFrame::CFrame(glm::vec3 translation, glm::mat3 rotation)
: translation(translation)
, rotation(rotation) {
}
Data::CFrame::CFrame(Data::Vector3 position, glm::quat quat)
: translation(position)
, rotation(quat) {
}
Data::CFrame::CFrame(const rp::Transform& transform) : Data::CFrame::CFrame(rpToGlm(transform.getPosition()), rpToGlm(transform.getOrientation())) {
}
glm::mat3 lookAt(Data::Vector3 position, Data::Vector3 lookAt, Data::Vector3 up) {
// https://github.com/sgorsten/glm/issues/29#issuecomment-743989030
Data::Vector3 f = (lookAt - position).Unit(); // Forward/Look
Data::Vector3 u = up.Unit(); // Up
Data::Vector3 s = f.Cross(u).Unit(); // Right
u = s.Cross(u);
return {
{ s.X(), u.X(), -f.X() },
{ s.Y(), u.Y(), -f.Y() },
{ s.Z(), u.Z(), -f.Z() },
};
}
Data::CFrame::CFrame(Data::Vector3 position, Data::Vector3 lookAt, Data::Vector3 up)
: translation(position)
, rotation(::lookAt(position, lookAt, up)) {
}
Data::CFrame::~CFrame() = default;
const Data::TypeInfo Data::CFrame::TYPE = {
.name = "CFrame",
};
const Data::TypeInfo& Data::CFrame::GetType() const { return Data::Vector3::TYPE; };
const Data::String Data::CFrame::ToString() const {
return std::to_string(X()) + ", " + std::to_string(Y()) + ", " + std::to_string(Z());
}
Data::CFrame::operator glm::mat4() const {
// Always make sure to translate the position first, then rotate. Matrices work backwards
return glm::translate(glm::mat4(1.0f), this->translation) * glm::mat4(this->rotation);
}
Data::CFrame::operator rp::Transform() const {
return rp::Transform(glmToRp(translation), glmToRp(rotation));
}
Data::Vector3 Data::CFrame::ToEulerAnglesXYZ() {
float x;
float y;
float z;
glm::extractEulerAngleXYZ(glm::mat4(this->rotation), x, y, z);
return Data::Vector3(x, y, z);
}
Data::CFrame Data::CFrame::FromEulerAnglesXYZ(Data::Vector3 vector) {
glm::mat3 mat = glm::eulerAngleXYZ(vector.X(), vector.Y(), vector.Z());
return Data::CFrame(Data::Vector3::ZERO, glm::column(mat, 2), (Data::Vector3)glm::column(mat, 1)); // Getting LookAt (3rd) and Up (2nd) vectors
}
// Operators
Data::CFrame Data::CFrame::operator +(Data::Vector3 vector) const {
return CFrame { this->translation + glm::vec3(vector), this->rotation };
}
Data::CFrame Data::CFrame::operator -(Data::Vector3 vector) const {
return *this + -vector;
}

56
src/datatypes/cframe.h Normal file
View file

@ -0,0 +1,56 @@
#pragma once
#include "base.h"
#include "datatypes/vector.h"
#include <glm/ext/matrix_float3x3.hpp>
#include <glm/ext/quaternion_geometric.hpp>
#include <glm/ext/vector_float3.hpp>
#include <glm/fwd.hpp>
#include <glm/gtc/matrix_access.hpp>
#include <reactphysics3d/mathematics/Transform.h>
#include <reactphysics3d/reactphysics3d.h>
namespace rp = reactphysics3d;
namespace Data {
class CFrame : Base {
glm::vec3 translation;
glm::mat3 rotation;
CFrame(glm::vec3, glm::mat3);
public:
// CFrame(float x, float y, float z);
// CFrame(const glm::vec3&);
// CFrame(const rp::Vector3&);
CFrame(const rp::Transform&);
CFrame(Data::Vector3 position, glm::quat quat);
CFrame(Data::Vector3 position, Data::Vector3 lookAt, Data::Vector3 up = Data::Vector3(0, 1, 0));
~CFrame();
virtual const TypeInfo& GetType() const override;
static const TypeInfo TYPE;
virtual const Data::String ToString() const override;
operator glm::mat4() const;
operator rp::Transform() const;
//inline static CFrame identity() { }
inline Vector3 Position() const { return translation; }
inline CFrame Rotation() const { return CFrame { glm::vec3(0, 0, 0), rotation }; }
inline float X() const { return translation.x; }
inline float Y() const { return translation.y; }
inline float Z() const { return translation.z; }
inline Vector3 RightVector() { return glm::column(rotation, 0); }
inline Vector3 UpVector() { return glm::column(rotation, 1); }
inline Vector3 LookVector() { return glm::column(rotation, 2); }
Vector3 ToEulerAnglesXYZ();
static CFrame FromEulerAnglesXYZ(Data::Vector3);
// Operators
Data::CFrame operator +(Data::Vector3) const;
Data::CFrame operator -(Data::Vector3) const;
};
}

View file

@ -1,8 +1,9 @@
#pragma once
#include <variant>
#include "base.h"
#include "vector.h"
#include <variant>
#include "cframe.h"
// #define __VARIANT_TYPE std::variant< \
// Null, \
@ -19,7 +20,8 @@ namespace Data {
Int,
Float,
String,
Vector3
Vector3,
CFrame
> __VARIANT_TYPE;
class Variant {

View file

@ -1,4 +1,5 @@
#include "vector.h"
#include <glm/ext/quaternion_geometric.hpp>
Data::Vector3::Vector3(const glm::vec3& src) : vector(src) {};
Data::Vector3::Vector3(const rp::Vector3& src) : vector(glm::vec3(src.x, src.y, src.z)) {};
@ -11,9 +12,33 @@ const Data::TypeInfo Data::Vector3::TYPE = {
const Data::TypeInfo& Data::Vector3::GetType() const { return Data::Vector3::TYPE; };
Data::Vector3 Data::Vector3::ZERO(0, 0, 0);
Data::Vector3 Data::Vector3::ONE(1, 1, 1);
const Data::String Data::Vector3::ToString() const {
return std::to_string(X()) + ", " + std::to_string(Y()) + ", " + std::to_string(Z());
}
Data::Vector3::operator glm::vec3() const { return vector; };
Data::Vector3::operator rp::Vector3() const { return rp::Vector3(X(), Y(), Z()); };
Data::Vector3::operator rp::Vector3() const { return rp::Vector3(X(), Y(), Z()); };
// Operators
Data::Vector3 Data::Vector3::operator +(Data::Vector3 other) const {
return Data::Vector3(this->X() + other.X(), this->Y() + other.Y(), this->Z() + other.Z());
}
Data::Vector3 Data::Vector3::operator -(Data::Vector3 other) const {
return Data::Vector3(this->X() - other.X(), this->Y() - other.Y(), this->Z() - other.Z());
}
Data::Vector3 Data::Vector3::operator -() const {
return Data::Vector3(-this->X(), -this->Y(), -this->Z());
}
Data::Vector3 Data::Vector3::Cross(Data::Vector3 other) const {
return glm::cross(this->vector, other.vector);
}
float Data::Vector3::Dot(Data::Vector3 other) const {
return glm::dot(this->vector, other.vector);
}

View file

@ -9,7 +9,7 @@ namespace rp = reactphysics3d;
namespace Data {
class Vector3 : Base {
const glm::vec3 vector;
glm::vec3 vector;
public:
Vector3(float x, float y, float z);
@ -20,6 +20,9 @@ namespace Data {
virtual const TypeInfo& GetType() const override;
static const TypeInfo TYPE;
static Data::Vector3 ZERO;
static Data::Vector3 ONE;
virtual const Data::String ToString() const override;
operator glm::vec3() const;
@ -29,5 +32,14 @@ namespace Data {
inline float Y() const { return vector.y; }
inline float Z() const { return vector.z; }
inline float Magnitude() const { return glm::length(vector); }
inline Data::Vector3 Unit() const { return glm::normalize(vector); }
Data::Vector3 Cross(Data::Vector3) const;
float Dot(Data::Vector3) const;
// Operators
Data::Vector3 operator +(Data::Vector3) const;
Data::Vector3 operator -(Data::Vector3) const;
Data::Vector3 operator -() const;
};
}

View file

@ -1,6 +1,7 @@
#include "part.h"
#include "base/instance.h"
#include "datatypes/base.h"
#include "datatypes/cframe.h"
#include "datatypes/vector.h"
#include "objects/base/member.h"
#include <memory>
@ -21,13 +22,13 @@ const InstanceType* Part::GetClass() {
Part::Part(): Part(PartConstructParams {}) {
}
Part::Part(PartConstructParams params): Instance(&TYPE), position(params.position), rotation(params.rotation),
Part::Part(PartConstructParams params): Instance(&TYPE), cframe(Data::CFrame(params.position, params.rotation)),
scale(params.scale), material(params.material), anchored(params.anchored) {
this->memberMap = std::make_unique<MemberMap>(MemberMap {
.super = std::move(this->memberMap),
.members = {
{ "Anchored", { .backingField = &anchored, .type = &Data::Bool::TYPE, .codec = fieldCodecOf<Data::Bool, bool>(), .updateCallback = memberFunctionOf(&Part::onUpdated, this) } },
{ "Position", { .backingField = &position, .type = &Data::Vector3::TYPE, .codec = fieldCodecOf<Data::Vector3, glm::vec3>(), .updateCallback = memberFunctionOf(&Part::onUpdated, this) } }
// { "Position", { .backingField = &position, .type = &Data::Vector3::TYPE, .codec = fieldCodecOf<Data::Vector3, glm::vec3>(), .updateCallback = memberFunctionOf(&Part::onUpdated, this) } }
}
});
}

View file

@ -5,6 +5,7 @@
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include "../rendering/material.h"
#include "datatypes/cframe.h"
#include "datatypes/vector.h"
#include <reactphysics3d/reactphysics3d.h>
@ -28,8 +29,7 @@ public:
const static InstanceType TYPE;
// TODO: Switch these over to our dedicated datatypes
glm::vec3 position;
glm::quat rotation = glm::identity<glm::quat>();
Data::CFrame cframe;
glm::vec3 scale;
Material material;
bool selected = false;
@ -45,4 +45,6 @@ public:
static inline std::shared_ptr<Part> New(PartConstructParams params) { return std::make_shared<Part>(params); };
static inline InstanceRef CreateGeneric() { return std::make_shared<Part>(); };
virtual const InstanceType* GetClass() override;
inline Data::Vector3 position() { return cframe.Position(); }
};

View file

@ -17,6 +17,7 @@
#include <reactphysics3d/reactphysics3d.h>
#include "../common.h"
#include "../objects/part.h"
#include "datatypes/cframe.h"
#include "util.h"
#include "simulation.h"
@ -45,7 +46,7 @@ void simulationInit() {
void syncPartPhysics(std::shared_ptr<Part> part) {
glm::mat4 rotMat = glm::mat4(1.0f);
rp::Transform transform(glmToRp(part->position), glmToRp(part->rotation));
rp::Transform transform = part->cframe;
if (!part->rigidBody) {
part->rigidBody = world->createRigidBody(transform);
} else {
@ -76,9 +77,7 @@ void physicsStep(float deltaTime) {
if (obj->GetClass()->className != "Part") continue; // TODO: Replace this with a .IsA call instead of comparing the class name directly
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(obj);
const rp::Transform& transform = part->rigidBody->getTransform();
part->position = rpToGlm(transform.getPosition());
// part.rotation = glm::eulerAngles(rpToGlm(transform.getOrientation()));
part->rotation = rpToGlm(transform.getOrientation());
part->cframe = Data::CFrame(transform);
}
}

View file

@ -2,6 +2,7 @@
#include <glm/ext/vector_float3.hpp>
#include <memory>
#include <reactphysics3d/body/Body.h>
#include <reactphysics3d/mathematics/Matrix3x3.h>
#include <reactphysics3d/mathematics/Quaternion.h>
#include <reactphysics3d/mathematics/Vector3.h>
#include <reactphysics3d/mathematics/mathematics.h>
@ -18,6 +19,10 @@ inline rp::Quaternion glmToRp(glm::quat quat) {
return rp::Quaternion(quat.w, rp::Vector3(quat.x, quat.y, quat.z));
}
// inline rp::Matrix3x3 glmToRp(glm::mat3 mat) {
// return (rp::Quaternion)glmToRp((glm::quat)mat);
// }
inline glm::vec3 rpToGlm(rp::Vector3 vec) {
return glm::vec3(vec.x, vec.y, vec.z);
}

View file

@ -10,6 +10,7 @@
#include <memory>
#include <vector>
#include "physics/util.h"
#include "shader.h"
#include "mesh.h"
#include "defaultmeshes.h"
@ -109,9 +110,7 @@ void renderParts() {
if (inst->GetClass()->className != "Part") continue;
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, part->position);
model = model * glm::mat4_cast(part->rotation);
glm::mat4 model = part->cframe;
model = glm::scale(model, part->scale);
shader->set("model", model);
shader->set("material", part->material);