diff --git a/client/src/main.cpp b/client/src/main.cpp index 53ef4a7..5c15e42 100644 --- a/client/src/main.cpp +++ b/client/src/main.cpp @@ -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) { diff --git a/editor/mainglwidget.cpp b/editor/mainglwidget.cpp index d90efc2..1ad678d 100644 --- a/editor/mainglwidget.cpp +++ b/editor/mainglwidget.cpp @@ -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()); } diff --git a/src/datatypes/cframe.cpp b/src/datatypes/cframe.cpp new file mode 100644 index 0000000..f148b73 --- /dev/null +++ b/src/datatypes/cframe.cpp @@ -0,0 +1,82 @@ +#include "cframe.h" +#include "datatypes/vector.h" +#include "physics/util.h" +#include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include + +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; +} \ No newline at end of file diff --git a/src/datatypes/cframe.h b/src/datatypes/cframe.h new file mode 100644 index 0000000..c5f761e --- /dev/null +++ b/src/datatypes/cframe.h @@ -0,0 +1,56 @@ +#pragma once + +#include "base.h" +#include "datatypes/vector.h" +#include +#include +#include +#include +#include +#include +#include + +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; + }; +} diff --git a/src/datatypes/meta.h b/src/datatypes/meta.h index c3a248e..c14d0d4 100644 --- a/src/datatypes/meta.h +++ b/src/datatypes/meta.h @@ -1,8 +1,9 @@ #pragma once +#include #include "base.h" #include "vector.h" -#include +#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 { diff --git a/src/datatypes/vector.cpp b/src/datatypes/vector.cpp index 7107924..69c9fd4 100644 --- a/src/datatypes/vector.cpp +++ b/src/datatypes/vector.cpp @@ -1,4 +1,5 @@ #include "vector.h" +#include 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()); }; \ No newline at end of file +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); +} \ No newline at end of file diff --git a/src/datatypes/vector.h b/src/datatypes/vector.h index 80154f1..9b04574 100644 --- a/src/datatypes/vector.h +++ b/src/datatypes/vector.h @@ -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; }; } diff --git a/src/objects/part.cpp b/src/objects/part.cpp index 89bd95c..5e41f24 100644 --- a/src/objects/part.cpp +++ b/src/objects/part.cpp @@ -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 @@ -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 { .super = std::move(this->memberMap), .members = { { "Anchored", { .backingField = &anchored, .type = &Data::Bool::TYPE, .codec = fieldCodecOf(), .updateCallback = memberFunctionOf(&Part::onUpdated, this) } }, - { "Position", { .backingField = &position, .type = &Data::Vector3::TYPE, .codec = fieldCodecOf(), .updateCallback = memberFunctionOf(&Part::onUpdated, this) } } + // { "Position", { .backingField = &position, .type = &Data::Vector3::TYPE, .codec = fieldCodecOf(), .updateCallback = memberFunctionOf(&Part::onUpdated, this) } } } }); } diff --git a/src/objects/part.h b/src/objects/part.h index 974d279..f74476e 100644 --- a/src/objects/part.h +++ b/src/objects/part.h @@ -5,6 +5,7 @@ #include #include #include "../rendering/material.h" +#include "datatypes/cframe.h" #include "datatypes/vector.h" #include @@ -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(); + Data::CFrame cframe; glm::vec3 scale; Material material; bool selected = false; @@ -45,4 +45,6 @@ public: static inline std::shared_ptr New(PartConstructParams params) { return std::make_shared(params); }; static inline InstanceRef CreateGeneric() { return std::make_shared(); }; virtual const InstanceType* GetClass() override; + + inline Data::Vector3 position() { return cframe.Position(); } }; \ No newline at end of file diff --git a/src/physics/simulation.cpp b/src/physics/simulation.cpp index 3ce7f9d..28dd23e 100644 --- a/src/physics/simulation.cpp +++ b/src/physics/simulation.cpp @@ -17,6 +17,7 @@ #include #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) { 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 = std::dynamic_pointer_cast(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); } } diff --git a/src/physics/util.h b/src/physics/util.h index 351e553..10042ad 100644 --- a/src/physics/util.h +++ b/src/physics/util.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -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); } diff --git a/src/rendering/renderer.cpp b/src/rendering/renderer.cpp index 9b6f190..4312b9f 100644 --- a/src/rendering/renderer.cpp +++ b/src/rendering/renderer.cpp @@ -10,6 +10,7 @@ #include #include +#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 = std::dynamic_pointer_cast(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);