From 529f7c8bcf809fc2e06daaf5d82ea59e97af6fea Mon Sep 17 00:00:00 2001 From: MegaMech Date: Mon, 7 Apr 2025 16:44:14 -0600 Subject: [PATCH] Failed attempt at transforming collision --- src/engine/CoreMath.h | 10 ++++ src/engine/editor/Collision.cpp | 86 +++++++++++++++++++++++++++++- src/engine/editor/Collision.h | 1 + src/engine/editor/EditorMath.cpp | 40 +++++++++++--- src/engine/editor/EditorMath.h | 1 + src/engine/editor/Gizmo.cpp | 41 ++++++++++---- src/engine/editor/Gizmo.h | 6 ++- src/engine/editor/ObjectPicker.cpp | 23 ++++---- 8 files changed, 181 insertions(+), 27 deletions(-) diff --git a/src/engine/CoreMath.h b/src/engine/CoreMath.h index 1a98c3763..b82324d3e 100644 --- a/src/engine/CoreMath.h +++ b/src/engine/CoreMath.h @@ -143,6 +143,16 @@ struct IRotator { yaw = y * (UINT16_MAX / 360); roll = r * (UINT16_MAX / 360); } + + // Convert to radians as FVector + [[nodiscard]] FVector ToRadians() const { + constexpr float scale = 2.0f * M_PI / 65536.0f; + return FVector( + pitch * scale, + yaw * scale, + roll * scale + ); + } #endif // __cplusplus }; diff --git a/src/engine/editor/Collision.cpp b/src/engine/editor/Collision.cpp index e0e983885..ecde8d340 100644 --- a/src/engine/editor/Collision.cpp +++ b/src/engine/editor/Collision.cpp @@ -1,5 +1,14 @@ #include "Collision.h" +#include +#include +#include "Matrix.h" + +extern "C" { +#include "main.h" +#include "other_textures.h" +} + namespace Editor { void GenerateCollisionMesh(GameObject* object, Gfx* model, float scale) { int8_t opcode; @@ -16,7 +25,6 @@ namespace Editor { hi = ptr->words.w1; opcode = (EDITOR_GFX_GET_OPCODE(lo) >> 24); - switch(opcode) { case G_DL: GenerateCollisionMesh(object, (Gfx*)hi, scale); @@ -25,15 +33,25 @@ namespace Editor { ptr++; GenerateCollisionMesh(object, (Gfx*)ResourceGetDataByCrc(((uint64_t)(ptr->words.w0 << 32)) + ptr->words.w1), scale); break; + case G_DL_OTR_FILEPATH: + // printf("otr filepath: %s\n", (const char*)hi); + GenerateCollisionMesh(object, (Gfx*)ResourceGetDataByName((const char*)hi), scale); + break; case G_VTX: vtx = (Vtx*)ptr->words.w1; break; case G_VTX_OTR_HASH: { - const uintptr_t offset = hi; ptr++; vtx = (Vtx*)ResourceGetDataByCrc(((uint64_t)(ptr->words.w0 << 32)) + ptr->words.w1); break; } + case G_VTX_OTR_FILEPATH: { + const const char* filePath = (const char*)hi; + ptr++; + size_t vtxDataOff = ptr->words.w1 & 0xFFFF; + vtx = ( (Vtx*)ResourceGetDataByName(filePath) ) + vtxDataOff; + break; + } case G_TRI1: { if (vtx == NULL) { ptr++; @@ -50,6 +68,25 @@ namespace Editor { object->Triangles.push_back({p1, p2, p3}); break; } + case G_TRI1_OTR: { + if (vtx == NULL) { + ptr++; + continue; + } + + // The shift values here are different than the above. No idea why. But it has to be this way. + uint32_t v1 = (lo & 0x0000FFFF); + uint32_t v2 = (hi >> 16); + uint32_t v3 = (hi & 0x0000FFFF); + + FVector p1 = FVector(vtx[v1].v.ob[0], vtx[v1].v.ob[1], vtx[v1].v.ob[2]); + FVector p2 = FVector(vtx[v2].v.ob[0], vtx[v2].v.ob[1], vtx[v2].v.ob[2]); + FVector p3 = FVector(vtx[v3].v.ob[0], vtx[v3].v.ob[1], vtx[v3].v.ob[2]); + + object->Triangles.push_back({p1, p2, p3}); + + break; + } case G_TRI2: { if (vtx == NULL) { ptr++; @@ -103,4 +140,49 @@ namespace Editor { ptr++; } } + + std::unordered_map> gDebugObjVtxCache; + + // Render a collision model + void DebugCollision(GameObject* obj, FVector pos, IRotator rot, FVector scale, const std::vector& triangles) { + if (obj == NULL || triangles.empty()) { + return; + } + + gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF); + + auto& vtxBuffer = gDebugObjVtxCache[obj]; + if (vtxBuffer.empty()) { + for (const auto& tri : triangles) { + vtxBuffer.push_back({(s16)tri.v0.x, (s16)tri.v0.y, (s16)tri.v0.z, 0, {0, 0}, {255, 255, 255, 255}}); + vtxBuffer.push_back({(s16)tri.v1.x, (s16)tri.v1.y, (s16)tri.v1.z, 0, {0, 0}, {255, 255, 255, 255}}); + vtxBuffer.push_back({(s16)tri.v2.x, (s16)tri.v2.y, (s16)tri.v2.z, 0, {0, 0}, {255, 255, 255, 255}}); + } + } + + // Setup matrix and render state + Mat4 mtx; + ApplyMatrixTransformations(mtx, pos, rot, scale); + Editor_AddMatrix(mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPSetGeometryMode(gDisplayListHead++, G_FOG); + gDPPipeSync(gDisplayListHead++); + gDPSetCombineMode(gDisplayListHead++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); + gSPTexture(gDisplayListHead++, 0, 0, 0, G_TX_RENDERTILE, G_OFF); + gDPSetRenderMode(gDisplayListHead++, G_RM_FOG_SHADE_A, G_RM_AA_ZB_OPA_SURF2); + uint32_t hash = (uint32_t)((uintptr_t)obj ^ ((uintptr_t)obj >> 16)); + u8 r = (hash >> 16) & 0xFF; + u8 g = (hash >> 8) & 0xFF; + u8 b = hash & 0xFF; + + gDPSetPrimColor(gDisplayListHead++, 0, 0, r, g, b, 255); + + // Render triangles in batches of 3 + for (size_t i = 0; i + 2 < vtxBuffer.size(); i += 3) { + gSPVertex(gDisplayListHead++, (uintptr_t)&vtxBuffer[i], 3, 0); + gSP1Triangle(gDisplayListHead++, 0, 1, 2, 0); + } + + gSPSetGeometryMode(gDisplayListHead++, G_CULL_BACK | G_ZBUFFER); + } } diff --git a/src/engine/editor/Collision.h b/src/engine/editor/Collision.h index 8ae4660e4..ee8fef4af 100644 --- a/src/engine/editor/Collision.h +++ b/src/engine/editor/Collision.h @@ -19,4 +19,5 @@ namespace Editor { void GenerateCollisionMesh(GameObject* object, Gfx* model, float scale); + void DebugCollision(GameObject* obj, FVector pos, IRotator rot, FVector scale, const std::vector& triangles); } \ No newline at end of file diff --git a/src/engine/editor/EditorMath.cpp b/src/engine/editor/EditorMath.cpp index fe365ef10..8aa10b881 100644 --- a/src/engine/editor/EditorMath.cpp +++ b/src/engine/editor/EditorMath.cpp @@ -133,9 +133,6 @@ s32 Inverse(MtxF* src, MtxF* dest) { // Reaching row = 4 means the column is either all 0 or a duplicate column. // Therefore src is a singular matrix (0 determinant). - // osSyncPrintf(VT_COL(YELLOW, BLACK)); - // osSyncPrintf("Skin_Matrix_InverseMatrix():逆行列つくれません\n"); - // osSyncPrintf(VT_RST); return 2; } @@ -215,9 +212,9 @@ bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, const FVector& ob const float EPSILON = 1e-6f; // 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 v0 = TransformPoint(tri.v0); + FVector v1 = TransformPoint(tri.v1); + FVector v2 = TransformPoint(tri.v2); DebugPoss = v0; @@ -246,6 +243,37 @@ bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, const FVector& ob return t > EPSILON; } +// Apply location, rotation, and scale transformations. +FVector TransformPoint(const FVector& point, const FVector& pos, const IRotator& n64Rot, const FVector& scale) { + FVector rot = n64Rot.ToRadians(); + + // Apply scale + FVector scaled = FVector(point.x * scale.x, point.y * scale.y, point.z * scale.z); + + // Apply rotation (ZXY order, typical in games) + float cz = cos(rot.z), sz = sin(rot.z); + float cx = cos(rot.x), sx = sin(rot.x); + float cy = cos(rot.y), sy = sin(rot.y); + + // Rotate around Z axis + float x1 = scaled.x * cz - scaled.y * sz; + float y1 = scaled.x * sz + scaled.y * cz; + float z1 = scaled.z; + + // Rotate around X axis + float y2 = y1 * cx - z1 * sx; + float z2 = y1 * sx + z1 * cx; + float x2 = x1; + + // Rotate around Y axis + float x3 = x2 * cy + z2 * sy; + float y3 = y2; + float z3 = -x2 * sy + z2 * cy; + + // Apply translation + return FVector(x3 + pos.x, y3 + pos.y, z3 + pos.z); +} + bool IntersectRaySphere(const Ray& ray, const FVector& sphereCenter, float radius, float& t) { const float EPSILON = 1e-6f; diff --git a/src/engine/editor/EditorMath.h b/src/engine/editor/EditorMath.h index 9e5b87c6a..26d5e1497 100644 --- a/src/engine/editor/EditorMath.h +++ b/src/engine/editor/EditorMath.h @@ -41,6 +41,7 @@ void Clear(MtxF* mf); bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, const FVector& objectPos, float& t); bool IntersectRaySphere(const Ray& ray, const FVector& sphereCenter, float radius, float& t); +FVector TransformPoint(const FVector& point, const FVector& pos, const IRotator& n64Rot, const FVector& scale); void Editor_MatrixIdentity(Mat4 mtx); void Editor_AddMatrix(Mat4 mtx, int32_t flags); diff --git a/src/engine/editor/Gizmo.cpp b/src/engine/editor/Gizmo.cpp index 4f8e4d0a9..3bc587f70 100644 --- a/src/engine/editor/Gizmo.cpp +++ b/src/engine/editor/Gizmo.cpp @@ -6,10 +6,12 @@ #include "EditorMath.h" #include "Gizmo.h" +#include "Collision.h" #include "port/Engine.h" #include #include + #include "engine/actors/Ship.h" #include "port/Game.h" #include "Handle.h" @@ -26,18 +28,34 @@ extern "C" { namespace Editor { void Gizmo::Load() { + /* Translate handle collision */ RedCollision.Pos = &Pos; - RedCollision.Model = handle_Cylinder_mesh; + RedCollision.Model = (Gfx*)"__OTR__editor/gizmo/translate_handle_red"; GreenCollision.Pos = &Pos; - GreenCollision.Model = handle_Cylinder_mesh; + GreenCollision.Model = (Gfx*)"__OTR__editor/gizmo/translate_handle_green"; BlueCollision.Pos = &Pos; - BlueCollision.Model = handle_Cylinder_mesh; + BlueCollision.Model = (Gfx*)"__OTR__editor/gizmo/translate_handle_blue"; - GenerateCollisionMesh(&RedCollision, RedCollision.Model, 0.05f); - GenerateCollisionMesh(&GreenCollision, GreenCollision.Model, 0.05f); - GenerateCollisionMesh(&BlueCollision, BlueCollision.Model, 0.05f); + /* Rotate handle Collision */ + RedRotateCollision.Pos = &Pos; + RedRotateCollision.Model = (Gfx*)"__OTR__editor/gizmo/rot_handle_red"; + + GreenRotateCollision.Pos = &Pos; + GreenRotateCollision.Model = (Gfx*)"__OTR__editor/gizmo/rot_handle_green"; + + BlueRotateCollision.Pos = &Pos; + BlueRotateCollision.Model = (Gfx*)"__OTR__editor/gizmo/rot_handle_blue"; + + //GenerateCollisionMesh(&RedCollision, (Gfx*)(handle_Cylinder_mesh), 1); + GenerateCollisionMesh(&RedCollision, (Gfx*)LOAD_ASSET_RAW(RedCollision.Model), 0.5f); + GenerateCollisionMesh(&GreenCollision, (Gfx*)LOAD_ASSET_RAW(GreenCollision.Model), 0.5f); + GenerateCollisionMesh(&BlueCollision, (Gfx*)LOAD_ASSET_RAW(BlueCollision.Model), 0.5f); + + GenerateCollisionMesh(&RedRotateCollision, (Gfx*)LOAD_ASSET_RAW(RedRotateCollision.Model), 0.15f); + GenerateCollisionMesh(&GreenRotateCollision, (Gfx*)LOAD_ASSET_RAW(GreenRotateCollision.Model), 0.15f); + GenerateCollisionMesh(&BlueRotateCollision, (Gfx*)LOAD_ASSET_RAW(BlueRotateCollision.Model), 0.15f); } void Gizmo::Tick() { @@ -169,7 +187,6 @@ void Gizmo::Rotate() { // Set rotation sensitivity diff = diff * 100.0f; - switch (SelectedHandle) { case GizmoHandle::X_Axis: _selected->Rot->pitch = (uint16_t)InitialRotation.pitch + diff.x; @@ -227,6 +244,12 @@ void Gizmo::Scale() { void Gizmo::Draw() { if (Enabled) { DrawHandles(); + DebugCollision(&RedCollision, Pos, {0, 0, 0}, {0.05f, 0.05f, 0.05f}, RedCollision.Triangles); + DebugCollision(&BlueCollision, Pos, {90, 0, 0}, {0.05f, 0.05f, 0.05f}, BlueCollision.Triangles); + DebugCollision(&GreenCollision, Pos, {0, 90, 0}, {0.05f, 0.05f, 0.05f}, GreenCollision.Triangles); + DebugCollision(&RedRotateCollision, Pos, {0, 0, 0}, {0.15f, 0.15f, 0.15f}, RedRotateCollision.Triangles); + //DebugCollision((uintptr_t)_selected, Pos, BlueRotateCollision.Triangles); + //DebugCollision((uintptr_t)_selected, Pos, GreenRotateCollision.Triangles); } } @@ -251,7 +274,7 @@ void Gizmo::DrawHandles() { _gizmoOffset = 8.0f; greenRot = {0, 90, 0}; blueRot = {90, 0, 0}; - scale = {0.05f, 0.05f, 0.05f}; + scale = {1, 1, 1}; break; case TranslationMode::Rotate: center = nullptr; // No All_Axis drag button for Rotation @@ -259,7 +282,7 @@ void Gizmo::DrawHandles() { greenHandle = "__OTR__editor/gizmo/rot_handle_green"; redHandle = "__OTR__editor/gizmo/rot_handle_red"; _gizmoOffset = 0.0f; - scale = {0.2f, 0.2f, 0.2f}; + scale = {0.15f, 0.15f, 0.15f}; break; case TranslationMode::Scale: center = "__OTR__editor/gizmo/center_handle"; diff --git a/src/engine/editor/Gizmo.h b/src/engine/editor/Gizmo.h index a56c0c7fe..efb53dbd3 100644 --- a/src/engine/editor/Gizmo.h +++ b/src/engine/editor/Gizmo.h @@ -56,9 +56,13 @@ public: GameObject GreenCollision; GameObject BlueCollision; + GameObject RedRotateCollision; + GameObject GreenRotateCollision; + GameObject BlueRotateCollision; + FVector Pos; // Global scene view IRotator Rot = {0, 0, 0}; - float AllAxisRadius = 4.0f; // Free move selection radius + float AllAxisRadius = 3.0f; // Free move selection radius float PickDistance; FVector _cursorOffset; float _gizmoOffset = 8.0f; diff --git a/src/engine/editor/ObjectPicker.cpp b/src/engine/editor/ObjectPicker.cpp index c2e682a87..5319801e7 100644 --- a/src/engine/editor/ObjectPicker.cpp +++ b/src/engine/editor/ObjectPicker.cpp @@ -69,18 +69,23 @@ void ObjectPicker::DragHandle() { // Is the gizmo being dragged? if (eGizmo.Enabled) { float t; - if (IntersectRaySphere(ray, eGizmo.Pos, eGizmo.AllAxisRadius, t)) { - eGizmo.SelectedHandle = Gizmo::GizmoHandle::All_Axis; - eGizmo._ray = ray.Direction; - FVector clickPosition = ray.Origin + ray.Direction * t; - eGizmo._cursorOffset = eGizmo.Pos - clickPosition; - eGizmo.PickDistance = t; - return; + + // No all_axis grab for rotate + if (static_cast(CVarGetInteger("eGizmoMode", 0)) != Gizmo::TranslationMode::Rotate) { + if (IntersectRaySphere(ray, eGizmo.Pos, eGizmo.AllAxisRadius, t)) { + eGizmo.SelectedHandle = Gizmo::GizmoHandle::All_Axis; + eGizmo._ray = ray.Direction; + FVector clickPosition = ray.Origin + ray.Direction * t; + eGizmo._cursorOffset = eGizmo.Pos - clickPosition; + eGizmo.PickDistance = t; + return; + } } 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); + //FVector pos = TransformPoint(*tri, FVector(eGizmo.Pos.x, eGizmo.Pos.y, eGizmo.Pos.z - eGizmo._gizmoOffset), {0, 90, 0}, {1, 1, 1}); + if (IntersectRayTriangle(ray, *tri, pos, t)) { eGizmo.SelectedHandle = Gizmo::GizmoHandle::Z_Axis; eGizmo._ray = ray.Direction; @@ -93,7 +98,7 @@ void ObjectPicker::DragHandle() { 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); + FVector pos = TransformPoint(FVector(eGizmo.Pos.x - eGizmo._gizmoOffset, eGizmo.Pos.y, eGizmo.Pos.z), {90, 0, 0}, {1, 1, 1}); if (IntersectRayTriangle(ray, *tri, pos, t)) { eGizmo.SelectedHandle = Gizmo::GizmoHandle::X_Axis; eGizmo._ray = ray.Direction;