From 2cc08361ac202e0a4690faf46da8f1aebec5fa0a Mon Sep 17 00:00:00 2001 From: Benjamin Kraft Date: Sun, 6 Oct 2024 16:12:33 +0200 Subject: [PATCH] grab ignores back faces, properly selects closest vertex --- shaders/grab.comp | 22 ++++++- src/camera.cpp | 124 ---------------------------------------- src/vulkan/instance.cpp | 1 + 3 files changed, 22 insertions(+), 125 deletions(-) diff --git a/shaders/grab.comp b/shaders/grab.comp index 1d3e401..a8949d7 100644 --- a/shaders/grab.comp +++ b/shaders/grab.comp @@ -101,16 +101,24 @@ void testFace(uint fID){ vec3 ac = c - a; vec3 n = cross(ab, ac); + + // only front faces if (dot(direction, n) < 0){ return; } float r = dot(a - origin, n) / dot(direction, n); + + // no faces behind us if (r < 0){ return; } + vec3 q = origin + r * direction; + // check if q is inside triangle + // https://math.stackexchange.com/questions/4322/check-whether-a-point-is-within-a-3d-triangle + vec3 qa = a - q; vec3 qb = b - q; vec3 qc = c - q; @@ -131,7 +139,19 @@ void testFace(uint fID){ } while (atomicCompSwap(distanceToFace, expectedOriginalDistance, newDistance) != expectedOriginalDistance); if (newDistance == floatBitsToUint(r)){ foundHit = true; - vID = face.a; + + // vertex nearest to q + if (length(qa) < length(qb)){ + if (length(qa) < length(qc)){ + vID = face.a; + } else { + vID = face.c; + } + } else if (length(qb) < length(qc)){ + vID = face.b; + } else { + vID = face.c; + } } } } diff --git a/src/camera.cpp b/src/camera.cpp index a5efd7f..a8d8588 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -62,127 +62,3 @@ void Camera::mouseMoved(const glm::vec2 &delta) { float margin = 0.01; theta = glm::clamp(theta, -glm::half_pi() + margin, glm::half_pi() - margin); } - -/* - * Vector3d Camera::toNDC(const Vector3d &pWorld) const { - Matrix4d VP = getProjection() * getView(); - return (VP * pWorld.homogeneous()).hnormalized(); -} - -Vector3d Camera::toWorld(const Vector3d &ndcCube) const { - Matrix4d VPinv = (getProjection() * getView()).inverse(); - return (VPinv * ndcCube.homogeneous()).hnormalized(); -} - -Ray Camera::rayForward(const Vector2d &screen) const { - Vector2d ndc = {(screen.x() / viewport.width() * 2) - 1, (2 - (screen.y() / viewport.height()) * 2) - 1}; - - Vector3d a, b; - a.head(2) = b.head(2) = ndc; - a(2) = -1; // near - b(2) = 1; // far - - Vector3d p1 = toWorld(a); - Vector3d p2 = toWorld(b); - - return {p1, (p2 - p1).normalized()}; -} - -Vector3d Camera::movePoint(const Vector3d &p, const Vector2d& pixelDelta) const { - Vector3d ndcDelta = {(pixelDelta.x() / viewport.width() * 2), -(pixelDelta.y() / viewport.height()) * 2, 0}; - - Vector3d ndc = toNDC(p); - Vector3d ndc2 = ndc + ndcDelta; - - Vector3d p2 = toWorld(ndc2); - - return p2 - p; -} - */ - -/* - * bool SoftBody::testRay(const Ray &ray, RayHit& rayHit) { - - GLfloat* gpuData; -#if USE_GPU - glBindBuffer(GL_SHADER_STORAGE_BUFFER, VBO); - gpuData = static_cast(glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY)); -#endif - - std::vector validResults; - for (size_t triangleId = 0; triangleId < outerFaces.size(); triangleId++){ - Face f = outerFaces[triangleId]; - Vector3d a = vertices[f.a].p; - Vector3d b = vertices[f.b].p; - Vector3d c = vertices[f.c].p; - -#if USE_GPU - a = Vector3f( - gpuData[f.a * GL_VERTEX_SIZE + 0], - gpuData[f.a * GL_VERTEX_SIZE + 1], - gpuData[f.a * GL_VERTEX_SIZE + 2]).cast(); - b = Vector3f( - gpuData[f.b * GL_VERTEX_SIZE + 0], - gpuData[f.b * GL_VERTEX_SIZE + 1], - gpuData[f.b * GL_VERTEX_SIZE + 2]).cast(); - c = Vector3f( - gpuData[f.c * GL_VERTEX_SIZE + 0], - gpuData[f.c * GL_VERTEX_SIZE + 1], - gpuData[f.c * GL_VERTEX_SIZE + 2]).cast(); -#endif - - Vector3d ab = b - a; - Vector3d ac = c - a; - * - * Line G: x = rayOrigin + r * rayDirection - * Plane A: (x - a) * n = 0 - * Intersection point q between G and A - * - * 0 = (x - a) * n = (o + r * d - a) * n = o * n + r * d * n - a * n - * <=> 0 = o * n + r * d * n - a * n - * <=> r * d * n = a * n - o * n = (a - o) * n - * <=> r = ((a - o) * n) / (d * n) - * q = o + r * d - * - * Select nearest point of triangle to q - * - * - * - -Vector3d n = ab.cross(ac); -double r = (a - ray.origin).dot(n) / ray.direction.dot(n); -Vector3d q = ray.origin + r * ray.direction; - -// check if q is inside triangle -// https://math.stackexchange.com/questions/4322/check-whether-a-point-is-within-a-3d-triangle - -Vector3d qa = a - q; -Vector3d qb = b - q; -Vector3d qc = c - q; - -double area = ab.cross(ac).norm() / 2; -double alpha = (qb).cross(qc).norm() / (2 * area); -double beta = (qc).cross(qa).norm() / (2 * area); -double gamma = (qa).cross(qb).norm() / (2 * area); - -bool isOne = std::abs(alpha + beta + gamma - 1) < 0.00001; - -if (alpha >= 0 && alpha <= 1 && beta >= 0 && beta <= 1 && gamma >= 0 && gamma <= 1 && isOne){ - -// find vertex nearest to q -size_t vId; -if (qa.norm() < qb.norm()){ -if (qa.norm() < qc.norm()) -vId = f.a; -else -vId = f.c; -} else if (qb.norm() < qc.norm()) -vId = f.b; -else -vId = f.c; - -validResults.push_back(RayHit(r, q, triangleId, vId)); -} - -} - */ diff --git a/src/vulkan/instance.cpp b/src/vulkan/instance.cpp index 22d85b2..046efac 100644 --- a/src/vulkan/instance.cpp +++ b/src/vulkan/instance.cpp @@ -150,6 +150,7 @@ void Instance::createLogicalDevice() { } VkPhysicalDeviceFeatures deviceFeatures {}; + deviceFeatures.fillModeNonSolid = true; VkDeviceCreateInfo createInfo {}; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;