From 3bb80b84644e8d0f2d0673b93d359dcdbece2385 Mon Sep 17 00:00:00 2001 From: MegaMech <7255464+MegaMech@users.noreply.github.com> Date: Fri, 28 Feb 2025 20:46:04 -0700 Subject: [PATCH] gizmo work --- src/engine/World.cpp | 5 +- src/engine/editor/Collision.cpp | 4 +- src/engine/editor/Collision.h | 2 +- src/engine/editor/Editor.cpp | 46 ++++++++++++++-- src/engine/editor/Editor.h | 2 +- src/engine/editor/EditorMath.cpp | 16 ++++-- src/engine/editor/EditorMath.h | 2 +- src/engine/editor/Gizmo.cpp | 40 +++++++++++--- src/engine/editor/Gizmo.h | 2 +- src/engine/editor/ObjectPicker.cpp | 88 ++++++++++++++++++------------ src/engine/editor/ObjectPicker.h | 4 +- 11 files changed, 145 insertions(+), 66 deletions(-) diff --git a/src/engine/World.cpp b/src/engine/World.cpp index 6f59f00cd..450c22ac7 100644 --- a/src/engine/World.cpp +++ b/src/engine/World.cpp @@ -115,7 +115,7 @@ void World::PreviousCourse() { AActor* World::AddActor(AActor* actor) { Actors.push_back(actor); - gEditor.AddObject((FVector*) &actor->Pos, actor->Model, CollisionType::VTX_INTERSECT, 0.0f); + gEditor.AddObject((FVector*) &actor->Pos, actor->Model, 1.0f, CollisionType::VTX_INTERSECT, 0.0f); return Actors.back(); } @@ -125,10 +125,9 @@ struct Actor* World::AddBaseActor(s16 actorType) { AActor* actor = Actors.back(); if (actorType == ACTOR_ITEM_BOX) { - printf("ADD ITEM BOX\n"); actor->Model = (Gfx*)LOAD_ASSET_RAW(itemBoxQuestionMarkModel); } - gEditor.AddObject((FVector*) &actor->Pos, actor->Model, CollisionType::VTX_INTERSECT, 0.0f); + gEditor.AddObject((FVector*) &actor->Pos, actor->Model, 1.0f, CollisionType::VTX_INTERSECT, 0.0f); // Skip C++ vtable to access variables in C return reinterpret_cast(reinterpret_cast(Actors.back()) + sizeof(void*)); } diff --git a/src/engine/editor/Collision.cpp b/src/engine/editor/Collision.cpp index af9a9bd3c..7de4e63e3 100644 --- a/src/engine/editor/Collision.cpp +++ b/src/engine/editor/Collision.cpp @@ -1,7 +1,7 @@ #include "Collision.h" -void GenerateCollisionMesh(GameObject& object, Gfx* model) { +void GenerateCollisionMesh(GameObject& object, Gfx* model, float scale) { int8_t opcode; uintptr_t lo; uintptr_t hi; @@ -18,7 +18,7 @@ void GenerateCollisionMesh(GameObject& object, Gfx* model) { switch(opcode) { case G_DL: - GenerateCollisionMesh(object, (Gfx*)hi); + GenerateCollisionMesh(object, (Gfx*)hi, scale); break; case G_VTX: vtx = (Vtx*)ptr->words.w1; diff --git a/src/engine/editor/Collision.h b/src/engine/editor/Collision.h index 6637051b8..5596b6acf 100644 --- a/src/engine/editor/Collision.h +++ b/src/engine/editor/Collision.h @@ -16,4 +16,4 @@ #define EDITOR_GFX_GET_OPCODE(var) ((uint32_t) ((var) & 0xFF000000)) -void GenerateCollisionMesh(GameObject& object, Gfx* model); +void GenerateCollisionMesh(GameObject& object, Gfx* model, float scale); diff --git a/src/engine/editor/Editor.cpp b/src/engine/editor/Editor.cpp index 0de8d2884..5256cb036 100644 --- a/src/engine/editor/Editor.cpp +++ b/src/engine/editor/Editor.cpp @@ -35,28 +35,62 @@ Editor::Editor() { void Editor::Load() { eObjectPicker.Load(); for (auto& object : eGameObjects) { - GenerateCollisionMesh(object, object.Model); + GenerateCollisionMesh(object, object.Model, 1.0f); } } void Editor::Tick() { auto wnd = GameEngine::Instance->context->GetWindow(); - // GetMouseState - if (wnd->MouseClick(Ship::LUS_MOUSE_BTN_LEFT)) { - eObjectPicker.SelectObject(eGameObjects); + static bool wasMouseDown = false; + static bool isDragging = false; + static Ship::Coords mouseStartPos; + + Ship::Coords mousePos = wnd->GetMousePos(); + bool isMouseDown = wnd->GetMouseState(Ship::LUS_MOUSE_BTN_LEFT); + + if (isMouseDown && !wasMouseDown) { + // Mouse just pressed (Pressed state) + mouseStartPos = mousePos; + isDragging = false; } + + if (isMouseDown) { + // Mouse is being held (Held state) + int dx = mousePos.x - mouseStartPos.x; + int dy = mousePos.y - mouseStartPos.y; + int dragThreshold = 5; // Adjust as needed + + if ((dx * dx + dy * dy) > (dragThreshold * dragThreshold)) { + // Squared distance check to avoid unnecessary sqrt() + isDragging = true; + eObjectPicker.DragHandle(); // Call drag logic + } + } + + if (!isMouseDown && wasMouseDown) { + // Mouse just released (Released state) + eObjectPicker.eGizmo.SelectedHandle = Gizmo::GizmoHandle::None; + if (!isDragging) { + eObjectPicker.SelectObject(eGameObjects); + } + + } + + wasMouseDown = isMouseDown; // Update previous state + + eObjectPicker.Tick(); } void Editor::Draw() { eObjectPicker.Draw(); } -void Editor::AddObject(FVector* pos, Gfx* model, CollisionType collision, float boundingBoxSize) { +void Editor::AddObject(FVector* pos, Gfx* model, float scale, CollisionType collision, float boundingBoxSize) { if (model != NULL) { eGameObjects.push_back({pos, model, {}, collision, boundingBoxSize}); - GenerateCollisionMesh(eGameObjects.back(), model); + GenerateCollisionMesh(eGameObjects.back(), model, scale); } else { // to bounding box or sphere collision eGameObjects.push_back({pos, model, {}, CollisionType::BOUNDING_BOX, 2.0f}); } diff --git a/src/engine/editor/Editor.h b/src/engine/editor/Editor.h index 86be459d2..829feb054 100644 --- a/src/engine/editor/Editor.h +++ b/src/engine/editor/Editor.h @@ -19,7 +19,7 @@ public: void Draw(); void MouseClick(); void Load(); - void AddObject(FVector* pos, Gfx* model, CollisionType collision, float boundingBoxSize); + void AddObject(FVector* pos, Gfx* model, float scale, CollisionType collision, float boundingBoxSize); private: bool _draw = false; Vec3f _ray; diff --git a/src/engine/editor/EditorMath.cpp b/src/engine/editor/EditorMath.cpp index cd2b3f3b4..a1af28fb9 100644 --- a/src/engine/editor/EditorMath.cpp +++ b/src/engine/editor/EditorMath.cpp @@ -191,11 +191,16 @@ void Clear(MtxF* mf) { mf->zw = 0.0f; } -bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, float& t) { +bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, const FVector& objectPos, float& t) { const float EPSILON = 1e-6f; - FVector edge1 = tri.v1 - tri.v0; - FVector edge2 = tri.v2 - tri.v0; + // Adjust the triangle vertices by the object's position + FVector v0 = tri.v0 + objectPos; + FVector v1 = tri.v1 + objectPos; + FVector v2 = tri.v2 + objectPos; + + FVector edge1 = v1 - v0; + FVector edge2 = v2 - v0; FVector h = ray.Direction.Cross(edge2); float a = edge1.Dot(h); @@ -203,7 +208,7 @@ bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, float& t) { return false; // Ray is parallel to triangle float f = 1.0f / a; - FVector s = ray.Origin - tri.v0; + FVector s = ray.Origin - v0; float u = f * s.Dot(h); if (u < 0.0f || u > 1.0f) @@ -219,6 +224,7 @@ bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, float& t) { return t > EPSILON; } + bool FindClosestObject(const Ray& ray, const std::vector& objects, GameObject& outObject, float& outDistance) { float closestDist = std::numeric_limits::max(); bool found = false; @@ -226,7 +232,7 @@ bool FindClosestObject(const Ray& ray, const std::vector& objects, G for (const auto& obj : objects) { for (const auto& tri : obj.Triangles) { float t; - if (IntersectRayTriangle(ray, tri, t) && t < closestDist) { + if (IntersectRayTriangle(ray, tri, *obj.Pos, t) && t < closestDist) { closestDist = t; outObject = obj; found = true; diff --git a/src/engine/editor/EditorMath.h b/src/engine/editor/EditorMath.h index 5a123b726..7ff5fb6a6 100644 --- a/src/engine/editor/EditorMath.h +++ b/src/engine/editor/EditorMath.h @@ -46,7 +46,7 @@ s32 Inverse(MtxF* src, MtxF* dest); void Copy(MtxF* src, MtxF* dest); void Clear(MtxF* mf); -bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, float& t); +bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, const FVector& objectPos, float& t); diff --git a/src/engine/editor/Gizmo.cpp b/src/engine/editor/Gizmo.cpp index 9341cb23b..b46e50aa1 100644 --- a/src/engine/editor/Gizmo.cpp +++ b/src/engine/editor/Gizmo.cpp @@ -36,13 +36,23 @@ void Gizmo::Load() { BlueCollision.Pos = &Pos; BlueCollision.Model = handle_Cylinder_mesh; - GenerateCollisionMesh(RedCollision, RedCollision.Model); - GenerateCollisionMesh(GreenCollision, GreenCollision.Model); - GenerateCollisionMesh(BlueCollision, BlueCollision.Model); + GenerateCollisionMesh(RedCollision, RedCollision.Model, 0.05f); + GenerateCollisionMesh(GreenCollision, GreenCollision.Model, 0.05f); + GenerateCollisionMesh(BlueCollision, BlueCollision.Model, 0.05f); } void Gizmo::Tick() { - + switch(SelectedHandle) { + case GizmoHandle::X_Axis: + Gizmo::Translate(); + break; + case GizmoHandle::Y_Axis: + Gizmo::Translate(); + break; + case GizmoHandle::Z_Axis: + Gizmo::Translate(); + break; + } } std::pair Gizmo::GetBoundingBox(GizmoHandle handle) { @@ -64,7 +74,6 @@ void Gizmo::StartManipulation(GizmoHandle handle) { case GizmoHandle::X_Axis: break; case GizmoHandle::Y_Axis: - Gizmo::Translate(); break; case GizmoHandle::Z_Axis: break; @@ -102,18 +111,31 @@ void Gizmo::Enable(GameObject* object, Ray ray) { void Gizmo::Translate() { static float length = 180.0f; // Default value + // Prevent nullptr exceptions + if (_selected == NULL || _selected->Pos == NULL) { + return; + } + if (Enabled) { //FVector ray = ScreenRayTrace(); - length = sqrt( pow(_selected->Pos->x - cameras[0].pos[0], 2) + pow(_selected->Pos->y - cameras[0].pos[1], 2) + pow(_selected->Pos->z - cameras[0].pos[2], 2) ); - //_selected->Pos[0] = cameras[0].pos[0] + ray.x * length; - _selected->Pos->x = cameras[0].pos[1] + _ray.y * length; - //_selected->Pos[2] = cameras[0].pos[2] + ray.z * length; + switch(SelectedHandle) { + case GizmoHandle::X_Axis: + _selected->Pos->x = cameras[0].pos[0] + _ray.x * length; + break; + case GizmoHandle::Y_Axis: + _selected->Pos->y = cameras[0].pos[1] + _ray.y * length; + break; + case GizmoHandle::Z_Axis: + _selected->Pos->z = cameras[0].pos[2] + _ray.z * length; + break; + } + Pos = FVector( _selected->Pos->x, _selected->Pos->y, diff --git a/src/engine/editor/Gizmo.h b/src/engine/editor/Gizmo.h index a2275972e..942d3119d 100644 --- a/src/engine/editor/Gizmo.h +++ b/src/engine/editor/Gizmo.h @@ -51,9 +51,9 @@ public: {0, 5, 0}, // Y-Axis (Green) {-5, 0, 0} // Z-Axis (Blue) }; + FVector _ray; private: bool _draw = false; - FVector _ray; GameObject* _selected; diff --git a/src/engine/editor/ObjectPicker.cpp b/src/engine/editor/ObjectPicker.cpp index 636c4b1a2..0bb4e1c61 100644 --- a/src/engine/editor/ObjectPicker.cpp +++ b/src/engine/editor/ObjectPicker.cpp @@ -33,6 +33,10 @@ void ObjectPicker::Load() { eGizmo.Load(); } +void ObjectPicker::Tick() { + eGizmo.Tick(); +} + void ObjectPicker::SelectObject(std::vector& objects) { Ray ray; ray.Origin = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]); @@ -49,6 +53,53 @@ void ObjectPicker::SelectObject(std::vector& objects) { } } +void ObjectPicker::DragHandle() { + Ray ray; + ray.Origin = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]); + ray.Direction = ScreenRayTrace(); + + // Skip if a drag is already in progress + if (eGizmo.SelectedHandle != Gizmo::GizmoHandle::None) { + eGizmo._ray = ray.Direction; + return; + } + + // Is the gizmo being dragged? + if (eGizmo.Enabled) { + for (auto tri = eGizmo.RedCollision.Triangles.begin(); tri < eGizmo.RedCollision.Triangles.end(); tri++) { + float t; + FVector pos = FVector(eGizmo.Pos.x, eGizmo.Pos.y, eGizmo.Pos.z - eGizmo._gizmoOffset); + if (IntersectRayTriangle(ray, *tri, pos, t)) { + //eGizmo.StartManipulation(Gizmo::GizmoHandle::X_Axis); + eGizmo.SelectedHandle = Gizmo::GizmoHandle::Z_Axis; + eGizmo._ray = ray.Direction; + return; // Stop checking objects if we selected a Gizmo handle + } + } + + for (auto tri = eGizmo.GreenCollision.Triangles.begin(); tri < eGizmo.GreenCollision.Triangles.end(); tri++) { + float t; + FVector pos = FVector(eGizmo.Pos.x - eGizmo._gizmoOffset, eGizmo.Pos.y, eGizmo.Pos.z); + if (IntersectRayTriangle(ray, *tri, pos, t)) { + //eGizmo.StartManipulation(Gizmo::GizmoHandle::Y_Axis); + eGizmo.SelectedHandle = Gizmo::GizmoHandle::X_Axis; + eGizmo._ray = ray.Direction; + return; // Stop checking objects if we selected a Gizmo handle + } + } + + for (auto tri = eGizmo.BlueCollision.Triangles.begin(); tri < eGizmo.BlueCollision.Triangles.end(); tri++) { + float t; + FVector pos = FVector(eGizmo.Pos.x, eGizmo.Pos.y + eGizmo._gizmoOffset, eGizmo.Pos.z); + if (IntersectRayTriangle(ray, *tri, pos, t)) { + eGizmo.SelectedHandle = Gizmo::GizmoHandle::Y_Axis; + eGizmo._ray = ray.Direction; + return; // Stop checking objects if we selected a Gizmo handle + } + } + } +} + void ObjectPicker::Draw() { if (_selected != nullptr) { eGizmo.Draw(); @@ -56,41 +107,6 @@ void ObjectPicker::Draw() { } void ObjectPicker::FindObject(Ray ray, std::vector& objects) { - // Is the gizmo being clicked? - if (eGizmo.Enabled) { - Gizmo::GizmoHandle handle = Gizmo::GizmoHandle::None; - - for (auto tri = eGizmo.RedCollision.Triangles.begin(); tri < eGizmo.RedCollision.Triangles.end(); tri++) { - float t; - if (IntersectRayTriangle(ray, *tri, t)) { - handle = Gizmo::GizmoHandle::X_Axis; - break; - } - } - - for (auto tri = eGizmo.GreenCollision.Triangles.begin(); tri < eGizmo.GreenCollision.Triangles.end(); tri++) { - float t; - if (IntersectRayTriangle(ray, *tri, t)) { - handle = Gizmo::GizmoHandle::Y_Axis; - break; - } - } - - for (auto tri = eGizmo.BlueCollision.Triangles.begin(); tri < eGizmo.BlueCollision.Triangles.end(); tri++) { - float t; - if (IntersectRayTriangle(ray, *tri, t)) { - handle = Gizmo::GizmoHandle::Z_Axis; - break; - } - } - - if (handle != Gizmo::GizmoHandle::None) { - eGizmo.StartManipulation(handle); - return; // Stop checking objects if we selected a Gizmo handle - } - } - - //s32 type = 0; bool found = false; for (auto& object : objects) { float boundingBox = object.BoundingBoxSize; @@ -102,7 +118,7 @@ void ObjectPicker::FindObject(Ray ray, std::vector& objects) { switch(object.Collision) { case CollisionType::VTX_INTERSECT: for (const auto& tri : object.Triangles) { - if (IntersectRayTriangle(ray, tri, t)) { + if (IntersectRayTriangle(ray, tri, *object.Pos, t)) { printf("\nSELECTED OBJECT\n\n"); _selected = &object; } diff --git a/src/engine/editor/ObjectPicker.h b/src/engine/editor/ObjectPicker.h index b8b0e0c46..1bf9afa1f 100644 --- a/src/engine/editor/ObjectPicker.h +++ b/src/engine/editor/ObjectPicker.h @@ -11,9 +11,12 @@ class ObjectPicker { ObjectPicker(); void SelectObject(std::vector& objects); + void DragHandle(); void Draw(); void FindObject(Ray ray, std::vector& objects); void Load(); + void Tick(); + Gizmo eGizmo; private: bool _draw = false; Vec3f _ray; @@ -25,5 +28,4 @@ class ObjectPicker { void DrawObj(float length); - Gizmo eGizmo; };