From 08f0d261d1eb92a0599228d04e27a3175a0050e5 Mon Sep 17 00:00:00 2001 From: MegaMech Date: Wed, 26 Feb 2025 15:46:20 -0700 Subject: [PATCH] wip --- courses/harbour/ship_model.c | 9 + src/actors/train/render.inc.c | 74 +-- src/engine/CoreMath.h | 10 + src/engine/actors/Ship.cpp | 18 +- src/engine/editor/ColourIdFramebuffer.cpp | 25 + src/engine/editor/ColourIdFramebuffer.h | 0 src/engine/editor/Editor.cpp | 249 +--------- src/engine/editor/Editor.h | 12 +- src/engine/editor/EditorMath.cpp | 188 ++++++++ src/engine/editor/EditorMath.h | 26 ++ src/engine/editor/Gizmo.cpp | 173 +++++++ src/engine/editor/Gizmo.h | 543 ++++++++++++++++++++++ src/engine/editor/ObjectPicker.cpp | 108 +++++ src/engine/editor/ObjectPicker.h | 28 ++ src/main.c | 1 - src/racing/framebuffer_effects.c | 13 +- 16 files changed, 1181 insertions(+), 296 deletions(-) create mode 100644 src/engine/editor/ColourIdFramebuffer.cpp create mode 100644 src/engine/editor/ColourIdFramebuffer.h create mode 100644 src/engine/editor/EditorMath.cpp create mode 100644 src/engine/editor/EditorMath.h create mode 100644 src/engine/editor/Gizmo.cpp create mode 100644 src/engine/editor/Gizmo.h create mode 100644 src/engine/editor/ObjectPicker.cpp create mode 100644 src/engine/editor/ObjectPicker.h diff --git a/courses/harbour/ship_model.c b/courses/harbour/ship_model.c index c46e5d3e0..8f55daa63 100644 --- a/courses/harbour/ship_model.c +++ b/courses/harbour/ship_model.c @@ -3914,6 +3914,15 @@ Vtx wheels_Spaghetti_002_mesh_vtx_0[111] = { }; Gfx wheels_Spaghetti_002_mesh_tri_0[] = { + gsDPPipeSync(), + gsDPSetCycleType(G_CYC_1CYCLE), + gsDPSetRenderMode(G_RM_OPA_SURF, G_RM_OPA_SURF2), + gsDPSetCombineMode(G_CC_PRIMITIVE, G_CC_PRIMITIVE), + gsDPSetPrimColor(0, 0, 255, 0, 0, 255), + + gsSPClearGeometryMode(G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR), + gsSPSetGeometryMode(G_SHADE | G_SHADING_SMOOTH), + gsSPVertex(wheels_Spaghetti_002_mesh_vtx_0 + 0, 32, 0), gsSP2Triangles(0, 1, 2, 0, 3, 1, 0, 0), gsSP2Triangles(4, 3, 0, 0, 4, 0, 5, 0), diff --git a/src/actors/train/render.inc.c b/src/actors/train/render.inc.c index d5d4d2203..825aa4cd9 100644 --- a/src/actors/train/render.inc.c +++ b/src/actors/train/render.inc.c @@ -15,9 +15,9 @@ void render_actor_train_engine(Camera* camera, struct TrainCar* actor) { UNUSED s32 pad[2]; s32 maxObjectsReached; Vec3f sp160; - Mat4 sp120; - Mat4 spE0; - Mat4 spA0; + Mat4 mainMtx; + Mat4 objectMtx; + Mat4 resultMtx; f32 distance = is_within_render_distance(camera->pos, actor->pos, camera->rot[1], 2500.0f, gCameraZoom[camera - camera1], 9000000.0f); @@ -36,8 +36,8 @@ void render_actor_train_engine(Camera* camera, struct TrainCar* actor) { gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING); - mtxf_pos_rotation_xyz(sp120, actor->pos, actor->rot); - maxObjectsReached = render_set_position(sp120, 0) == 0; + mtxf_pos_rotation_xyz(mainMtx, actor->pos, actor->rot); + maxObjectsReached = render_set_position(mainMtx, 0) == 0; if (maxObjectsReached) { return; } @@ -62,12 +62,12 @@ void render_actor_train_engine(Camera* camera, struct TrainCar* actor) { gSPClearGeometryMode(gDisplayListHead++, G_CULL_BACK); gSPDisplayList(gDisplayListHead++, d_course_kalimari_desert_dl_22D28); - mtxf_rotate_x(sp120, actor->wheelRot); + mtxf_rotate_x(mainMtx, actor->wheelRot); vec3f_set(sp160, 17.0f, 6.0f, 32.0f); - mtxf_translate(spE0, sp160); - mtxf_multiplication(spA0, sp120, spE0); + mtxf_translate(objectMtx, sp160); + mtxf_multiplication(resultMtx, mainMtx, objectMtx); - maxObjectsReached = render_set_position(spA0, 3) == 0; + maxObjectsReached = render_set_position(resultMtx, 3) == 0; if (maxObjectsReached) { return; } @@ -75,12 +75,12 @@ void render_actor_train_engine(Camera* camera, struct TrainCar* actor) { gSPDisplayList(gDisplayListHead++, d_course_kalimari_desert_dl_22DB8); gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); - mtxf_rotate_x(sp120, actor->wheelRot); + mtxf_rotate_x(mainMtx, actor->wheelRot); vec3f_set(sp160, -17.0, 6.0f, 32.0f); - mtxf_translate(spE0, sp160); - mtxf_multiplication(spA0, sp120, spE0); + mtxf_translate(objectMtx, sp160); + mtxf_multiplication(resultMtx, mainMtx, objectMtx); - maxObjectsReached = render_set_position(spA0, 3) == 0; + maxObjectsReached = render_set_position(resultMtx, 3) == 0; if (maxObjectsReached) { return; } @@ -88,12 +88,12 @@ void render_actor_train_engine(Camera* camera, struct TrainCar* actor) { gSPDisplayList(gDisplayListHead++, d_course_kalimari_desert_dl_22DB8); gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); - mtxf_rotate_x(sp120, (s16) (actor->wheelRot + 0x16C)); + mtxf_rotate_x(mainMtx, (s16) (actor->wheelRot + 0x16C)); vec3f_set(sp160, 17.0f, 6.0f, 16.0f); - mtxf_translate(spE0, sp160); - mtxf_multiplication(spA0, sp120, spE0); + mtxf_translate(objectMtx, sp160); + mtxf_multiplication(resultMtx, mainMtx, objectMtx); - maxObjectsReached = render_set_position(spA0, 3) == 0; + maxObjectsReached = render_set_position(resultMtx, 3) == 0; if (maxObjectsReached) { return; } @@ -101,12 +101,12 @@ void render_actor_train_engine(Camera* camera, struct TrainCar* actor) { gSPDisplayList(gDisplayListHead++, d_course_kalimari_desert_dl_22DB8); gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); - mtxf_rotate_x(sp120, (s16) (actor->wheelRot + 0x16C)); + mtxf_rotate_x(mainMtx, (s16) (actor->wheelRot + 0x16C)); vec3f_set(sp160, -17.0f, 6.0f, 16.0f); - mtxf_translate(spE0, sp160); - mtxf_multiplication(spA0, sp120, spE0); + mtxf_translate(objectMtx, sp160); + mtxf_multiplication(resultMtx, mainMtx, objectMtx); - maxObjectsReached = render_set_position(spA0, 3) == 0; + maxObjectsReached = render_set_position(resultMtx, 3) == 0; if (maxObjectsReached) { return; } @@ -114,12 +114,12 @@ void render_actor_train_engine(Camera* camera, struct TrainCar* actor) { gSPDisplayList(gDisplayListHead++, d_course_kalimari_desert_dl_22DB8); gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); - mtxf_rotate_x(sp120, (s16) (actor->wheelRot + 0x444)); + mtxf_rotate_x(mainMtx, (s16) (actor->wheelRot + 0x444)); vec3f_set(sp160, 17.0f, 12.0f, -12.0f); - mtxf_translate(spE0, sp160); - mtxf_multiplication(spA0, sp120, spE0); + mtxf_translate(objectMtx, sp160); + mtxf_multiplication(resultMtx, mainMtx, objectMtx); - maxObjectsReached = render_set_position(spA0, 3) == 0; + maxObjectsReached = render_set_position(resultMtx, 3) == 0; if (maxObjectsReached) { return; } @@ -127,12 +127,12 @@ void render_actor_train_engine(Camera* camera, struct TrainCar* actor) { gSPDisplayList(gDisplayListHead++, d_course_kalimari_desert_dl_22D70); gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); - mtxf_rotate_x(sp120, (s16) (actor->wheelRot + 0x444)); + mtxf_rotate_x(mainMtx, (s16) (actor->wheelRot + 0x444)); vec3f_set(sp160, -17.0f, 12.0f, -12.0f); - mtxf_translate(spE0, sp160); - mtxf_multiplication(spA0, sp120, spE0); + mtxf_translate(objectMtx, sp160); + mtxf_multiplication(resultMtx, mainMtx, objectMtx); - maxObjectsReached = render_set_position(spA0, 3) == 0; + maxObjectsReached = render_set_position(resultMtx, 3) == 0; if (maxObjectsReached) { return; } @@ -140,12 +140,12 @@ void render_actor_train_engine(Camera* camera, struct TrainCar* actor) { gSPDisplayList(gDisplayListHead++, d_course_kalimari_desert_dl_22D70); gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); - mtxf_rotate_x(sp120, (s16) (actor->wheelRot + 0x2D8)); + mtxf_rotate_x(mainMtx, (s16) (actor->wheelRot + 0x2D8)); vec3f_set(sp160, 17.0f, 12.0f, -34.0f); - mtxf_translate(spE0, sp160); - mtxf_multiplication(spA0, sp120, spE0); + mtxf_translate(objectMtx, sp160); + mtxf_multiplication(resultMtx, mainMtx, objectMtx); - maxObjectsReached = render_set_position(spA0, 3) == 0; + maxObjectsReached = render_set_position(resultMtx, 3) == 0; if (maxObjectsReached) { return; } @@ -153,12 +153,12 @@ void render_actor_train_engine(Camera* camera, struct TrainCar* actor) { gSPDisplayList(gDisplayListHead++, d_course_kalimari_desert_dl_22D70); gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); - mtxf_rotate_x(sp120, (s16) (actor->wheelRot + 0x2D8)); + mtxf_rotate_x(mainMtx, (s16) (actor->wheelRot + 0x2D8)); vec3f_set(sp160, -17.0f, 12.0f, -34.0f); - mtxf_translate(spE0, sp160); - mtxf_multiplication(spA0, sp120, spE0); + mtxf_translate(objectMtx, sp160); + mtxf_multiplication(resultMtx, mainMtx, objectMtx); - maxObjectsReached = render_set_position(spA0, 3) == 0; + maxObjectsReached = render_set_position(resultMtx, 3) == 0; if (maxObjectsReached) { return; } diff --git a/src/engine/CoreMath.h b/src/engine/CoreMath.h index 1e7638a70..81bb9e2ea 100644 --- a/src/engine/CoreMath.h +++ b/src/engine/CoreMath.h @@ -22,6 +22,16 @@ struct FVector { return *this; } + // Operator to add two FVector objects + FVector operator+(const FVector& other) const { + return FVector(x + other.x, y + other.y, z + other.z); + } + + // Operator to subtract two FVector objects + FVector operator-(const FVector& other) const { + return FVector(x - other.x, y - other.y, z - other.z); + } + FVector() : x(0), y(0), z(0) {} FVector(float x, float y, float z) : x(x), y(y), z(z) {} #endif // __cplusplus diff --git a/src/engine/actors/Ship.cpp b/src/engine/actors/Ship.cpp index 148b883eb..0f3ccac9d 100644 --- a/src/engine/actors/Ship.cpp +++ b/src/engine/actors/Ship.cpp @@ -29,18 +29,18 @@ AShip::AShip(FVector pos, AShip::Skin skin) { } void AShip::Tick() { - static float angle = 0.0f; // Keeps track of the ship's rotation around the circle - float radius = 150.0f; // The radius of the circular path - float speed = 0.01f; // Speed of rotation + // static float angle = 0.0f; // Keeps track of the ship's rotation around the circle + // float radius = 150.0f; // The radius of the circular path + // float speed = 0.01f; // Speed of rotation - angle += speed; // Increment the angle to move in a circle + // angle += speed; // Increment the angle to move in a circle - // Update the position based on a circular path - Pos.x = Spawn.x + radius * cosf(angle); - Pos.z = Spawn.z + radius * sinf(angle); + // // Update the position based on a circular path + // Pos.x = Spawn.x + radius * cosf(angle); + // Pos.z = Spawn.z + radius * sinf(angle); - // Rotate to face forward along the circle - Rot.yaw = -static_cast(angle * (32768.0f / M_PI / 2.0f)); + // // Rotate to face forward along the circle + // Rot.yaw = -static_cast(angle * (32768.0f / M_PI / 2.0f)); } void AShip::Draw(Camera *camera) { diff --git a/src/engine/editor/ColourIdFramebuffer.cpp b/src/engine/editor/ColourIdFramebuffer.cpp new file mode 100644 index 000000000..12b96e318 --- /dev/null +++ b/src/engine/editor/ColourIdFramebuffer.cpp @@ -0,0 +1,25 @@ + +#include +#include "framebuffer_effects.h" +#include "mk64.h" +#include +#include "port/Engine.h" +#include "math_util.h" +#include + +int gfx_create_framebuffer(uint32_t width, uint32_t height, uint32_t native_width, uint32_t native_height, + uint8_t resize); + + +s32 gColourIdFramebuffer = -1; + +void CreateColourIdFramebuffer(void) { + if (gColourIdFramebuffer == -1) { + gColourIdFramebuffer = gfx_create_framebuffer(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, true); + } +} + +void DrawAsColour() { + + +} \ No newline at end of file diff --git a/src/engine/editor/ColourIdFramebuffer.h b/src/engine/editor/ColourIdFramebuffer.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/engine/editor/Editor.cpp b/src/engine/editor/Editor.cpp index 457e543f9..9cf08a689 100644 --- a/src/engine/editor/Editor.cpp +++ b/src/engine/editor/Editor.cpp @@ -22,124 +22,26 @@ extern "C" { #include "camera.h" } -Editor::Editor() { +int gfx_create_framebuffer(uint32_t width, uint32_t height, uint32_t native_width, uint32_t native_height, + uint8_t resize); +Editor::Editor() { + s32 test = 1; + // gsSPSetFB(gDisplayListHead++, &test); } void Editor::Tick() { auto wnd = GameEngine::Instance->context->GetWindow(); - if (wnd->GetMouseState(Ship::LUS_MOUSE_BTN_LEFT)) { - MouseClick(); - _draw = true; - } else { - _draw = false; - } - if (_heldActor != nullptr) { - FVector ray = ScreenRayTrace(); - float length = 400.0f; - _heldActor->Pos[0] = cameras[0].pos[0] + ray.x * length; - _heldActor->Pos[1] = cameras[0].pos[1] + ray.y * length; - _heldActor->Pos[2] = cameras[0].pos[2] + ray.z * length; - } -} - -void Editor::MouseClick() { - FVector ray = ScreenRayTrace(); - //Actor* foundActor = nullptr; - s32 type = 0; - bool found = false; - for (auto& actor : gWorldInstance.Actors) { - float boundingBox = actor->BoundingBoxSize; - if (boundingBox == 0.0f) { - boundingBox = 2.0f; - } - float t; - float max = 2.0f; - float min = -2.0f; - Vec3f boxMin = { actor->Pos[0] + boundingBox * min, - actor->Pos[1] + boundingBox * min, - actor->Pos[2] + boundingBox * min }; - - Vec3f boxMax = { actor->Pos[0] + actor->BoundingBoxSize * max, - actor->Pos[1] + actor->BoundingBoxSize * max, - actor->Pos[2] + actor->BoundingBoxSize * max }; - - if (Editor::QueryCollisionRayActor(cameras[0].pos, &ray.x, boxMin, boxMax, &t)) { - if (actor == _heldActor) { - _heldActor = nullptr; - break; - } - found = true; - //foundActor = &actor; - type = actor->Type; - _heldActor = actor; - break; - } - } - if (found) { - printf("FOUND COLLISION %d\n", type); - } else { - printf("NO COLLISION\n"); - _heldActor = nullptr; - } -} - -/** - * Projects 2D cursor into the game world - * - * @return FVector ray direction - * - * ray.x = camera->pos[0] + direction.x * length; - * ray.y = camera->pos[1] + direction.y * length; - * ray.z = camera->pos[2] + direction.z * length; - */ -FVector Editor::ScreenRayTrace() { - auto wnd = GameEngine::Instance->context->GetWindow(); - Camera* camera = &cameras[0]; - - Ship::Coords mouse = wnd->GetMousePos(); - - // Get screen dimensions - uint32_t width = wnd->GetWidth(); - uint32_t height = wnd->GetHeight(); - - // Convert mouse to NDS screen coordinates - float x = (2.0f * mouse.x) / width - 1.0f; // Normalized X: -1 to 1 - float y = 1.0f - (2.0f * mouse.y) / height; // Normalized Y: -1 to 1 - float z = 1.0f; // z is typically 1.0 for the near plane - - FVector4 rayClip = {x, y, z, 1.0f}; - - Mat4 perspMtx; - u16 perspNorm; - guPerspectiveF(perspMtx, &perspNorm, gCameraZoom[0], OTRGetAspectRatio(), CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f); - - Mat4 inversePerspMtx; - if (Editor::Inverse((MtxF*)&perspMtx, (MtxF*)&inversePerspMtx) != 2) { - FVector4 rayEye = MultiplyMatrixVector(inversePerspMtx, (float*)&rayClip.x); - - Mat4 lookAtMtx; - guLookAtF(lookAtMtx, camera->pos[0], camera->pos[1], camera->pos[2], camera->lookAt[0], camera->lookAt[1], camera->lookAt[2], camera->up[0], camera->up[1], camera->up[2]); - Mat4 inverseViewMtx; - if (Editor::Inverse((MtxF*)&lookAtMtx, (MtxF*)&inverseViewMtx[0][0]) != 2) { - rayEye.w = 0; - FVector4 invRayWor = MultiplyMatrixVector(inverseViewMtx, (float*)&rayEye.x); - - FVector direction; - direction = FVector(invRayWor.x, invRayWor.y, invRayWor.z); - - return direction; - } + // GetMouseState + if (wnd->MouseClick(Ship::LUS_MOUSE_BTN_LEFT)) { + eObjectPicker.SelectObject(); } } void Editor::Draw() { - if (_draw) { - DrawObj(20); - DrawObj(100); - } + eObjectPicker.Draw(); } void Editor::DrawObj(float length) { @@ -150,136 +52,3 @@ void Editor::DrawObj(float length) { render_set_position(mtx, 0); gSPDisplayList(gDisplayListHead++, Editor::box_Cube_mesh); } - -FVector4 Editor::MultiplyMatrixVector(float matrix[4][4], float vector[4]) { - FVector4 result; - float* resultPtr = &result.x; - for (int i = 0; i < 4; i++) { - resultPtr[i] = 0; - for (int j = 0; j < 4; j++) { - resultPtr[i] += matrix[j][i] * vector[j]; // Swap [i][j] → [j][i] for column order - } - } - return result; -} - -s32 Editor::Inverse(MtxF* src, MtxF* dest) { - MtxF mfCopy; - s32 i; - s32 pad; - f32 temp2; - f32 temp1; - s32 thisCol; - s32 thisRow; - - Editor::Copy(src, &mfCopy); - Editor::Clear(dest); - for (thisCol = 0; thisCol < 4; thisCol++) { - thisRow = thisCol; - while ((thisRow < 4) && (fabsf(mfCopy.mf[thisCol][thisRow]) < 0.0005f)) { - thisRow++; - } - if (thisRow == 4) { - // 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; - } - - if (thisRow != thisCol) { - // Diagonal element mf[thisCol][thisCol] is zero. - // Swap the rows thisCol and thisRow. - for (i = 0; i < 4; i++) { - temp1 = mfCopy.mf[i][thisRow]; - mfCopy.mf[i][thisRow] = mfCopy.mf[i][thisCol]; - mfCopy.mf[i][thisCol] = temp1; - - temp2 = dest->mf[i][thisRow]; - dest->mf[i][thisRow] = dest->mf[i][thisCol]; - dest->mf[i][thisCol] = temp2; - } - } - - // Scale this whole row such that the diagonal element is 1. - temp1 = mfCopy.mf[thisCol][thisCol]; - for (i = 0; i < 4; i++) { - mfCopy.mf[i][thisCol] /= temp1; - dest->mf[i][thisCol] /= temp1; - } - - for (thisRow = 0; thisRow < 4; thisRow++) { - if (thisRow != thisCol) { - temp1 = mfCopy.mf[thisCol][thisRow]; - for (i = 0; i < 4; i++) { - mfCopy.mf[i][thisRow] -= mfCopy.mf[i][thisCol] * temp1; - dest->mf[i][thisRow] -= dest->mf[i][thisCol] * temp1; - } - } - } - } - return 0; -} - -void Editor::Copy(MtxF* src, MtxF* dest) { - dest->xx = src->xx; - dest->yx = src->yx; - dest->zx = src->zx; - dest->wx = src->wx; - dest->xy = src->xy; - dest->yy = src->yy; - dest->zy = src->zy; - dest->wy = src->wy; - dest->xz = src->xz; - dest->yz = src->yz; - dest->zz = src->zz; - dest->wz = src->wz; - dest->xw = src->xw; - dest->yw = src->yw; - dest->zw = src->zw; - dest->ww = src->ww; -} - -void Editor::Clear(MtxF* mf) { - mf->xx = 1.0f; - mf->yy = 1.0f; - mf->zz = 1.0f; - mf->ww = 1.0f; - mf->yx = 0.0f; - mf->zx = 0.0f; - mf->wx = 0.0f; - mf->xy = 0.0f; - mf->zy = 0.0f; - mf->wy = 0.0f; - mf->xz = 0.0f; - mf->yz = 0.0f; - mf->wz = 0.0f; - mf->xw = 0.0f; - mf->yw = 0.0f; - mf->zw = 0.0f; -} - -bool Editor::QueryCollisionRayActor(Vec3f rayOrigin, Vec3f rayDir, Vec3f actorMin, Vec3f actorMax, float* t) { - float tmin = -FLT_MAX, tmax = FLT_MAX; - - for (int i = 0; i < 3; i++) { - if (fabs(rayDir[i]) > 1e-6f) { // Avoid division by zero - float t1 = (actorMin[i] - rayOrigin[i]) / rayDir[i]; - float t2 = (actorMax[i] - rayOrigin[i]) / rayDir[i]; - - if (t1 > t2) { float temp = t1; t1 = t2; t2 = temp; } - - tmin = fmax(tmin, t1); - tmax = fmin(tmax, t2); - - if (tmax < tmin) return false; // No intersection - } else if (rayOrigin[i] < actorMin[i] || rayOrigin[i] > actorMax[i]) { - return false; // Ray is outside the slab - } - } - - *t = tmin; // Distance to first intersection - return true; -} diff --git a/src/engine/editor/Editor.h b/src/engine/editor/Editor.h index c8aabf97b..3126bf7bd 100644 --- a/src/engine/editor/Editor.h +++ b/src/engine/editor/Editor.h @@ -3,6 +3,7 @@ #include #include #include "engine/objects/Flagpole.h" +#include "ObjectPicker.h" class AShip; @@ -13,21 +14,22 @@ public: void Tick(); void Draw(); void MouseClick(); - FVector ScreenRayTrace(); - bool QueryCollisionRayActor(Vec3f rayOrigin, Vec3f rayDir, Vec3f actorMin, Vec3f actorMax, float* t); - FVector4 MultiplyMatrixVector(float matrix[4][4], float vector[4]); private: bool _draw = false; AShip* object; Vec3f _ray; - AActor* _heldActor; + AActor* _selected; + AActor* _lastSelected; + + s32 _colourIdFramebuffer = -1; + s32 Inverse(MtxF* src, MtxF* dest); void Copy(MtxF* src, MtxF* dest); void Clear(MtxF* mf); void DrawObj(float length); - + ObjectPicker eObjectPicker; Vtx box_Cube_mesh_vtx_cull[8] = { diff --git a/src/engine/editor/EditorMath.cpp b/src/engine/editor/EditorMath.cpp new file mode 100644 index 000000000..64d39c938 --- /dev/null +++ b/src/engine/editor/EditorMath.cpp @@ -0,0 +1,188 @@ +#include "EditorMath.h" + +#include +#include "port/Game.h" +#include "port/Engine.h" + +extern "C" { + #include "common_structs.h" + #include "main.h" + #include "defines.h" + #include "actors.h" + #include "math_util.h" + #include "math_util_2.h" + #include "camera.h" +} + +FVector ScreenRayTrace() { + auto wnd = GameEngine::Instance->context->GetWindow(); + Camera* camera = &cameras[0]; + + Ship::Coords mouse = wnd->GetMousePos(); + + // Get screen dimensions + uint32_t width = wnd->GetWidth(); + uint32_t height = wnd->GetHeight(); + + // Convert mouse to NDS screen coordinates + float x = (2.0f * mouse.x) / width - 1.0f; // Normalized X: -1 to 1 + float y = 1.0f - (2.0f * mouse.y) / height; // Normalized Y: -1 to 1 + float z = 1.0f; // z is typically 1.0 for the near plane + + FVector4 rayClip = {x, y, z, 1.0f}; + + Mat4 perspMtx; + u16 perspNorm; + guPerspectiveF(perspMtx, &perspNorm, gCameraZoom[0], OTRGetAspectRatio(), CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f); + + Mat4 inversePerspMtx; + if (Inverse((MtxF*)&perspMtx, (MtxF*)&inversePerspMtx) != 2) { + FVector4 rayEye = MultiplyMatrixVector(inversePerspMtx, (float*)&rayClip.x); + + Mat4 lookAtMtx; + guLookAtF(lookAtMtx, camera->pos[0], camera->pos[1], camera->pos[2], camera->lookAt[0], camera->lookAt[1], camera->lookAt[2], camera->up[0], camera->up[1], camera->up[2]); + Mat4 inverseViewMtx; + if (Inverse((MtxF*)&lookAtMtx, (MtxF*)&inverseViewMtx[0][0]) != 2) { + rayEye.w = 0; + FVector4 invRayWor = MultiplyMatrixVector(inverseViewMtx, (float*)&rayEye.x); + + FVector direction; + direction = FVector(invRayWor.x, invRayWor.y, invRayWor.z); + + return direction; + } + } +} + +bool QueryCollisionRayActor(Vec3f rayOrigin, Vec3f rayDir, Vec3f actorMin, Vec3f actorMax, float* t) { + float tmin = -FLT_MAX, tmax = FLT_MAX; + + for (int i = 0; i < 3; i++) { + if (fabs(rayDir[i]) > 1e-6f) { // Avoid division by zero + float t1 = (actorMin[i] - rayOrigin[i]) / rayDir[i]; + float t2 = (actorMax[i] - rayOrigin[i]) / rayDir[i]; + + if (t1 > t2) { float temp = t1; t1 = t2; t2 = temp; } + + tmin = fmax(tmin, t1); + tmax = fmin(tmax, t2); + + if (tmax < tmin) return false; // No intersection + } else if (rayOrigin[i] < actorMin[i] || rayOrigin[i] > actorMax[i]) { + return false; // Ray is outside the slab + } + } + + *t = tmin; // Distance to first intersection + return true; +} + +FVector4 MultiplyMatrixVector(float matrix[4][4], float vector[4]) { + FVector4 result; + float* resultPtr = &result.x; + for (int i = 0; i < 4; i++) { + resultPtr[i] = 0; + for (int j = 0; j < 4; j++) { + resultPtr[i] += matrix[j][i] * vector[j]; // Swap [i][j] → [j][i] for column order + } + } + return result; +} + +s32 Inverse(MtxF* src, MtxF* dest) { + MtxF mfCopy; + s32 i; + s32 pad; + f32 temp2; + f32 temp1; + s32 thisCol; + s32 thisRow; + + Copy(src, &mfCopy); + Clear(dest); + for (thisCol = 0; thisCol < 4; thisCol++) { + thisRow = thisCol; + while ((thisRow < 4) && (fabsf(mfCopy.mf[thisCol][thisRow]) < 0.0005f)) { + thisRow++; + } + if (thisRow == 4) { + // 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; + } + + if (thisRow != thisCol) { + // Diagonal element mf[thisCol][thisCol] is zero. + // Swap the rows thisCol and thisRow. + for (i = 0; i < 4; i++) { + temp1 = mfCopy.mf[i][thisRow]; + mfCopy.mf[i][thisRow] = mfCopy.mf[i][thisCol]; + mfCopy.mf[i][thisCol] = temp1; + + temp2 = dest->mf[i][thisRow]; + dest->mf[i][thisRow] = dest->mf[i][thisCol]; + dest->mf[i][thisCol] = temp2; + } + } + + // Scale this whole row such that the diagonal element is 1. + temp1 = mfCopy.mf[thisCol][thisCol]; + for (i = 0; i < 4; i++) { + mfCopy.mf[i][thisCol] /= temp1; + dest->mf[i][thisCol] /= temp1; + } + + for (thisRow = 0; thisRow < 4; thisRow++) { + if (thisRow != thisCol) { + temp1 = mfCopy.mf[thisCol][thisRow]; + for (i = 0; i < 4; i++) { + mfCopy.mf[i][thisRow] -= mfCopy.mf[i][thisCol] * temp1; + dest->mf[i][thisRow] -= dest->mf[i][thisCol] * temp1; + } + } + } + } + return 0; +} + +void Copy(MtxF* src, MtxF* dest) { + dest->xx = src->xx; + dest->yx = src->yx; + dest->zx = src->zx; + dest->wx = src->wx; + dest->xy = src->xy; + dest->yy = src->yy; + dest->zy = src->zy; + dest->wy = src->wy; + dest->xz = src->xz; + dest->yz = src->yz; + dest->zz = src->zz; + dest->wz = src->wz; + dest->xw = src->xw; + dest->yw = src->yw; + dest->zw = src->zw; + dest->ww = src->ww; +} + +void Clear(MtxF* mf) { + mf->xx = 1.0f; + mf->yy = 1.0f; + mf->zz = 1.0f; + mf->ww = 1.0f; + mf->yx = 0.0f; + mf->zx = 0.0f; + mf->wx = 0.0f; + mf->xy = 0.0f; + mf->zy = 0.0f; + mf->wy = 0.0f; + mf->xz = 0.0f; + mf->yz = 0.0f; + mf->wz = 0.0f; + mf->xw = 0.0f; + mf->yw = 0.0f; + mf->zw = 0.0f; +} diff --git a/src/engine/editor/EditorMath.h b/src/engine/editor/EditorMath.h new file mode 100644 index 000000000..165b28ec5 --- /dev/null +++ b/src/engine/editor/EditorMath.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include "../CoreMath.h" + +extern "C" { +#include "common_structs.h" +} + +/** + * Projects 2D cursor into the game world + * + * @return FVector ray direction + * + * ray.x = camera->pos[0] + direction.x * length; + * ray.y = camera->pos[1] + direction.y * length; + * ray.z = camera->pos[2] + direction.z * length; + */ +FVector ScreenRayTrace(); +bool QueryCollisionRayActor(Vec3f rayOrigin, Vec3f rayDir, Vec3f actorMin, Vec3f actorMax, float* t); +FVector4 MultiplyMatrixVector(float matrix[4][4], float vector[4]); +s32 Inverse(MtxF* src, MtxF* dest); +void Copy(MtxF* src, MtxF* dest); +void Clear(MtxF* mf); + + diff --git a/src/engine/editor/Gizmo.cpp b/src/engine/editor/Gizmo.cpp new file mode 100644 index 000000000..97445464b --- /dev/null +++ b/src/engine/editor/Gizmo.cpp @@ -0,0 +1,173 @@ +#include +#include +#include "../CoreMath.h" +#include +#include "../World.h" + +#include "Gizmo.h" +#include "port/Engine.h" +#include +#include + +#include "engine/actors/Ship.h" +#include "port/Game.h" + +extern "C" { +#include "common_structs.h" +#include "main.h" +#include "defines.h" +#include "actors.h" +#include "math_util.h" +#include "math_util_2.h" +#include "camera.h" +#include "courses/harbour/ship_model.h" +} + +Gizmo::Gizmo() { +} + +void Gizmo::Tick() { + +} + +std::pair Gizmo::GetBoundingBox(GizmoHandle handle) { + FVector min = Pos + HandleOffsets[(int)handle] - FVector(HandleSize, HandleSize, HandleSize); + FVector max = Pos + HandleOffsets[(int)handle] + FVector(HandleSize, HandleSize, HandleSize); + return {min, max}; +} + +void Gizmo::StartManipulation(GizmoHandle handle) { + printf("HANDLE SELECTED %d\n", (s32)handle); + auto wnd = GameEngine::Instance->context->GetWindow(); + + if (wnd->GetMouseState(Ship::LUS_MOUSE_BTN_LEFT)) { + switch(handle) { + case GizmoHandle::None: + break; + case GizmoHandle::Center: + break; + case GizmoHandle::X_Axis: + break; + case GizmoHandle::Y_Axis: + Gizmo::Translate(); + break; + case GizmoHandle::Z_Axis: + break; + } + } +} + +void Gizmo::Enable(Vec3f* object, FVector ray) { + static float length = 180.0f; // Default value + + // static AActor* lastSelected = nullptr; + // if (object != lastSelected) { + // length = sqrt( + // pow(object->Pos[0] - cameras[0].pos[0], 2) + + // pow(object->Pos[1] - cameras[0].pos[1], 2) + + // pow(object->Pos[2] - cameras[0].pos[2], 2) + // ); + // lastSelected = object; + // } + + //_selected->Pos[0] = cameras[0].pos[0] + ray.x * length; + //object->Pos[1] = cameras[0].pos[1] + ray.y * length; + //_selected->Pos[2] = cameras[0].pos[2] + ray.z * length; + _selected = &object[0]; + _ray = ray; + Pos = FVector( + object[0][0], + object[0][1], + object[0][2] + ); +} + +void Gizmo::Translate() { + static float length = 180.0f; // Default value + + if (Enabled) { + //FVector ray = ScreenRayTrace(); + + length = sqrt( + pow(_selected[0][0] - cameras[0].pos[0], 2) + + pow(_selected[0][1] - cameras[0].pos[1], 2) + + pow(_selected[0][2] - cameras[0].pos[2], 2) + ); + + //_selected->Pos[0] = cameras[0].pos[0] + ray.x * length; + _selected[0][0] = cameras[0].pos[1] + _ray.y * length; + //_selected->Pos[2] = cameras[0].pos[2] + ray.z * length; + Pos = FVector( + _selected[0][0], + _selected[0][1], + _selected[0][2] + ); + } +} + +// void Gizmo::Rotate() { + +// } + +// void Gizmo::Scale() { + +// } + +void Gizmo::Draw() { + if (Enabled) { + DrawHandles(); + } +} + +void Gizmo::DrawHandles() { + Mat4 mainMtx; + + Vec3s rot = {0, 0, 0}; + mtxf_pos_rotation_xyz(mainMtx, &Pos.x, rot); + //mtxf_scale(mainMtx, 0.05f); + if (render_set_position(mainMtx, 0) != 0) { + //gSPDisplayList(gDisplayListHead++, wheels_Spaghetti_002_mesh); + //gSPDisplayList(gDisplayListHead++, handle_Cylinder_mesh); + } + + handle_f3dlite_material_lights = gdSPDefLights1( + 0x7F, 0x7F, 0x7F, + 0xFF, 0, 0, 0x49, 0x49, 0x49); + + Mat4 RedXMtx; + Vec3s rot1 = {0, 0, 0}; + Vec3f pos1 = {Pos.x, Pos.y, Pos.z - _gizmoOffset}; + mtxf_pos_rotation_xyz(RedXMtx, pos1, rot1); + mtxf_scale(RedXMtx, 0.05); + if (render_set_position(RedXMtx, 0) != 0) { + gSPDisplayList(gDisplayListHead++, handle_Cylinder_mesh); + } + + Vec3s rot2 = {0, 0x4000, 0}; + + handle_f3dlite_material_lights = gdSPDefLights1( + 0x7F, 0x7F, 0x7F, + 0, 0xFF, 0, 0x49, 0x49, 0x49); + + Mat4 GreenYMtx; + Vec3f pos2 = {Pos.x - _gizmoOffset, Pos.y, Pos.z}; + mtxf_pos_rotation_xyz(GreenYMtx, pos2, rot2); + mtxf_scale(GreenYMtx, 0.05); + if (render_set_position(GreenYMtx, 0) != 0) { + gSPDisplayList(gDisplayListHead++, handle_Cylinder_mesh); + } + + Vec3s rot3 = {0x4000, 0, 0}; + + handle_f3dlite_material_lights = gdSPDefLights1( + 0x7F, 0x7F, 0x7F, + 0, 0, 0xFF, 0x49, 0x49, 0x49); + + Mat4 BlueZMtx; + Vec3f pos3 = {Pos.x, Pos.y + _gizmoOffset, Pos.z}; + mtxf_pos_rotation_xyz(BlueZMtx, pos3, rot3); + mtxf_scale(BlueZMtx, 0.05); + if (render_set_position(BlueZMtx, 0) != 0) { + gSPDisplayList(gDisplayListHead++, handle_Cylinder_mesh); + } +} diff --git a/src/engine/editor/Gizmo.h b/src/engine/editor/Gizmo.h new file mode 100644 index 000000000..a8cc60a9a --- /dev/null +++ b/src/engine/editor/Gizmo.h @@ -0,0 +1,543 @@ +#pragma once + +#include +#include +#include "engine/objects/Flagpole.h" + +class Gizmo { +public: + + enum class GizmoHandle { + None, + Center, + X_Axis, + Y_Axis, + Z_Axis + }; + + Gizmo(); + + void Tick(); + void Draw(); + + void StartManipulation(GizmoHandle handle); + void Enable(Vec3f* object, FVector ray); + void Translate(); + void DrawHandles(); + + + std::pair GetBoundingBox(GizmoHandle handle); + + bool Enabled; + GizmoHandle SelectedHandle; + + FVector Pos; // Global scene view + float _gizmoOffset = 5.0f; + FVector RedPos = {0, 0, -_gizmoOffset}; // Local model view + FVector GreenPos = {-_gizmoOffset, 0, 0}; // Local model view + FVector BluePos = {0, _gizmoOffset, 0}; // Local model view + + float HandleSize = 2.0f; + + FVector HandleOffsets[4] = { + {0, 0, 0}, // Center Button + {0, 0, -5}, // X-Axis (Red) + {0, 5, 0}, // Y-Axis (Green) + {-5, 0, 0} // Z-Axis (Blue) + }; + private: + bool _draw = false; + FVector _ray; + Vec3f* _selected; + + +Lights1 handle_f3dlite_material_lights = gdSPDefLights1( + 0x7F, 0x7F, 0x7F, + 0xFF, 0xFF, 0xFF, 0x49, 0x49, 0x49); + + + Vtx handle_Cylinder_mesh_vtx_cull[8] = { + {{ {-22, -22, -271}, 0, {0, 0}, {0, 0, 0, 0} }}, + {{ {-22, -22, 0}, 0, {0, 0}, {0, 0, 0, 0} }}, + {{ {-22, 22, 0}, 0, {0, 0}, {0, 0, 0, 0} }}, + {{ {-22, 22, -271}, 0, {0, 0}, {0, 0, 0, 0} }}, + {{ {22, -22, -271}, 0, {0, 0}, {0, 0, 0, 0} }}, + {{ {22, -22, 0}, 0, {0, 0}, {0, 0, 0, 0} }}, + {{ {22, 22, 0}, 0, {0, 0}, {0, 0, 0, 0} }}, + {{ {22, 22, -271}, 0, {0, 0}, {0, 0, 0, 0} }}, + }; + + Vtx handle_Cylinder_mesh_vtx_0[329] = { + {{ {0, -22, -194}, 0, {240, 506}, {12, 134, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {12, 134, 222, 255} }}, + {{ {4, -21, -194}, 0, {288, 511}, {12, 134, 222, 255} }}, + {{ {4, -21, -194}, 0, {288, 511}, {35, 139, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {35, 139, 222, 255} }}, + {{ {8, -20, -194}, 0, {334, 525}, {35, 139, 222, 255} }}, + {{ {8, -20, -194}, 0, {334, 525}, {58, 148, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {58, 148, 222, 255} }}, + {{ {12, -18, -194}, 0, {377, 548}, {58, 148, 222, 255} }}, + {{ {12, -18, -194}, 0, {377, 548}, {78, 162, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {78, 162, 222, 255} }}, + {{ {15, -15, -194}, 0, {414, 578}, {78, 162, 222, 255} }}, + {{ {15, -15, -194}, 0, {414, 578}, {94, 178, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {94, 178, 222, 255} }}, + {{ {18, -12, -194}, 0, {444, 615}, {94, 178, 222, 255} }}, + {{ {18, -12, -194}, 0, {444, 615}, {108, 198, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {108, 198, 222, 255} }}, + {{ {20, -8, -194}, 0, {467, 658}, {108, 198, 222, 255} }}, + {{ {20, -8, -194}, 0, {467, 658}, {117, 221, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {117, 221, 222, 255} }}, + {{ {21, -4, -194}, 0, {481, 704}, {117, 221, 222, 255} }}, + {{ {21, -4, -194}, 0, {481, 704}, {122, 244, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {122, 244, 222, 255} }}, + {{ {22, 0, -194}, 0, {486, 752}, {122, 244, 222, 255} }}, + {{ {22, 0, -194}, 0, {486, 752}, {122, 12, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {122, 12, 222, 255} }}, + {{ {21, 4, -194}, 0, {481, 800}, {122, 12, 222, 255} }}, + {{ {21, 4, -194}, 0, {481, 800}, {117, 35, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {117, 35, 222, 255} }}, + {{ {20, 8, -194}, 0, {467, 846}, {117, 35, 222, 255} }}, + {{ {20, 8, -194}, 0, {467, 846}, {108, 58, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {108, 58, 222, 255} }}, + {{ {18, 12, -194}, 0, {444, 889}, {108, 58, 222, 255} }}, + {{ {18, 12, -194}, 0, {444, 889}, {94, 78, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {94, 78, 222, 255} }}, + {{ {15, 15, -194}, 0, {414, 926}, {94, 78, 222, 255} }}, + {{ {15, 15, -194}, 0, {414, 926}, {78, 94, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {78, 94, 222, 255} }}, + {{ {12, 18, -194}, 0, {377, 956}, {78, 94, 222, 255} }}, + {{ {12, 18, -194}, 0, {377, 956}, {58, 108, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {58, 108, 222, 255} }}, + {{ {8, 20, -194}, 0, {334, 979}, {58, 108, 222, 255} }}, + {{ {8, 20, -194}, 0, {334, 979}, {35, 117, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {35, 117, 222, 255} }}, + {{ {4, 21, -194}, 0, {288, 993}, {35, 117, 222, 255} }}, + {{ {4, 21, -194}, 0, {288, 993}, {12, 122, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {12, 122, 222, 255} }}, + {{ {0, 22, -194}, 0, {240, 998}, {12, 122, 222, 255} }}, + {{ {0, 22, -194}, 0, {240, 998}, {244, 122, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {244, 122, 222, 255} }}, + {{ {-4, 21, -194}, 0, {192, 993}, {244, 122, 222, 255} }}, + {{ {-4, 21, -194}, 0, {192, 993}, {221, 117, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {221, 117, 222, 255} }}, + {{ {-8, 20, -194}, 0, {146, 979}, {221, 117, 222, 255} }}, + {{ {-8, 20, -194}, 0, {146, 979}, {198, 108, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {198, 108, 222, 255} }}, + {{ {-12, 18, -194}, 0, {103, 956}, {198, 108, 222, 255} }}, + {{ {-12, 18, -194}, 0, {103, 956}, {178, 94, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {178, 94, 222, 255} }}, + {{ {-15, 15, -194}, 0, {66, 926}, {178, 94, 222, 255} }}, + {{ {-15, 15, -194}, 0, {66, 926}, {162, 78, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {162, 78, 222, 255} }}, + {{ {-18, 12, -194}, 0, {36, 889}, {162, 78, 222, 255} }}, + {{ {-18, 12, -194}, 0, {36, 889}, {148, 58, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {148, 58, 222, 255} }}, + {{ {-20, 8, -194}, 0, {13, 846}, {148, 58, 222, 255} }}, + {{ {-20, 8, -194}, 0, {13, 846}, {139, 35, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {139, 35, 222, 255} }}, + {{ {-21, 4, -194}, 0, {-1, 800}, {139, 35, 222, 255} }}, + {{ {-21, 4, -194}, 0, {-1, 800}, {134, 12, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {134, 12, 222, 255} }}, + {{ {-22, 0, -194}, 0, {-6, 752}, {134, 12, 222, 255} }}, + {{ {-22, 0, -194}, 0, {-6, 752}, {134, 244, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {134, 244, 222, 255} }}, + {{ {-21, -4, -194}, 0, {-1, 704}, {134, 244, 222, 255} }}, + {{ {-21, -4, -194}, 0, {-1, 704}, {139, 221, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {139, 221, 222, 255} }}, + {{ {-20, -8, -194}, 0, {13, 658}, {139, 221, 222, 255} }}, + {{ {-20, -8, -194}, 0, {13, 658}, {148, 198, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {148, 198, 222, 255} }}, + {{ {-18, -12, -194}, 0, {36, 615}, {148, 198, 222, 255} }}, + {{ {-18, -12, -194}, 0, {36, 615}, {162, 178, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {162, 178, 222, 255} }}, + {{ {-15, -15, -194}, 0, {66, 578}, {162, 178, 222, 255} }}, + {{ {-15, -15, -194}, 0, {66, 578}, {178, 162, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {178, 162, 222, 255} }}, + {{ {-12, -18, -194}, 0, {103, 548}, {178, 162, 222, 255} }}, + {{ {-12, -18, -194}, 0, {103, 548}, {198, 148, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {198, 148, 222, 255} }}, + {{ {-8, -20, -194}, 0, {146, 525}, {198, 148, 222, 255} }}, + {{ {-8, -20, -194}, 0, {146, 525}, {221, 139, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {221, 139, 222, 255} }}, + {{ {-4, -21, -194}, 0, {192, 511}, {221, 139, 222, 255} }}, + {{ {-4, -21, -194}, 0, {192, 511}, {244, 134, 222, 255} }}, + {{ {0, 0, -271}, 0, {240, 752}, {244, 134, 222, 255} }}, + {{ {0, -22, -194}, 0, {240, 506}, {244, 134, 222, 255} }}, + {{ {0, 9, -194}, 0, {1008, 496}, {12, 126, 0, 255} }}, + {{ {0, 9, 0}, 0, {1008, -16}, {12, 126, 0, 255} }}, + {{ {2, 9, 0}, 0, {976, -16}, {12, 126, 0, 255} }}, + {{ {2, 9, -194}, 0, {976, 496}, {12, 126, 0, 255} }}, + {{ {2, 9, -194}, 0, {976, 496}, {37, 122, 0, 255} }}, + {{ {2, 9, 0}, 0, {976, -16}, {37, 122, 0, 255} }}, + {{ {3, 8, 0}, 0, {944, -16}, {37, 122, 0, 255} }}, + {{ {3, 8, -194}, 0, {944, 496}, {37, 122, 0, 255} }}, + {{ {3, 8, -194}, 0, {944, 496}, {60, 112, 0, 255} }}, + {{ {3, 8, 0}, 0, {944, -16}, {60, 112, 0, 255} }}, + {{ {5, 7, 0}, 0, {912, -16}, {60, 112, 0, 255} }}, + {{ {5, 7, -194}, 0, {912, 496}, {60, 112, 0, 255} }}, + {{ {5, 7, -194}, 0, {912, 496}, {81, 98, 0, 255} }}, + {{ {5, 7, 0}, 0, {912, -16}, {81, 98, 0, 255} }}, + {{ {6, 6, 0}, 0, {880, -16}, {81, 98, 0, 255} }}, + {{ {6, 6, -194}, 0, {880, 496}, {81, 98, 0, 255} }}, + {{ {6, 6, -194}, 0, {880, 496}, {98, 81, 0, 255} }}, + {{ {6, 6, 0}, 0, {880, -16}, {98, 81, 0, 255} }}, + {{ {7, 5, 0}, 0, {848, -16}, {98, 81, 0, 255} }}, + {{ {7, 5, -194}, 0, {848, 496}, {98, 81, 0, 255} }}, + {{ {7, 5, -194}, 0, {848, 496}, {112, 60, 0, 255} }}, + {{ {7, 5, 0}, 0, {848, -16}, {112, 60, 0, 255} }}, + {{ {8, 3, 0}, 0, {816, -16}, {112, 60, 0, 255} }}, + {{ {8, 3, -194}, 0, {816, 496}, {112, 60, 0, 255} }}, + {{ {8, 3, -194}, 0, {816, 496}, {122, 37, 0, 255} }}, + {{ {8, 3, 0}, 0, {816, -16}, {122, 37, 0, 255} }}, + {{ {9, 2, 0}, 0, {784, -16}, {122, 37, 0, 255} }}, + {{ {9, 2, -194}, 0, {784, 496}, {122, 37, 0, 255} }}, + {{ {9, 2, -194}, 0, {784, 496}, {126, 12, 0, 255} }}, + {{ {9, 2, 0}, 0, {784, -16}, {126, 12, 0, 255} }}, + {{ {9, 0, 0}, 0, {752, -16}, {126, 12, 0, 255} }}, + {{ {9, 0, -194}, 0, {752, 496}, {126, 12, 0, 255} }}, + {{ {9, 0, -194}, 0, {752, 496}, {126, 244, 0, 255} }}, + {{ {9, 0, 0}, 0, {752, -16}, {126, 244, 0, 255} }}, + {{ {9, -2, 0}, 0, {720, -16}, {126, 244, 0, 255} }}, + {{ {9, -2, -194}, 0, {720, 496}, {126, 244, 0, 255} }}, + {{ {9, -2, -194}, 0, {720, 496}, {122, 219, 0, 255} }}, + {{ {9, -2, 0}, 0, {720, -16}, {122, 219, 0, 255} }}, + {{ {8, -3, 0}, 0, {688, -16}, {122, 219, 0, 255} }}, + {{ {8, -3, -194}, 0, {688, 496}, {122, 219, 0, 255} }}, + {{ {8, -3, -194}, 0, {688, 496}, {112, 196, 0, 255} }}, + {{ {8, -3, 0}, 0, {688, -16}, {112, 196, 0, 255} }}, + {{ {7, -5, 0}, 0, {656, -16}, {112, 196, 0, 255} }}, + {{ {7, -5, -194}, 0, {656, 496}, {112, 196, 0, 255} }}, + {{ {7, -5, -194}, 0, {656, 496}, {98, 175, 0, 255} }}, + {{ {7, -5, 0}, 0, {656, -16}, {98, 175, 0, 255} }}, + {{ {6, -6, 0}, 0, {624, -16}, {98, 175, 0, 255} }}, + {{ {6, -6, -194}, 0, {624, 496}, {98, 175, 0, 255} }}, + {{ {6, -6, -194}, 0, {624, 496}, {81, 158, 0, 255} }}, + {{ {6, -6, 0}, 0, {624, -16}, {81, 158, 0, 255} }}, + {{ {5, -7, 0}, 0, {592, -16}, {81, 158, 0, 255} }}, + {{ {5, -7, -194}, 0, {592, 496}, {81, 158, 0, 255} }}, + {{ {5, -7, -194}, 0, {592, 496}, {60, 144, 0, 255} }}, + {{ {5, -7, 0}, 0, {592, -16}, {60, 144, 0, 255} }}, + {{ {3, -8, 0}, 0, {560, -16}, {60, 144, 0, 255} }}, + {{ {3, -8, -194}, 0, {560, 496}, {60, 144, 0, 255} }}, + {{ {3, -8, -194}, 0, {560, 496}, {37, 134, 0, 255} }}, + {{ {3, -8, 0}, 0, {560, -16}, {37, 134, 0, 255} }}, + {{ {2, -9, 0}, 0, {528, -16}, {37, 134, 0, 255} }}, + {{ {2, -9, -194}, 0, {528, 496}, {37, 134, 0, 255} }}, + {{ {2, -9, -194}, 0, {528, 496}, {12, 130, 0, 255} }}, + {{ {2, -9, 0}, 0, {528, -16}, {12, 130, 0, 255} }}, + {{ {0, -9, 0}, 0, {496, -16}, {12, 130, 0, 255} }}, + {{ {0, -9, -194}, 0, {496, 496}, {12, 130, 0, 255} }}, + {{ {0, -9, -194}, 0, {496, 496}, {244, 130, 0, 255} }}, + {{ {0, -9, 0}, 0, {496, -16}, {244, 130, 0, 255} }}, + {{ {-2, -9, 0}, 0, {464, -16}, {244, 130, 0, 255} }}, + {{ {-2, -9, -194}, 0, {464, 496}, {244, 130, 0, 255} }}, + {{ {-2, -9, -194}, 0, {464, 496}, {219, 134, 0, 255} }}, + {{ {-2, -9, 0}, 0, {464, -16}, {219, 134, 0, 255} }}, + {{ {-3, -8, 0}, 0, {432, -16}, {219, 134, 0, 255} }}, + {{ {-3, -8, -194}, 0, {432, 496}, {219, 134, 0, 255} }}, + {{ {-3, -8, -194}, 0, {432, 496}, {196, 144, 0, 255} }}, + {{ {-3, -8, 0}, 0, {432, -16}, {196, 144, 0, 255} }}, + {{ {-5, -7, 0}, 0, {400, -16}, {196, 144, 0, 255} }}, + {{ {-5, -7, -194}, 0, {400, 496}, {196, 144, 0, 255} }}, + {{ {-5, -7, -194}, 0, {400, 496}, {175, 158, 0, 255} }}, + {{ {-5, -7, 0}, 0, {400, -16}, {175, 158, 0, 255} }}, + {{ {-6, -6, 0}, 0, {368, -16}, {175, 158, 0, 255} }}, + {{ {-6, -6, -194}, 0, {368, 496}, {175, 158, 0, 255} }}, + {{ {-6, -6, -194}, 0, {368, 496}, {158, 175, 0, 255} }}, + {{ {-6, -6, 0}, 0, {368, -16}, {158, 175, 0, 255} }}, + {{ {-7, -5, 0}, 0, {336, -16}, {158, 175, 0, 255} }}, + {{ {-7, -5, -194}, 0, {336, 496}, {158, 175, 0, 255} }}, + {{ {-7, -5, -194}, 0, {336, 496}, {144, 196, 0, 255} }}, + {{ {-7, -5, 0}, 0, {336, -16}, {144, 196, 0, 255} }}, + {{ {-8, -3, 0}, 0, {304, -16}, {144, 196, 0, 255} }}, + {{ {-8, -3, -194}, 0, {304, 496}, {144, 196, 0, 255} }}, + {{ {-8, -3, -194}, 0, {304, 496}, {134, 219, 0, 255} }}, + {{ {-8, -3, 0}, 0, {304, -16}, {134, 219, 0, 255} }}, + {{ {-9, -2, 0}, 0, {272, -16}, {134, 219, 0, 255} }}, + {{ {-9, -2, -194}, 0, {272, 496}, {134, 219, 0, 255} }}, + {{ {-9, -2, -194}, 0, {272, 496}, {130, 244, 0, 255} }}, + {{ {-9, -2, 0}, 0, {272, -16}, {130, 244, 0, 255} }}, + {{ {-9, 0, 0}, 0, {240, -16}, {130, 244, 0, 255} }}, + {{ {-9, 0, -194}, 0, {240, 496}, {130, 244, 0, 255} }}, + {{ {-9, 0, -194}, 0, {240, 496}, {130, 12, 0, 255} }}, + {{ {-9, 0, 0}, 0, {240, -16}, {130, 12, 0, 255} }}, + {{ {-9, 2, 0}, 0, {208, -16}, {130, 12, 0, 255} }}, + {{ {-9, 2, -194}, 0, {208, 496}, {130, 12, 0, 255} }}, + {{ {-9, 2, -194}, 0, {208, 496}, {134, 37, 0, 255} }}, + {{ {-9, 2, 0}, 0, {208, -16}, {134, 37, 0, 255} }}, + {{ {-8, 3, 0}, 0, {176, -16}, {134, 37, 0, 255} }}, + {{ {-8, 3, -194}, 0, {176, 496}, {134, 37, 0, 255} }}, + {{ {-8, 3, -194}, 0, {176, 496}, {144, 60, 0, 255} }}, + {{ {-8, 3, 0}, 0, {176, -16}, {144, 60, 0, 255} }}, + {{ {-7, 5, 0}, 0, {144, -16}, {144, 60, 0, 255} }}, + {{ {-7, 5, -194}, 0, {144, 496}, {144, 60, 0, 255} }}, + {{ {-7, 5, -194}, 0, {144, 496}, {158, 81, 0, 255} }}, + {{ {-7, 5, 0}, 0, {144, -16}, {158, 81, 0, 255} }}, + {{ {-6, 6, 0}, 0, {112, -16}, {158, 81, 0, 255} }}, + {{ {-6, 6, -194}, 0, {112, 496}, {158, 81, 0, 255} }}, + {{ {-6, 6, -194}, 0, {112, 496}, {175, 98, 0, 255} }}, + {{ {-6, 6, 0}, 0, {112, -16}, {175, 98, 0, 255} }}, + {{ {-5, 7, 0}, 0, {80, -16}, {175, 98, 0, 255} }}, + {{ {-5, 7, -194}, 0, {80, 496}, {175, 98, 0, 255} }}, + {{ {-5, 7, -194}, 0, {80, 496}, {196, 112, 0, 255} }}, + {{ {-5, 7, 0}, 0, {80, -16}, {196, 112, 0, 255} }}, + {{ {-3, 8, 0}, 0, {48, -16}, {196, 112, 0, 255} }}, + {{ {-3, 8, -194}, 0, {48, 496}, {196, 112, 0, 255} }}, + {{ {3, 8, 0}, 0, {334, 525}, {0, 0, 127, 255} }}, + {{ {2, 9, 0}, 0, {288, 511}, {0, 0, 127, 255} }}, + {{ {0, 9, 0}, 0, {240, 506}, {0, 0, 127, 255} }}, + {{ {-3, 8, 0}, 0, {146, 525}, {0, 0, 127, 255} }}, + {{ {-2, 9, 0}, 0, {192, 511}, {0, 0, 127, 255} }}, + {{ {-8, 3, 0}, 0, {13, 658}, {0, 0, 127, 255} }}, + {{ {-6, 6, 0}, 0, {66, 578}, {0, 0, 127, 255} }}, + {{ {-5, 7, 0}, 0, {103, 548}, {0, 0, 127, 255} }}, + {{ {-7, 5, 0}, 0, {36, 615}, {0, 0, 127, 255} }}, + {{ {-9, 2, 0}, 0, {-1, 704}, {0, 0, 127, 255} }}, + {{ {-9, 0, 0}, 0, {-6, 752}, {0, 0, 127, 255} }}, + {{ {-8, -3, 0}, 0, {13, 846}, {0, 0, 127, 255} }}, + {{ {-9, -2, 0}, 0, {-1, 800}, {0, 0, 127, 255} }}, + {{ {-3, -8, 0}, 0, {146, 979}, {0, 0, 127, 255} }}, + {{ {-6, -6, 0}, 0, {66, 926}, {0, 0, 127, 255} }}, + {{ {-7, -5, 0}, 0, {36, 889}, {0, 0, 127, 255} }}, + {{ {-5, -7, 0}, 0, {103, 956}, {0, 0, 127, 255} }}, + {{ {-2, -9, 0}, 0, {192, 993}, {0, 0, 127, 255} }}, + {{ {0, -9, 0}, 0, {240, 998}, {0, 0, 127, 255} }}, + {{ {3, -8, 0}, 0, {334, 979}, {0, 0, 127, 255} }}, + {{ {2, -9, 0}, 0, {288, 993}, {0, 0, 127, 255} }}, + {{ {8, -3, 0}, 0, {467, 846}, {0, 0, 127, 255} }}, + {{ {6, -6, 0}, 0, {414, 926}, {0, 0, 127, 255} }}, + {{ {5, -7, 0}, 0, {377, 956}, {0, 0, 127, 255} }}, + {{ {7, -5, 0}, 0, {444, 889}, {0, 0, 127, 255} }}, + {{ {9, -2, 0}, 0, {481, 800}, {0, 0, 127, 255} }}, + {{ {9, 0, 0}, 0, {486, 752}, {0, 0, 127, 255} }}, + {{ {8, 3, 0}, 0, {467, 658}, {0, 0, 127, 255} }}, + {{ {9, 2, 0}, 0, {481, 704}, {0, 0, 127, 255} }}, + {{ {6, 6, 0}, 0, {414, 578}, {0, 0, 127, 255} }}, + {{ {7, 5, 0}, 0, {444, 615}, {0, 0, 127, 255} }}, + {{ {5, 7, 0}, 0, {377, 548}, {0, 0, 127, 255} }}, + {{ {-3, 8, -194}, 0, {48, 496}, {219, 122, 0, 255} }}, + {{ {-3, 8, 0}, 0, {48, -16}, {219, 122, 0, 255} }}, + {{ {-2, 9, 0}, 0, {16, -16}, {219, 122, 0, 255} }}, + {{ {-2, 9, -194}, 0, {16, 496}, {219, 122, 0, 255} }}, + {{ {-2, 9, -194}, 0, {16, 496}, {244, 126, 0, 255} }}, + {{ {-2, 9, 0}, 0, {16, -16}, {244, 126, 0, 255} }}, + {{ {0, 9, 0}, 0, {-16, -16}, {244, 126, 0, 255} }}, + {{ {0, 9, -194}, 0, {-16, 496}, {244, 126, 0, 255} }}, + {{ {-2, 9, -194}, 0, {704, 511}, {0, 0, 129, 255} }}, + {{ {0, 9, -194}, 0, {752, 506}, {0, 0, 129, 255} }}, + {{ {2, 9, -194}, 0, {800, 511}, {0, 0, 129, 255} }}, + {{ {5, 7, -194}, 0, {889, 548}, {0, 0, 129, 255} }}, + {{ {3, 8, -194}, 0, {846, 525}, {0, 0, 129, 255} }}, + {{ {9, 2, -194}, 0, {993, 704}, {0, 0, 129, 255} }}, + {{ {7, 5, -194}, 0, {956, 615}, {0, 0, 129, 255} }}, + {{ {6, 6, -194}, 0, {926, 578}, {0, 0, 129, 255} }}, + {{ {8, 3, -194}, 0, {979, 658}, {0, 0, 129, 255} }}, + {{ {9, 0, -194}, 0, {998, 752}, {0, 0, 129, 255} }}, + {{ {9, -2, -194}, 0, {993, 800}, {0, 0, 129, 255} }}, + {{ {7, -5, -194}, 0, {956, 889}, {0, 0, 129, 255} }}, + {{ {8, -3, -194}, 0, {979, 846}, {0, 0, 129, 255} }}, + {{ {2, -9, -194}, 0, {800, 993}, {0, 0, 129, 255} }}, + {{ {5, -7, -194}, 0, {889, 956}, {0, 0, 129, 255} }}, + {{ {6, -6, -194}, 0, {926, 926}, {0, 0, 129, 255} }}, + {{ {3, -8, -194}, 0, {846, 979}, {0, 0, 129, 255} }}, + {{ {0, -9, -194}, 0, {752, 998}, {0, 0, 129, 255} }}, + {{ {-2, -9, -194}, 0, {704, 993}, {0, 0, 129, 255} }}, + {{ {-5, -7, -194}, 0, {615, 956}, {0, 0, 129, 255} }}, + {{ {-3, -8, -194}, 0, {658, 979}, {0, 0, 129, 255} }}, + {{ {-9, -2, -194}, 0, {511, 800}, {0, 0, 129, 255} }}, + {{ {-7, -5, -194}, 0, {548, 889}, {0, 0, 129, 255} }}, + {{ {-6, -6, -194}, 0, {578, 926}, {0, 0, 129, 255} }}, + {{ {-7, -5, -194}, 0, {548, 889}, {0, 0, 129, 255} }}, + {{ {-8, -3, -194}, 0, {525, 846}, {0, 0, 129, 255} }}, + {{ {-9, -2, -194}, 0, {511, 800}, {0, 0, 129, 255} }}, + {{ {-9, 0, -194}, 0, {506, 752}, {0, 0, 129, 255} }}, + {{ {-9, 2, -194}, 0, {511, 704}, {0, 0, 129, 255} }}, + {{ {-7, 5, -194}, 0, {548, 615}, {0, 0, 129, 255} }}, + {{ {-8, 3, -194}, 0, {525, 658}, {0, 0, 129, 255} }}, + {{ {-2, 9, -194}, 0, {704, 511}, {0, 0, 129, 255} }}, + {{ {-5, 7, -194}, 0, {615, 548}, {0, 0, 129, 255} }}, + {{ {-6, 6, -194}, 0, {578, 578}, {0, 0, 129, 255} }}, + {{ {-3, 8, -194}, 0, {658, 525}, {0, 0, 129, 255} }}, + {{ {9, 2, -194}, 0, {993, 704}, {0, 0, 129, 255} }}, + {{ {2, -9, -194}, 0, {800, 993}, {0, 0, 129, 255} }}, + {{ {-4, -21, -194}, 0, {704, 511}, {0, 0, 127, 255} }}, + {{ {0, -22, -194}, 0, {752, 506}, {0, 0, 127, 255} }}, + {{ {4, -21, -194}, 0, {800, 511}, {0, 0, 127, 255} }}, + {{ {12, -18, -194}, 0, {889, 548}, {0, 0, 127, 255} }}, + {{ {8, -20, -194}, 0, {846, 525}, {0, 0, 127, 255} }}, + {{ {21, -4, -194}, 0, {993, 704}, {0, 0, 127, 255} }}, + {{ {18, -12, -194}, 0, {956, 615}, {0, 0, 127, 255} }}, + {{ {15, -15, -194}, 0, {926, 578}, {0, 0, 127, 255} }}, + {{ {20, -8, -194}, 0, {979, 658}, {0, 0, 127, 255} }}, + {{ {22, 0, -194}, 0, {998, 752}, {0, 0, 127, 255} }}, + {{ {21, 4, -194}, 0, {993, 800}, {0, 0, 127, 255} }}, + {{ {18, 12, -194}, 0, {956, 889}, {0, 0, 127, 255} }}, + {{ {20, 8, -194}, 0, {979, 846}, {0, 0, 127, 255} }}, + {{ {4, 21, -194}, 0, {800, 993}, {0, 0, 127, 255} }}, + {{ {12, 18, -194}, 0, {889, 956}, {0, 0, 127, 255} }}, + {{ {15, 15, -194}, 0, {926, 926}, {0, 0, 127, 255} }}, + {{ {8, 20, -194}, 0, {846, 979}, {0, 0, 127, 255} }}, + {{ {0, 22, -194}, 0, {752, 998}, {0, 0, 127, 255} }}, + {{ {-4, 21, -194}, 0, {704, 993}, {0, 0, 127, 255} }}, + {{ {4, 21, -194}, 0, {800, 993}, {0, 0, 127, 255} }}, + {{ {-4, 21, -194}, 0, {704, 993}, {0, 0, 127, 255} }}, + {{ {-12, 18, -194}, 0, {615, 956}, {0, 0, 127, 255} }}, + {{ {-8, 20, -194}, 0, {658, 979}, {0, 0, 127, 255} }}, + {{ {-21, 4, -194}, 0, {511, 800}, {0, 0, 127, 255} }}, + {{ {-18, 12, -194}, 0, {548, 889}, {0, 0, 127, 255} }}, + {{ {-15, 15, -194}, 0, {578, 926}, {0, 0, 127, 255} }}, + {{ {-20, 8, -194}, 0, {525, 846}, {0, 0, 127, 255} }}, + {{ {-22, 0, -194}, 0, {506, 752}, {0, 0, 127, 255} }}, + {{ {-21, -4, -194}, 0, {511, 704}, {0, 0, 127, 255} }}, + {{ {-18, -12, -194}, 0, {548, 615}, {0, 0, 127, 255} }}, + {{ {-20, -8, -194}, 0, {525, 658}, {0, 0, 127, 255} }}, + {{ {-4, -21, -194}, 0, {704, 511}, {0, 0, 127, 255} }}, + {{ {-12, -18, -194}, 0, {615, 548}, {0, 0, 127, 255} }}, + {{ {-15, -15, -194}, 0, {578, 578}, {0, 0, 127, 255} }}, + {{ {-8, -20, -194}, 0, {658, 525}, {0, 0, 127, 255} }}, + {{ {21, -4, -194}, 0, {993, 704}, {0, 0, 127, 255} }}, + }; +Gfx handle_Cylinder_mesh_tri_0[106] = { + gsSPVertex(handle_Cylinder_mesh_vtx_0 + 0, 30, 0), + gsSP2Triangles(0, 1, 2, 0, 3, 4, 5, 0), + gsSP2Triangles(6, 7, 8, 0, 9, 10, 11, 0), + gsSP2Triangles(12, 13, 14, 0, 15, 16, 17, 0), + gsSP2Triangles(18, 19, 20, 0, 21, 22, 23, 0), + gsSP2Triangles(24, 25, 26, 0, 27, 28, 29, 0), + gsSPVertex(handle_Cylinder_mesh_vtx_0 + 30, 30, 0), + gsSP2Triangles(0, 1, 2, 0, 3, 4, 5, 0), + gsSP2Triangles(6, 7, 8, 0, 9, 10, 11, 0), + gsSP2Triangles(12, 13, 14, 0, 15, 16, 17, 0), + gsSP2Triangles(18, 19, 20, 0, 21, 22, 23, 0), + gsSP2Triangles(24, 25, 26, 0, 27, 28, 29, 0), + gsSPVertex(handle_Cylinder_mesh_vtx_0 + 60, 30, 0), + gsSP2Triangles(0, 1, 2, 0, 3, 4, 5, 0), + gsSP2Triangles(6, 7, 8, 0, 9, 10, 11, 0), + gsSP2Triangles(12, 13, 14, 0, 15, 16, 17, 0), + gsSP2Triangles(18, 19, 20, 0, 21, 22, 23, 0), + gsSP2Triangles(24, 25, 26, 0, 27, 28, 29, 0), + gsSPVertex(handle_Cylinder_mesh_vtx_0 + 90, 30, 0), + gsSP2Triangles(0, 1, 2, 0, 3, 4, 5, 0), + gsSP2Triangles(6, 7, 8, 0, 6, 8, 9, 0), + gsSP2Triangles(10, 11, 12, 0, 10, 12, 13, 0), + gsSP2Triangles(14, 15, 16, 0, 14, 16, 17, 0), + gsSP2Triangles(18, 19, 20, 0, 18, 20, 21, 0), + gsSP2Triangles(22, 23, 24, 0, 22, 24, 25, 0), + gsSP2Triangles(26, 27, 28, 0, 26, 28, 29, 0), + gsSPVertex(handle_Cylinder_mesh_vtx_0 + 120, 32, 0), + gsSP2Triangles(0, 1, 2, 0, 0, 2, 3, 0), + gsSP2Triangles(4, 5, 6, 0, 4, 6, 7, 0), + gsSP2Triangles(8, 9, 10, 0, 8, 10, 11, 0), + gsSP2Triangles(12, 13, 14, 0, 12, 14, 15, 0), + gsSP2Triangles(16, 17, 18, 0, 16, 18, 19, 0), + gsSP2Triangles(20, 21, 22, 0, 20, 22, 23, 0), + gsSP2Triangles(24, 25, 26, 0, 24, 26, 27, 0), + gsSP2Triangles(28, 29, 30, 0, 28, 30, 31, 0), + gsSPVertex(handle_Cylinder_mesh_vtx_0 + 152, 32, 0), + gsSP2Triangles(0, 1, 2, 0, 0, 2, 3, 0), + gsSP2Triangles(4, 5, 6, 0, 4, 6, 7, 0), + gsSP2Triangles(8, 9, 10, 0, 8, 10, 11, 0), + gsSP2Triangles(12, 13, 14, 0, 12, 14, 15, 0), + gsSP2Triangles(16, 17, 18, 0, 16, 18, 19, 0), + gsSP2Triangles(20, 21, 22, 0, 20, 22, 23, 0), + gsSP2Triangles(24, 25, 26, 0, 24, 26, 27, 0), + gsSP2Triangles(28, 29, 30, 0, 28, 30, 31, 0), + gsSPVertex(handle_Cylinder_mesh_vtx_0 + 184, 32, 0), + gsSP2Triangles(0, 1, 2, 0, 0, 2, 3, 0), + gsSP2Triangles(4, 5, 6, 0, 4, 6, 7, 0), + gsSP2Triangles(8, 9, 10, 0, 8, 10, 11, 0), + gsSP2Triangles(12, 13, 14, 0, 12, 14, 15, 0), + gsSP2Triangles(16, 17, 18, 0, 16, 18, 19, 0), + gsSP2Triangles(20, 21, 22, 0, 20, 22, 23, 0), + gsSP2Triangles(24, 25, 26, 0, 24, 26, 27, 0), + gsSP2Triangles(28, 29, 30, 0, 28, 30, 31, 0), + gsSPVertex(handle_Cylinder_mesh_vtx_0 + 216, 32, 0), + gsSP2Triangles(0, 1, 2, 0, 0, 2, 3, 0), + gsSP2Triangles(2, 4, 3, 0, 0, 3, 5, 0), + gsSP2Triangles(3, 6, 5, 0, 3, 7, 6, 0), + gsSP2Triangles(6, 8, 5, 0, 5, 9, 10, 0), + gsSP2Triangles(5, 10, 11, 0, 10, 12, 11, 0), + gsSP2Triangles(5, 11, 13, 0, 11, 14, 13, 0), + gsSP2Triangles(11, 15, 14, 0, 14, 16, 13, 0), + gsSP2Triangles(13, 17, 18, 0, 13, 18, 19, 0), + gsSP2Triangles(18, 20, 19, 0, 13, 19, 21, 0), + gsSP2Triangles(19, 22, 21, 0, 19, 23, 22, 0), + gsSP2Triangles(22, 24, 21, 0, 21, 25, 26, 0), + gsSP2Triangles(21, 26, 27, 0, 26, 28, 27, 0), + gsSP2Triangles(21, 27, 0, 0, 27, 29, 0, 0), + gsSP2Triangles(27, 30, 29, 0, 29, 31, 0, 0), + gsSP2Triangles(0, 5, 13, 0, 13, 21, 0, 0), + gsSPVertex(handle_Cylinder_mesh_vtx_0 + 248, 32, 0), + gsSP2Triangles(0, 1, 2, 0, 0, 2, 3, 0), + gsSP2Triangles(4, 5, 6, 0, 4, 6, 7, 0), + gsSP2Triangles(8, 9, 10, 0, 8, 10, 11, 0), + gsSP2Triangles(10, 12, 11, 0, 8, 11, 13, 0), + gsSP2Triangles(11, 14, 13, 0, 11, 15, 14, 0), + gsSP2Triangles(14, 16, 13, 0, 13, 17, 18, 0), + gsSP2Triangles(13, 18, 19, 0, 18, 20, 19, 0), + gsSP2Triangles(13, 19, 21, 0, 19, 22, 21, 0), + gsSP2Triangles(19, 23, 22, 0, 22, 24, 21, 0), + gsSP2Triangles(21, 25, 26, 0, 21, 26, 27, 0), + gsSP2Triangles(26, 28, 27, 0, 21, 27, 29, 0), + gsSP2Triangles(27, 30, 29, 0, 27, 31, 30, 0), + gsSPVertex(handle_Cylinder_mesh_vtx_0 + 280, 32, 0), + gsSP2Triangles(0, 1, 2, 0, 2, 3, 4, 0), + gsSP2Triangles(2, 4, 5, 0, 4, 6, 5, 0), + gsSP2Triangles(2, 5, 7, 0, 5, 8, 7, 0), + gsSP2Triangles(5, 9, 8, 0, 8, 10, 7, 0), + gsSP2Triangles(7, 11, 12, 0, 12, 2, 7, 0), + gsSP2Triangles(13, 14, 15, 0, 13, 15, 16, 0), + gsSP2Triangles(15, 17, 16, 0, 13, 16, 18, 0), + gsSP2Triangles(16, 19, 18, 0, 16, 20, 19, 0), + gsSP2Triangles(19, 21, 18, 0, 18, 22, 23, 0), + gsSP2Triangles(18, 23, 24, 0, 23, 25, 24, 0), + gsSP2Triangles(18, 24, 26, 0, 24, 27, 26, 0), + gsSP2Triangles(24, 28, 27, 0, 27, 29, 26, 0), + gsSP1Triangle(26, 30, 31, 0), + gsSPVertex(handle_Cylinder_mesh_vtx_0 + 312, 17, 0), + gsSP2Triangles(0, 1, 2, 0, 1, 3, 2, 0), + gsSP2Triangles(0, 2, 4, 0, 2, 5, 4, 0), + gsSP2Triangles(2, 6, 5, 0, 5, 7, 4, 0), + gsSP2Triangles(4, 8, 9, 0, 4, 9, 10, 0), + gsSP2Triangles(9, 11, 10, 0, 4, 10, 12, 0), + gsSP2Triangles(10, 13, 12, 0, 10, 14, 13, 0), + gsSP2Triangles(13, 15, 12, 0, 12, 16, 0, 0), + gsSP1Triangle(0, 4, 12, 0), + gsSPEndDisplayList(), +}; + +Gfx mat_handle_f3dlite_material[9] = { + gsSPClearGeometryMode(G_CLIPPING), + gsSPSetLights1(handle_f3dlite_material_lights), + gsDPPipeSync(), + gsDPSetCombineLERP(0, 0, 0, SHADE, 0, 0, 0, ENVIRONMENT, 0, 0, 0, SHADE, 0, 0, 0, ENVIRONMENT), + gsDPSetAlphaDither(G_AD_NOISE), + gsSPTexture(65535, 65535, 0, 0, 1), + gsSPEndDisplayList(), +}; + +Gfx mat_revert_handle_f3dlite_material[4] = { + gsSPSetGeometryMode(G_CLIPPING), + gsDPPipeSync(), + gsDPSetAlphaDither(G_AD_DISABLE), + gsSPEndDisplayList(), +}; + +Gfx handle_Cylinder_mesh[13] = { + gsSPClearGeometryMode(G_LIGHTING), + gsSPVertex(handle_Cylinder_mesh_vtx_cull + 0, 8, 0), + gsSPSetGeometryMode(G_LIGHTING), + gsSPCullDisplayList(0, 7), + gsSPDisplayList(mat_handle_f3dlite_material), + gsSPDisplayList(handle_Cylinder_mesh_tri_0), + gsSPDisplayList(mat_revert_handle_f3dlite_material), + gsDPPipeSync(), + gsSPSetGeometryMode(G_LIGHTING), + gsSPClearGeometryMode(G_TEXTURE_GEN), + gsDPSetCombineLERP(0, 0, 0, SHADE, 0, 0, 0, ENVIRONMENT, 0, 0, 0, SHADE, 0, 0, 0, ENVIRONMENT), + gsSPTexture(65535, 65535, 0, 0, 0), + gsSPEndDisplayList(), +}; + +}; diff --git a/src/engine/editor/ObjectPicker.cpp b/src/engine/editor/ObjectPicker.cpp new file mode 100644 index 000000000..bc16b9db4 --- /dev/null +++ b/src/engine/editor/ObjectPicker.cpp @@ -0,0 +1,108 @@ +#include +#include +#include "../CoreMath.h" +#include +#include "../World.h" + +#include "ObjectPicker.h" +#include "port/Engine.h" +#include +#include + +#include "engine/actors/Ship.h" +#include "port/Game.h" +#include "Gizmo.h" + +#include "EditorMath.h" + +extern "C" { +#include "common_structs.h" +#include "main.h" +#include "defines.h" +#include "actors.h" +#include "math_util.h" +#include "math_util_2.h" +#include "camera.h" +} + +ObjectPicker::ObjectPicker() { + +} + +void ObjectPicker::SelectObject() { + FVector ray = ScreenRayTrace(); + + ObjectPicker::FindObject(ray); + + if (_selected != nullptr) { + eGizmo.Enable(&_selected->Pos, ray); + eGizmo.Enabled = true; + } else { + //eGizmo.Disable(); + eGizmo.Enabled = false; + } +} + +void ObjectPicker::Draw() { + if (_selected != nullptr) { + eGizmo.Draw(); + } +} + +void ObjectPicker::FindObject(FVector ray) { + // Is the gizmo being clicked? + if (eGizmo.Enabled) { + Gizmo::GizmoHandle handle = Gizmo::GizmoHandle::None; + for (size_t i = 0; i < 4; i++) { + float t; + auto [boxMin, boxMax] = eGizmo.GetBoundingBox((Gizmo::GizmoHandle) i); + + if (QueryCollisionRayActor(cameras[0].pos, &ray.x, &boxMin.x, &boxMax.x, &t)) { + handle = (Gizmo::GizmoHandle) i; + 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& actor : gWorldInstance.Actors) { + float boundingBox = actor->BoundingBoxSize; + if (boundingBox == 0.0f) { + boundingBox = 2.0f; + } + float t; + float max = 2.0f; + float min = -2.0f; + Vec3f boxMin = { actor->Pos[0] + boundingBox * min, + actor->Pos[1] + boundingBox * min, + actor->Pos[2] + boundingBox * min }; + + Vec3f boxMax = { actor->Pos[0] + actor->BoundingBoxSize * max, + actor->Pos[1] + actor->BoundingBoxSize * max, + actor->Pos[2] + actor->BoundingBoxSize * max }; + + if (QueryCollisionRayActor(cameras[0].pos, &ray.x, boxMin, boxMax, &t)) { + // if (actor == _selected) { + // _selected = nullptr; + // break; + // } + found = true; + //foundActor = &actor; + type = actor->Type; + _selected = actor; + break; + } + } + if (found) { + // printf("FOUND COLLISION %d\n", type); + } else { + // printf("NO COLLISION\n"); + _selected = nullptr; + } +} diff --git a/src/engine/editor/ObjectPicker.h b/src/engine/editor/ObjectPicker.h new file mode 100644 index 000000000..5c4679abe --- /dev/null +++ b/src/engine/editor/ObjectPicker.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include "engine/objects/Flagpole.h" +#include "Gizmo.h" + +class ObjectPicker { + public: + ObjectPicker(); + + void SelectObject(); + void Draw(); + void FindObject(FVector ray); + private: + bool _draw = false; + Vec3f _ray; + AActor* _selected; + AActor* _lastSelected; + s32 Inverse(MtxF* src, MtxF* dest); + void Copy(MtxF* src, MtxF* dest); + void Clear(MtxF* mf); + + void DrawObj(float length); + + Gizmo eGizmo; + +}; \ No newline at end of file diff --git a/src/main.c b/src/main.c index 48fcec7ac..94e076ca6 100644 --- a/src/main.c +++ b/src/main.c @@ -1250,7 +1250,6 @@ void thread5_iteration(void) { func_800CB2C4(); } #endif - calculate_updaterate(); if (GfxDebuggerIsDebugging()) { Graphics_PushFrame(gGfxPool->gfxPool); diff --git a/src/racing/framebuffer_effects.c b/src/racing/framebuffer_effects.c index 4406ca787..c0569ae03 100644 --- a/src/racing/framebuffer_effects.c +++ b/src/racing/framebuffer_effects.c @@ -16,13 +16,19 @@ s32 gReusableFrameBuffer = -1; // N64 resolution sized buffer (320x240), used by picto box and deku bubble s32 gN64ResFrameBuffer = -1; +s32 buf = -1; + void FB_CreateFramebuffers(void) { if (gReusableFrameBuffer == -1) { - gReusableFrameBuffer = gfx_create_framebuffer(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, true); + gReusableFrameBuffer = gfx_create_framebuffer(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, true, true, true, NULL); } if (gN64ResFrameBuffer == -1) { - gN64ResFrameBuffer = gfx_create_framebuffer(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, false); + gN64ResFrameBuffer = gfx_create_framebuffer(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, false, true, true, NULL); + } + + if (buf == -1) { + gN64ResFrameBuffer = gfx_create_framebuffer(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, false, true, true, NULL); } } @@ -69,9 +75,8 @@ void FB_CopyToFramebuffer(Gfx** gfxP, s32 fb_src, s32 fb_dest, u8 oncePerFrame, */ void FB_WriteFramebufferSliceToCPU(Gfx** gfxP, void* buffer, u8 byteSwap) { Gfx* gfx = *gfxP; - FB_CopyToFramebuffer(&gfx, 0, gReusableFrameBuffer, false, NULL); - + // Set the N64 resolution framebuffer as the draw target (320x240) gsSPSetFB(gfx++, gN64ResFrameBuffer); // Reset scissor for new framebuffer