From 4caa65a4374a0e510e5dd7426d4346ec44d35763 Mon Sep 17 00:00:00 2001 From: maelstrom Date: Sat, 1 Feb 2025 21:15:53 +0100 Subject: [PATCH] intersting --- editor/mainglwidget.cpp | 69 +++++++++++++++++++++++++++++++++++--- src/physics/simulation.cpp | 11 +++++- src/physics/simulation.h | 5 ++- 3 files changed, 79 insertions(+), 6 deletions(-) diff --git a/editor/mainglwidget.cpp b/editor/mainglwidget.cpp index 0e8e09f..6b82f16 100644 --- a/editor/mainglwidget.cpp +++ b/editor/mainglwidget.cpp @@ -2,11 +2,17 @@ #include #include +#include +#include +#include +#include +#include #include "GLFW/glfw3.h" #include "qcursor.h" #include "qevent.h" #include "qnamespace.h" +#include "qwindowdefs.h" #include "rendering/renderer.h" #include "physics/simulation.h" #include "camera.h" @@ -50,11 +56,66 @@ void MainGLWidget::mouseMoveEvent(QMouseEvent* evt) { // QCursor::setPos(lastMousePos); } -void MainGLWidget::mousePressEvent(QMouseEvent* evt) { - if (evt->button() != Qt::RightButton) return; +class FirstRayHit : public rp::RaycastCallback { + rp::Body** target; - lastMousePos = evt->pos(); - isMouseDragging = true; + virtual rp::decimal notifyRaycastHit(const rp::RaycastInfo& raycastInfo) override { + if (reinterpret_cast(raycastInfo.body->getUserData())->name == "Baseplate") return 1; + + *target = raycastInfo.body; + return 0; + } + +public: + FirstRayHit(rp::Body** target) : target(target) {} +}; + +void MainGLWidget::mousePressEvent(QMouseEvent* evt) { + switch(evt->button()) { + // Camera drag + case Qt::RightButton: { + lastMousePos = evt->pos(); + isMouseDragging = true; + return; + // Clicking on objects + } case Qt::LeftButton: { + QPoint position = evt->pos(); + rp::Body* rayHitTarget = NULL; + + // VVV Thank goodness for this person's answer + // https://stackoverflow.com/a/30005258/16255372 + + // glm::vec3 worldPos = camera.cameraPos + glm::vec3(glm::vec4(float(position.x()) / width() - 0.5f, float(position.y()) / height() - 0.5f, 0, 0) * camera.getLookAt()); + glm::mat4 projection = glm::perspective(glm::radians(45.f), (float)width() / (float)height(), 0.1f, 100.0f); + glm::mat4 view = glm::lookAt(glm::vec3(0), camera.cameraFront, camera.cameraUp); + glm::mat4 inverseViewport = glm::inverse(projection * view); + + glm::vec2 ndc = glm::vec2(float(position.x()) / width() * 2.f - 1.f, -float(position.y()) / height() * 2.f + 1.f); + glm::vec4 world = glm::normalize(inverseViewport * glm::vec4(ndc, 1, 1)); + glm::vec3 flat = glm::vec3(world) / world.w; // https://stackoverflow.com/a/68870587/16255372 + + printf("At: %f; %f; %f\n", world.x, world.y, world.z); + + workspace->AddChild(lastPart = Part::New({ + .position = camera.cameraPos + glm::vec3(world) * 10.f, + .rotation = glm::vec3(0), + .scale = glm::vec3(1, 1, 1), + .material = Material { + .diffuse = glm::vec3(1.0f, 0.5f, 0.31f), + .specular = glm::vec3(0.5f, 0.5f, 0.5f), + .shininess = 32.0f, + }, + .anchored = true, + })); + syncPartPhysics(lastPart); + + castRay(camera.cameraPos, world, 500, new FirstRayHit(&rayHitTarget)); + if (!rayHitTarget) return; + printf("Hit: %s\n", reinterpret_cast(rayHitTarget->getUserData())->name.c_str()); + return; + } default: + return; + } } void MainGLWidget::mouseReleaseEvent(QMouseEvent* evt) { diff --git a/src/physics/simulation.cpp b/src/physics/simulation.cpp index 6dba846..d86e4c4 100644 --- a/src/physics/simulation.cpp +++ b/src/physics/simulation.cpp @@ -2,12 +2,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -36,6 +38,8 @@ void simulationInit() { world = physicsCommon->createPhysicsWorld(); world->setGravity(rp::Vector3(0, -196.2, 0)); + + world->setEventListener(&eventListener); } void syncPartPhysics(std::shared_ptr part) { @@ -58,7 +62,7 @@ void syncPartPhysics(std::shared_ptr part) { part->rigidBody->addCollider(shape, rp::Transform()); part->rigidBody->setType(part->anchored ? rp::BodyType::STATIC : rp::BodyType::DYNAMIC); - world->setEventListener(&eventListener); + part->rigidBody->setUserData(&*part); } void physicsStep(float deltaTime) { @@ -75,4 +79,9 @@ void physicsStep(float deltaTime) { // part.rotation = glm::eulerAngles(rpToGlm(transform.getOrientation())); part->rotation = rpToGlm(transform.getOrientation()); } +} + +void castRay(glm::vec3 point, glm::vec3 rotation, float maxLength, rp::RaycastCallback* callback) { + rp::Ray ray(glmToRp(point), glmToRp(glm::normalize(rotation)) * maxLength); + world->raycast(ray, callback); } \ No newline at end of file diff --git a/src/physics/simulation.h b/src/physics/simulation.h index f9d4f0a..203671d 100644 --- a/src/physics/simulation.h +++ b/src/physics/simulation.h @@ -1,8 +1,11 @@ #pragma once #include "../objects/part.h" +#include #include +#include void simulationInit(); void syncPartPhysics(std::shared_ptr part); -void physicsStep(float deltaTime); \ No newline at end of file +void physicsStep(float deltaTime); +void castRay(glm::vec3 point, glm::vec3 rotation, float maxLength, rp::RaycastCallback* callback); \ No newline at end of file