mirror of
https://github.com/HarbourMasters/SpaghettiKart
synced 2026-07-08 14:37:09 -04:00
gizmo work
This commit is contained in:
@@ -115,7 +115,7 @@ void World::PreviousCourse() {
|
||||
AActor* World::AddActor(AActor* actor) {
|
||||
Actors.push_back(actor);
|
||||
|
||||
gEditor.AddObject((FVector*) &actor->Pos, actor->Model, CollisionType::VTX_INTERSECT, 0.0f);
|
||||
gEditor.AddObject((FVector*) &actor->Pos, actor->Model, 1.0f, CollisionType::VTX_INTERSECT, 0.0f);
|
||||
|
||||
return Actors.back();
|
||||
}
|
||||
@@ -125,10 +125,9 @@ struct Actor* World::AddBaseActor(s16 actorType) {
|
||||
|
||||
AActor* actor = Actors.back();
|
||||
if (actorType == ACTOR_ITEM_BOX) {
|
||||
printf("ADD ITEM BOX\n");
|
||||
actor->Model = (Gfx*)LOAD_ASSET_RAW(itemBoxQuestionMarkModel);
|
||||
}
|
||||
gEditor.AddObject((FVector*) &actor->Pos, actor->Model, CollisionType::VTX_INTERSECT, 0.0f);
|
||||
gEditor.AddObject((FVector*) &actor->Pos, actor->Model, 1.0f, CollisionType::VTX_INTERSECT, 0.0f);
|
||||
// Skip C++ vtable to access variables in C
|
||||
return reinterpret_cast<struct Actor*>(reinterpret_cast<char*>(Actors.back()) + sizeof(void*));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "Collision.h"
|
||||
|
||||
|
||||
void GenerateCollisionMesh(GameObject& object, Gfx* model) {
|
||||
void GenerateCollisionMesh(GameObject& object, Gfx* model, float scale) {
|
||||
int8_t opcode;
|
||||
uintptr_t lo;
|
||||
uintptr_t hi;
|
||||
@@ -18,7 +18,7 @@ void GenerateCollisionMesh(GameObject& object, Gfx* model) {
|
||||
|
||||
switch(opcode) {
|
||||
case G_DL:
|
||||
GenerateCollisionMesh(object, (Gfx*)hi);
|
||||
GenerateCollisionMesh(object, (Gfx*)hi, scale);
|
||||
break;
|
||||
case G_VTX:
|
||||
vtx = (Vtx*)ptr->words.w1;
|
||||
|
||||
@@ -16,4 +16,4 @@
|
||||
|
||||
#define EDITOR_GFX_GET_OPCODE(var) ((uint32_t) ((var) & 0xFF000000))
|
||||
|
||||
void GenerateCollisionMesh(GameObject& object, Gfx* model);
|
||||
void GenerateCollisionMesh(GameObject& object, Gfx* model, float scale);
|
||||
|
||||
@@ -35,28 +35,62 @@ Editor::Editor() {
|
||||
void Editor::Load() {
|
||||
eObjectPicker.Load();
|
||||
for (auto& object : eGameObjects) {
|
||||
GenerateCollisionMesh(object, object.Model);
|
||||
GenerateCollisionMesh(object, object.Model, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::Tick() {
|
||||
auto wnd = GameEngine::Instance->context->GetWindow();
|
||||
|
||||
// GetMouseState
|
||||
if (wnd->MouseClick(Ship::LUS_MOUSE_BTN_LEFT)) {
|
||||
eObjectPicker.SelectObject(eGameObjects);
|
||||
static bool wasMouseDown = false;
|
||||
static bool isDragging = false;
|
||||
static Ship::Coords mouseStartPos;
|
||||
|
||||
Ship::Coords mousePos = wnd->GetMousePos();
|
||||
bool isMouseDown = wnd->GetMouseState(Ship::LUS_MOUSE_BTN_LEFT);
|
||||
|
||||
if (isMouseDown && !wasMouseDown) {
|
||||
// Mouse just pressed (Pressed state)
|
||||
mouseStartPos = mousePos;
|
||||
isDragging = false;
|
||||
}
|
||||
|
||||
if (isMouseDown) {
|
||||
// Mouse is being held (Held state)
|
||||
int dx = mousePos.x - mouseStartPos.x;
|
||||
int dy = mousePos.y - mouseStartPos.y;
|
||||
int dragThreshold = 5; // Adjust as needed
|
||||
|
||||
if ((dx * dx + dy * dy) > (dragThreshold * dragThreshold)) {
|
||||
// Squared distance check to avoid unnecessary sqrt()
|
||||
isDragging = true;
|
||||
eObjectPicker.DragHandle(); // Call drag logic
|
||||
}
|
||||
}
|
||||
|
||||
if (!isMouseDown && wasMouseDown) {
|
||||
// Mouse just released (Released state)
|
||||
eObjectPicker.eGizmo.SelectedHandle = Gizmo::GizmoHandle::None;
|
||||
if (!isDragging) {
|
||||
eObjectPicker.SelectObject(eGameObjects);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
wasMouseDown = isMouseDown; // Update previous state
|
||||
|
||||
eObjectPicker.Tick();
|
||||
}
|
||||
|
||||
void Editor::Draw() {
|
||||
eObjectPicker.Draw();
|
||||
}
|
||||
|
||||
void Editor::AddObject(FVector* pos, Gfx* model, CollisionType collision, float boundingBoxSize) {
|
||||
void Editor::AddObject(FVector* pos, Gfx* model, float scale, CollisionType collision, float boundingBoxSize) {
|
||||
|
||||
if (model != NULL) {
|
||||
eGameObjects.push_back({pos, model, {}, collision, boundingBoxSize});
|
||||
GenerateCollisionMesh(eGameObjects.back(), model);
|
||||
GenerateCollisionMesh(eGameObjects.back(), model, scale);
|
||||
} else { // to bounding box or sphere collision
|
||||
eGameObjects.push_back({pos, model, {}, CollisionType::BOUNDING_BOX, 2.0f});
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
void Draw();
|
||||
void MouseClick();
|
||||
void Load();
|
||||
void AddObject(FVector* pos, Gfx* model, CollisionType collision, float boundingBoxSize);
|
||||
void AddObject(FVector* pos, Gfx* model, float scale, CollisionType collision, float boundingBoxSize);
|
||||
private:
|
||||
bool _draw = false;
|
||||
Vec3f _ray;
|
||||
|
||||
@@ -191,11 +191,16 @@ void Clear(MtxF* mf) {
|
||||
mf->zw = 0.0f;
|
||||
}
|
||||
|
||||
bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, float& t) {
|
||||
bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, const FVector& objectPos, float& t) {
|
||||
const float EPSILON = 1e-6f;
|
||||
|
||||
FVector edge1 = tri.v1 - tri.v0;
|
||||
FVector edge2 = tri.v2 - tri.v0;
|
||||
// Adjust the triangle vertices by the object's position
|
||||
FVector v0 = tri.v0 + objectPos;
|
||||
FVector v1 = tri.v1 + objectPos;
|
||||
FVector v2 = tri.v2 + objectPos;
|
||||
|
||||
FVector edge1 = v1 - v0;
|
||||
FVector edge2 = v2 - v0;
|
||||
FVector h = ray.Direction.Cross(edge2);
|
||||
float a = edge1.Dot(h);
|
||||
|
||||
@@ -203,7 +208,7 @@ bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, float& t) {
|
||||
return false; // Ray is parallel to triangle
|
||||
|
||||
float f = 1.0f / a;
|
||||
FVector s = ray.Origin - tri.v0;
|
||||
FVector s = ray.Origin - v0;
|
||||
float u = f * s.Dot(h);
|
||||
|
||||
if (u < 0.0f || u > 1.0f)
|
||||
@@ -219,6 +224,7 @@ bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, float& t) {
|
||||
return t > EPSILON;
|
||||
}
|
||||
|
||||
|
||||
bool FindClosestObject(const Ray& ray, const std::vector<GameObject>& objects, GameObject& outObject, float& outDistance) {
|
||||
float closestDist = std::numeric_limits<float>::max();
|
||||
bool found = false;
|
||||
@@ -226,7 +232,7 @@ bool FindClosestObject(const Ray& ray, const std::vector<GameObject>& objects, G
|
||||
for (const auto& obj : objects) {
|
||||
for (const auto& tri : obj.Triangles) {
|
||||
float t;
|
||||
if (IntersectRayTriangle(ray, tri, t) && t < closestDist) {
|
||||
if (IntersectRayTriangle(ray, tri, *obj.Pos, t) && t < closestDist) {
|
||||
closestDist = t;
|
||||
outObject = obj;
|
||||
found = true;
|
||||
|
||||
@@ -46,7 +46,7 @@ s32 Inverse(MtxF* src, MtxF* dest);
|
||||
void Copy(MtxF* src, MtxF* dest);
|
||||
void Clear(MtxF* mf);
|
||||
|
||||
bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, float& t);
|
||||
bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, const FVector& objectPos, float& t);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -36,13 +36,23 @@ void Gizmo::Load() {
|
||||
BlueCollision.Pos = &Pos;
|
||||
BlueCollision.Model = handle_Cylinder_mesh;
|
||||
|
||||
GenerateCollisionMesh(RedCollision, RedCollision.Model);
|
||||
GenerateCollisionMesh(GreenCollision, GreenCollision.Model);
|
||||
GenerateCollisionMesh(BlueCollision, BlueCollision.Model);
|
||||
GenerateCollisionMesh(RedCollision, RedCollision.Model, 0.05f);
|
||||
GenerateCollisionMesh(GreenCollision, GreenCollision.Model, 0.05f);
|
||||
GenerateCollisionMesh(BlueCollision, BlueCollision.Model, 0.05f);
|
||||
}
|
||||
|
||||
void Gizmo::Tick() {
|
||||
|
||||
switch(SelectedHandle) {
|
||||
case GizmoHandle::X_Axis:
|
||||
Gizmo::Translate();
|
||||
break;
|
||||
case GizmoHandle::Y_Axis:
|
||||
Gizmo::Translate();
|
||||
break;
|
||||
case GizmoHandle::Z_Axis:
|
||||
Gizmo::Translate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<FVector, FVector> Gizmo::GetBoundingBox(GizmoHandle handle) {
|
||||
@@ -64,7 +74,6 @@ void Gizmo::StartManipulation(GizmoHandle handle) {
|
||||
case GizmoHandle::X_Axis:
|
||||
break;
|
||||
case GizmoHandle::Y_Axis:
|
||||
Gizmo::Translate();
|
||||
break;
|
||||
case GizmoHandle::Z_Axis:
|
||||
break;
|
||||
@@ -102,18 +111,31 @@ void Gizmo::Enable(GameObject* object, Ray ray) {
|
||||
void Gizmo::Translate() {
|
||||
static float length = 180.0f; // Default value
|
||||
|
||||
// Prevent nullptr exceptions
|
||||
if (_selected == NULL || _selected->Pos == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Enabled) {
|
||||
//FVector ray = ScreenRayTrace();
|
||||
|
||||
length = sqrt(
|
||||
pow(_selected->Pos->x - cameras[0].pos[0], 2) +
|
||||
pow(_selected->Pos->y - cameras[0].pos[1], 2) +
|
||||
pow(_selected->Pos->z - cameras[0].pos[2], 2)
|
||||
);
|
||||
|
||||
//_selected->Pos[0] = cameras[0].pos[0] + ray.x * length;
|
||||
_selected->Pos->x = cameras[0].pos[1] + _ray.y * length;
|
||||
//_selected->Pos[2] = cameras[0].pos[2] + ray.z * length;
|
||||
switch(SelectedHandle) {
|
||||
case GizmoHandle::X_Axis:
|
||||
_selected->Pos->x = cameras[0].pos[0] + _ray.x * length;
|
||||
break;
|
||||
case GizmoHandle::Y_Axis:
|
||||
_selected->Pos->y = cameras[0].pos[1] + _ray.y * length;
|
||||
break;
|
||||
case GizmoHandle::Z_Axis:
|
||||
_selected->Pos->z = cameras[0].pos[2] + _ray.z * length;
|
||||
break;
|
||||
}
|
||||
|
||||
Pos = FVector(
|
||||
_selected->Pos->x,
|
||||
_selected->Pos->y,
|
||||
|
||||
@@ -51,9 +51,9 @@ public:
|
||||
{0, 5, 0}, // Y-Axis (Green)
|
||||
{-5, 0, 0} // Z-Axis (Blue)
|
||||
};
|
||||
FVector _ray;
|
||||
private:
|
||||
bool _draw = false;
|
||||
FVector _ray;
|
||||
GameObject* _selected;
|
||||
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@ void ObjectPicker::Load() {
|
||||
eGizmo.Load();
|
||||
}
|
||||
|
||||
void ObjectPicker::Tick() {
|
||||
eGizmo.Tick();
|
||||
}
|
||||
|
||||
void ObjectPicker::SelectObject(std::vector<GameObject>& objects) {
|
||||
Ray ray;
|
||||
ray.Origin = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]);
|
||||
@@ -49,6 +53,53 @@ void ObjectPicker::SelectObject(std::vector<GameObject>& objects) {
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectPicker::DragHandle() {
|
||||
Ray ray;
|
||||
ray.Origin = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]);
|
||||
ray.Direction = ScreenRayTrace();
|
||||
|
||||
// Skip if a drag is already in progress
|
||||
if (eGizmo.SelectedHandle != Gizmo::GizmoHandle::None) {
|
||||
eGizmo._ray = ray.Direction;
|
||||
return;
|
||||
}
|
||||
|
||||
// Is the gizmo being dragged?
|
||||
if (eGizmo.Enabled) {
|
||||
for (auto tri = eGizmo.RedCollision.Triangles.begin(); tri < eGizmo.RedCollision.Triangles.end(); tri++) {
|
||||
float t;
|
||||
FVector pos = FVector(eGizmo.Pos.x, eGizmo.Pos.y, eGizmo.Pos.z - eGizmo._gizmoOffset);
|
||||
if (IntersectRayTriangle(ray, *tri, pos, t)) {
|
||||
//eGizmo.StartManipulation(Gizmo::GizmoHandle::X_Axis);
|
||||
eGizmo.SelectedHandle = Gizmo::GizmoHandle::Z_Axis;
|
||||
eGizmo._ray = ray.Direction;
|
||||
return; // Stop checking objects if we selected a Gizmo handle
|
||||
}
|
||||
}
|
||||
|
||||
for (auto tri = eGizmo.GreenCollision.Triangles.begin(); tri < eGizmo.GreenCollision.Triangles.end(); tri++) {
|
||||
float t;
|
||||
FVector pos = FVector(eGizmo.Pos.x - eGizmo._gizmoOffset, eGizmo.Pos.y, eGizmo.Pos.z);
|
||||
if (IntersectRayTriangle(ray, *tri, pos, t)) {
|
||||
//eGizmo.StartManipulation(Gizmo::GizmoHandle::Y_Axis);
|
||||
eGizmo.SelectedHandle = Gizmo::GizmoHandle::X_Axis;
|
||||
eGizmo._ray = ray.Direction;
|
||||
return; // Stop checking objects if we selected a Gizmo handle
|
||||
}
|
||||
}
|
||||
|
||||
for (auto tri = eGizmo.BlueCollision.Triangles.begin(); tri < eGizmo.BlueCollision.Triangles.end(); tri++) {
|
||||
float t;
|
||||
FVector pos = FVector(eGizmo.Pos.x, eGizmo.Pos.y + eGizmo._gizmoOffset, eGizmo.Pos.z);
|
||||
if (IntersectRayTriangle(ray, *tri, pos, t)) {
|
||||
eGizmo.SelectedHandle = Gizmo::GizmoHandle::Y_Axis;
|
||||
eGizmo._ray = ray.Direction;
|
||||
return; // Stop checking objects if we selected a Gizmo handle
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectPicker::Draw() {
|
||||
if (_selected != nullptr) {
|
||||
eGizmo.Draw();
|
||||
@@ -56,41 +107,6 @@ void ObjectPicker::Draw() {
|
||||
}
|
||||
|
||||
void ObjectPicker::FindObject(Ray ray, std::vector<GameObject>& objects) {
|
||||
// Is the gizmo being clicked?
|
||||
if (eGizmo.Enabled) {
|
||||
Gizmo::GizmoHandle handle = Gizmo::GizmoHandle::None;
|
||||
|
||||
for (auto tri = eGizmo.RedCollision.Triangles.begin(); tri < eGizmo.RedCollision.Triangles.end(); tri++) {
|
||||
float t;
|
||||
if (IntersectRayTriangle(ray, *tri, t)) {
|
||||
handle = Gizmo::GizmoHandle::X_Axis;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto tri = eGizmo.GreenCollision.Triangles.begin(); tri < eGizmo.GreenCollision.Triangles.end(); tri++) {
|
||||
float t;
|
||||
if (IntersectRayTriangle(ray, *tri, t)) {
|
||||
handle = Gizmo::GizmoHandle::Y_Axis;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto tri = eGizmo.BlueCollision.Triangles.begin(); tri < eGizmo.BlueCollision.Triangles.end(); tri++) {
|
||||
float t;
|
||||
if (IntersectRayTriangle(ray, *tri, t)) {
|
||||
handle = Gizmo::GizmoHandle::Z_Axis;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (handle != Gizmo::GizmoHandle::None) {
|
||||
eGizmo.StartManipulation(handle);
|
||||
return; // Stop checking objects if we selected a Gizmo handle
|
||||
}
|
||||
}
|
||||
|
||||
//s32 type = 0;
|
||||
bool found = false;
|
||||
for (auto& object : objects) {
|
||||
float boundingBox = object.BoundingBoxSize;
|
||||
@@ -102,7 +118,7 @@ void ObjectPicker::FindObject(Ray ray, std::vector<GameObject>& objects) {
|
||||
switch(object.Collision) {
|
||||
case CollisionType::VTX_INTERSECT:
|
||||
for (const auto& tri : object.Triangles) {
|
||||
if (IntersectRayTriangle(ray, tri, t)) {
|
||||
if (IntersectRayTriangle(ray, tri, *object.Pos, t)) {
|
||||
printf("\nSELECTED OBJECT\n\n");
|
||||
_selected = &object;
|
||||
}
|
||||
|
||||
@@ -11,9 +11,12 @@ class ObjectPicker {
|
||||
ObjectPicker();
|
||||
|
||||
void SelectObject(std::vector<GameObject>& objects);
|
||||
void DragHandle();
|
||||
void Draw();
|
||||
void FindObject(Ray ray, std::vector<GameObject>& objects);
|
||||
void Load();
|
||||
void Tick();
|
||||
Gizmo eGizmo;
|
||||
private:
|
||||
bool _draw = false;
|
||||
Vec3f _ray;
|
||||
@@ -25,5 +28,4 @@ class ObjectPicker {
|
||||
|
||||
void DrawObj(float length);
|
||||
|
||||
Gizmo eGizmo;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user