Failed attempt at transforming collision

This commit is contained in:
MegaMech
2025-04-07 16:44:14 -06:00
parent f5f36fee7d
commit 529f7c8bcf
8 changed files with 181 additions and 27 deletions
+10
View File
@@ -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
};
+84 -2
View File
@@ -1,5 +1,14 @@
#include "Collision.h"
#include <libultraship/libultraship.h>
#include <libultra/gbi.h>
#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<GameObject*, std::vector<Vtx>> gDebugObjVtxCache;
// Render a collision model
void DebugCollision(GameObject* obj, FVector pos, IRotator rot, FVector scale, const std::vector<Triangle>& 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);
}
}
+1
View File
@@ -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<Triangle>& triangles);
}
+34 -6
View File
@@ -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;
+1
View File
@@ -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);
+32 -9
View File
@@ -6,10 +6,12 @@
#include "EditorMath.h"
#include "Gizmo.h"
#include "Collision.h"
#include "port/Engine.h"
#include <controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h>
#include <window/Window.h>
#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";
+5 -1
View File
@@ -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;
+14 -9
View File
@@ -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<Gizmo::TranslationMode>(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;