grab ignores back faces, properly selects closest vertex

feature/softbody-runtime-control
Benjamin Kraft 3 months ago
parent cf23267a9e
commit 2cc08361ac
  1. 20
      shaders/grab.comp
  2. 124
      src/camera.cpp
  3. 1
      src/vulkan/instance.cpp

@ -101,16 +101,24 @@ void testFace(uint fID){
vec3 ac = c - a; vec3 ac = c - a;
vec3 n = cross(ab, ac); vec3 n = cross(ab, ac);
// only front faces
if (dot(direction, n) < 0){ if (dot(direction, n) < 0){
return; return;
} }
float r = dot(a - origin, n) / dot(direction, n); float r = dot(a - origin, n) / dot(direction, n);
// no faces behind us
if (r < 0){ if (r < 0){
return; return;
} }
vec3 q = origin + r * direction; 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 qa = a - q;
vec3 qb = b - q; vec3 qb = b - q;
vec3 qc = c - q; vec3 qc = c - q;
@ -131,7 +139,19 @@ void testFace(uint fID){
} while (atomicCompSwap(distanceToFace, expectedOriginalDistance, newDistance) != expectedOriginalDistance); } while (atomicCompSwap(distanceToFace, expectedOriginalDistance, newDistance) != expectedOriginalDistance);
if (newDistance == floatBitsToUint(r)){ if (newDistance == floatBitsToUint(r)){
foundHit = true; foundHit = true;
// vertex nearest to q
if (length(qa) < length(qb)){
if (length(qa) < length(qc)){
vID = face.a; vID = face.a;
} else {
vID = face.c;
}
} else if (length(qb) < length(qc)){
vID = face.b;
} else {
vID = face.c;
}
} }
} }
} }

@ -62,127 +62,3 @@ void Camera::mouseMoved(const glm::vec2 &delta) {
float margin = 0.01; float margin = 0.01;
theta = glm::clamp(theta, -glm::half_pi<float>() + margin, glm::half_pi<float>() - margin); theta = glm::clamp(theta, -glm::half_pi<float>() + margin, glm::half_pi<float>() - 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<GLfloat*>(glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY));
#endif
std::vector<RayHit> 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<double>();
b = Vector3f(
gpuData[f.b * GL_VERTEX_SIZE + 0],
gpuData[f.b * GL_VERTEX_SIZE + 1],
gpuData[f.b * GL_VERTEX_SIZE + 2]).cast<double>();
c = Vector3f(
gpuData[f.c * GL_VERTEX_SIZE + 0],
gpuData[f.c * GL_VERTEX_SIZE + 1],
gpuData[f.c * GL_VERTEX_SIZE + 2]).cast<double>();
#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));
}
}
*/

@ -150,6 +150,7 @@ void Instance::createLogicalDevice() {
} }
VkPhysicalDeviceFeatures deviceFeatures {}; VkPhysicalDeviceFeatures deviceFeatures {};
deviceFeatures.fillModeNonSolid = true;
VkDeviceCreateInfo createInfo {}; VkDeviceCreateInfo createInfo {};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;

Loading…
Cancel
Save