diff --git a/src/engine/editor/EditorMath.cpp b/src/engine/editor/EditorMath.cpp index d590a954a..260ceb5b1 100644 --- a/src/engine/editor/EditorMath.cpp +++ b/src/engine/editor/EditorMath.cpp @@ -305,6 +305,18 @@ bool IntersectRaySphere(const Ray& ray, const FVector& sphereCenter, float radiu // return false; // } +// Transform a matrix to a matrix identity +void Editor_Matrixidentity(Mat4 mtx) { + register s32 i; + register s32 k; + + for (i = 0; i < 4; i++) { + for (k = 0; k < 4; k++) { + mtx[i][k] = (i == k) ? 1.0f : 0.0f; + } + } +} + void Editor_AddMatrix(Mat4 mtx, int32_t flags) { EditorMatrix.emplace_back(); guMtxF2L(mtx, &EditorMatrix.back()); @@ -323,10 +335,8 @@ float CalculateAngle(const FVector& start, const FVector& end) { return acos(cosAngle); } -// Used for gSPLights1 void SetDirectionFromRotator(IRotator rot, s8 direction[3]) { - // Subtract 0x4000 to lineup the rotator with the light direction - float yaw = (rot.yaw - 0x4000) * (M_PI / 32768.0f); // Convert from n64 binary angles 0-0xFFFF 0-360 degrees to radians + float yaw = (rot.yaw) * (M_PI / 32768.0f); // Convert from n64 binary angles 0-0xFFFF 0-360 degrees to radians float pitch = rot.pitch * (M_PI / 32768.0f); // Compute unit direction vector @@ -342,6 +352,19 @@ void SetDirectionFromRotator(IRotator rot, s8 direction[3]) { //printf("Light dir %d %d %d (from rot 0x%X 0x%X 0x%X)\n", direction[0], direction[1], direction[2], rotator[0], rotator[1], rotator[2]); } +void SetRotatorFromDirection(FVector direction, IRotator* rot) { + // Compute pitch (inverse of -sinf(pitch)) + float pitch = -asinf(direction.y); + + // Compute yaw (inverse of cosf(yaw) * cosf(pitch)) + float yaw = atan2f(-direction.z, direction.x); + + // Convert back to N64 angles (0-0xFFFF range) + rot->pitch = (s16)(pitch * (32768.0f / M_PI)); + rot->yaw = (s16)(yaw * (32768.0f / M_PI)); + rot->roll = 0; // Assume no roll, since it's undefined from direction alone +} + FVector GetPositionAheadOfCamera(f32 dist) { FVector pos = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]); diff --git a/src/engine/editor/EditorMath.h b/src/engine/editor/EditorMath.h index f2b9e8835..c28ccea48 100644 --- a/src/engine/editor/EditorMath.h +++ b/src/engine/editor/EditorMath.h @@ -42,7 +42,9 @@ 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); +void Editor_Matrixidentity(Mat4 mtx); void Editor_AddMatrix(Mat4 mtx, int32_t flags); float CalculateAngle(const FVector& start, const FVector& end); void SetDirectionFromRotator(IRotator rot, s8 direction[3]); +void SetRotatorFromDirection(FVector direction, IRotator* rot); FVector GetPositionAheadOfCamera(f32 dist); diff --git a/src/engine/editor/Gizmo.cpp b/src/engine/editor/Gizmo.cpp index 554367a05..86c90fa0d 100644 --- a/src/engine/editor/Gizmo.cpp +++ b/src/engine/editor/Gizmo.cpp @@ -20,6 +20,7 @@ extern "C" { #include "actors.h" #include "camera.h" #include "src/racing/collision.h" +#include "math_util.h" } namespace Editor { @@ -201,9 +202,42 @@ void Gizmo::Draw() { void Gizmo::DrawHandles() { Mat4 mainMtx; + Gfx* handle = handle_Cylinder_mesh; + Gfx* center = (Gfx*)"__OTR__gizmo/gizmo_center_button"; + switch(static_cast(CVarGetInteger("eGizmoMode", 0))) { + case TranslationMode::Move: + handle = handle_Cylinder_mesh; + break; + case TranslationMode::Rotate: + handle = handle_Cylinder_mesh; + center = NULL; + break; + case TranslationMode::Scale: + handle = (Gfx*)"__OTR__gizmo/scale_handle"; + break; + } + ApplyMatrixTransformations(mainMtx, Pos, Rot, {1, 1, 1}); Editor_AddMatrix(mainMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + if (center) { + Mat4 CenterMtx; + Editor_Matrixidentity(CenterMtx); + + // Calculate camera-to-object distance + FVector cameraDir = FVector(Pos.x - cameras[0].pos[0], Pos.y - cameras[0].pos[1], Pos.z - cameras[0].pos[2]); + cameraDir = cameraDir.Normalize(); + + IRotator centerRot; + SetRotatorFromDirection(cameraDir, ¢erRot); + centerRot.pitch += 0x4000; // Align mesh to face camera since it was not exported facing the correct direction + centerRot.yaw += 0x4000; + + ApplyMatrixTransformations(CenterMtx, Pos, centerRot, FVector(0.06f, 0.06f, 0.06f)); + Editor_AddMatrix(CenterMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gDisplayListHead++, center); + } + handle_f3dlite_material_lights = gdSPDefLights1( 0x7F, 0x7F, 0x7F, 0xFF, 0, 0, 0x49, 0x49, 0x49); @@ -211,7 +245,7 @@ void Gizmo::DrawHandles() { Mat4 RedXMtx; ApplyMatrixTransformations(RedXMtx, FVector(Pos.x, Pos.y, Pos.z - _gizmoOffset), Rot, {0.05f, 0.05f, 0.05f}); Editor_AddMatrix(RedXMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(gDisplayListHead++, handle_Cylinder_mesh); + gSPDisplayList(gDisplayListHead++, handle); handle_f3dlite_material_lights = gdSPDefLights1( 0x7F, 0x7F, 0x7F, 0, 0xFF, 0, 0x49, 0x49, 0x49); @@ -220,7 +254,7 @@ void Gizmo::DrawHandles() { ApplyMatrixTransformations(GreenYMtx, FVector(Pos.x - _gizmoOffset, Pos.y, Pos.z), IRotator(0, 90, 0), {0.05f, 0.05f, 0.05f}); Editor_AddMatrix(GreenYMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(gDisplayListHead++, handle_Cylinder_mesh); + gSPDisplayList(gDisplayListHead++, handle); handle_f3dlite_material_lights = gdSPDefLights1( 0x7F, 0x7F, 0x7F, @@ -230,6 +264,6 @@ void Gizmo::DrawHandles() { ApplyMatrixTransformations(BlueZMtx, FVector(Pos.x, Pos.y + _gizmoOffset, Pos.z), IRotator(90, 0, 0), {0.05f, 0.05f, 0.05f}); Editor_AddMatrix(BlueZMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(gDisplayListHead++, handle_Cylinder_mesh); + gSPDisplayList(gDisplayListHead++, handle); } } diff --git a/src/engine/editor/Light.cpp b/src/engine/editor/Light.cpp index 8f2764f3c..047575348 100644 --- a/src/engine/editor/Light.cpp +++ b/src/engine/editor/Light.cpp @@ -57,7 +57,10 @@ size_t LightObject::NumLights = 0; void LightObject::Draw() { Mat4 mtx; - ApplyMatrixTransformations(mtx, LightPos, LightRot, LightScale); + // Account for object not facing the correct direction when exported + IRotator rot = LightRot; + rot.yaw += 0x4000; + ApplyMatrixTransformations(mtx, LightPos, rot, LightScale); Editor_AddMatrix(mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(gDisplayListHead++, sun_LightModel_mesh); gSPDisplayList(gDisplayListHead++, handle_Cylinder_mesh);