parent
b44339ea14
commit
6ffe08a013
14 changed files with 541 additions and 63 deletions
@ -0,0 +1,18 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "input.hpp" |
||||||
|
#include "glm/vec2.hpp" |
||||||
|
|
||||||
|
class Grabber : MouseListener { |
||||||
|
public: |
||||||
|
bool started(); |
||||||
|
bool stopped(); |
||||||
|
bool moved(glm::vec2 &delta); |
||||||
|
glm::vec2 previousCursorPosition; |
||||||
|
protected: |
||||||
|
virtual void mouseButtonPressed(int button); |
||||||
|
virtual void mouseButtonReleased(int button); |
||||||
|
private: |
||||||
|
bool start = false; |
||||||
|
bool stop = false; |
||||||
|
}; |
@ -0,0 +1,180 @@ |
|||||||
|
#version 450 |
||||||
|
|
||||||
|
layout (local_size_x = 32) in; |
||||||
|
|
||||||
|
struct Vertex { |
||||||
|
vec3 position; |
||||||
|
vec3 color; |
||||||
|
vec2 uv; |
||||||
|
vec3 normal; |
||||||
|
vec3 velocity; |
||||||
|
vec3 prevPosition; |
||||||
|
float inverseMass; |
||||||
|
}; |
||||||
|
|
||||||
|
struct Face { |
||||||
|
uint a; |
||||||
|
uint b; |
||||||
|
uint c; |
||||||
|
}; |
||||||
|
|
||||||
|
layout (std430, set = 0, binding = 0) buffer VertexBuffer { |
||||||
|
Vertex vertices[]; |
||||||
|
}; |
||||||
|
layout (std430, set = 0, binding = 1) buffer FaceBuffer { |
||||||
|
Face faces[]; |
||||||
|
}; |
||||||
|
|
||||||
|
layout (std140, set = 0, binding = 5) uniform Sizes { |
||||||
|
uint vertexCount; |
||||||
|
uint faceCount; |
||||||
|
}; |
||||||
|
|
||||||
|
layout (set = 1, binding = 0) uniform CameraUniform { |
||||||
|
mat4 view; |
||||||
|
mat4 projection; |
||||||
|
vec2 viewport; |
||||||
|
} camera; |
||||||
|
|
||||||
|
|
||||||
|
layout (std430, set = 2, binding = 1) buffer GrabInformation { |
||||||
|
float originalInverseMass; |
||||||
|
uint vID; |
||||||
|
float distanceToFace; |
||||||
|
bool foundHit; |
||||||
|
}; |
||||||
|
|
||||||
|
layout (push_constant, std430) uniform PushConstants { |
||||||
|
uint state; |
||||||
|
vec2 screenPosition; |
||||||
|
vec2 screenDelta; |
||||||
|
}; |
||||||
|
|
||||||
|
vec3 toNDC(vec3 world){ |
||||||
|
mat4 realProjection = camera.projection; |
||||||
|
realProjection[1][1] *= -1; |
||||||
|
|
||||||
|
mat4 VP = realProjection * camera.view; |
||||||
|
|
||||||
|
vec4 inhomo = VP * vec4(world, 1); |
||||||
|
|
||||||
|
return vec3(inhomo.xyz / inhomo.w); |
||||||
|
} |
||||||
|
|
||||||
|
vec3 toWorld(vec3 ndcCube){ |
||||||
|
mat4 realProjection = camera.projection; |
||||||
|
realProjection[1][1] *= -1; |
||||||
|
mat4 VPinv = inverse(realProjection * camera.view); |
||||||
|
|
||||||
|
vec4 inhomo = VPinv * vec4(ndcCube, 1); |
||||||
|
|
||||||
|
return vec3(inhomo.xyz / inhomo.w); |
||||||
|
} |
||||||
|
|
||||||
|
void rayForward(out vec3 origin, out vec3 direction){ |
||||||
|
vec2 ndc = vec2( |
||||||
|
(2 * screenPosition.x / camera.viewport.x) - 1, |
||||||
|
1 - (2 * screenPosition.y / camera.viewport.y) |
||||||
|
); |
||||||
|
|
||||||
|
vec3 a = vec3(ndc, 0); |
||||||
|
vec3 b = vec3(ndc, 1); |
||||||
|
|
||||||
|
vec3 p1 = toWorld(a); |
||||||
|
vec3 p2 = toWorld(b); |
||||||
|
|
||||||
|
origin = p1; |
||||||
|
direction = normalize(p2 - p1); |
||||||
|
} |
||||||
|
|
||||||
|
void testFace(uint fID){ |
||||||
|
// test this face, if hit, set grabinformation if distance is new minimum |
||||||
|
vec3 origin; |
||||||
|
vec3 direction; |
||||||
|
rayForward(origin, direction); |
||||||
|
|
||||||
|
Face face = faces[fID]; |
||||||
|
vec3 a = vertices[face.a].position; |
||||||
|
vec3 b = vertices[face.b].position; |
||||||
|
vec3 c = vertices[face.c].position; |
||||||
|
|
||||||
|
vec3 ab = b - a; |
||||||
|
vec3 ac = c - a; |
||||||
|
|
||||||
|
vec3 n = cross(ab, ac); |
||||||
|
float r = dot(a - origin, n) / dot(direction, n); |
||||||
|
vec3 q = origin + r * direction; |
||||||
|
|
||||||
|
vec3 qa = a - q; |
||||||
|
vec3 qb = b - q; |
||||||
|
vec3 qc = c - q; |
||||||
|
|
||||||
|
float area = length(cross(ab, ac)) / 2; |
||||||
|
float alpha = length(cross(qb, qc)) / (2 * area); |
||||||
|
float beta = length(cross(qc, qa)) / (2 * area); |
||||||
|
float gamma = length(cross(qa, qb)) / (2 * area); |
||||||
|
|
||||||
|
bool isOne = abs(alpha + beta + gamma - 1) < 0.001; |
||||||
|
|
||||||
|
if (alpha >= 0 && alpha <= 1 && beta >= 0 && beta <= 1 && gamma >= 0 && gamma <= 1 && isOne){ |
||||||
|
if (r < distanceToFace){ |
||||||
|
foundHit = true; |
||||||
|
vID = face.a; |
||||||
|
distanceToFace = r; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void move(){ |
||||||
|
vec3 ndcDelta = vec3( |
||||||
|
2 * screenDelta.x / camera.viewport.x, |
||||||
|
-2 * screenDelta.y / camera.viewport.y, |
||||||
|
0 |
||||||
|
); |
||||||
|
|
||||||
|
vec3 ndc = toNDC(vertices[vID].position); |
||||||
|
vec3 ndc2 = ndc + ndcDelta; |
||||||
|
|
||||||
|
vec3 p2 = toWorld(ndc2); |
||||||
|
|
||||||
|
vec3 worldDelta = p2 - vertices[vID].position; |
||||||
|
|
||||||
|
vertices[vID].position += worldDelta; |
||||||
|
} |
||||||
|
|
||||||
|
void release(){ |
||||||
|
vertices[vID].inverseMass = originalInverseMass; |
||||||
|
distanceToFace = 1e20; |
||||||
|
foundHit = false; |
||||||
|
} |
||||||
|
|
||||||
|
void main(){ |
||||||
|
uint id = gl_GlobalInvocationID.x; |
||||||
|
|
||||||
|
switch (state){ |
||||||
|
case 0: |
||||||
|
if (id < faceCount){ |
||||||
|
testFace(id); |
||||||
|
} |
||||||
|
break; |
||||||
|
case 1: |
||||||
|
if (id == 0 && foundHit){ |
||||||
|
originalInverseMass = vertices[vID].inverseMass; |
||||||
|
vertices[vID].inverseMass = 0; |
||||||
|
} |
||||||
|
break; |
||||||
|
case 2: |
||||||
|
if (id == 0 && foundHit){ |
||||||
|
move(); |
||||||
|
} |
||||||
|
break; |
||||||
|
case 3: |
||||||
|
if (id == 0 && foundHit){ |
||||||
|
release(); |
||||||
|
} |
||||||
|
break; |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
#include "grabber.hpp" |
||||||
|
|
||||||
|
void Grabber::mouseButtonPressed(int button) { |
||||||
|
if (button != GLFW_MOUSE_BUTTON_LEFT) |
||||||
|
return; |
||||||
|
|
||||||
|
start = true; |
||||||
|
previousCursorPosition = Input::instance->currentCursorPosition; |
||||||
|
} |
||||||
|
|
||||||
|
void Grabber::mouseButtonReleased(int button) { |
||||||
|
if (button != GLFW_MOUSE_BUTTON_LEFT) |
||||||
|
return; |
||||||
|
|
||||||
|
stop = true; |
||||||
|
} |
||||||
|
|
||||||
|
bool Grabber::started() { |
||||||
|
if (start){ |
||||||
|
start = false; |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool Grabber::stopped() { |
||||||
|
if (stop){ |
||||||
|
stop = false; |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool Grabber::moved(glm::vec2 &delta) { |
||||||
|
if (!Input::MouseButtonIsDown[GLFW_MOUSE_BUTTON_LEFT]) |
||||||
|
return false; |
||||||
|
|
||||||
|
glm::vec2 currentCursorPosition = Input::instance->currentCursorPosition; |
||||||
|
if (previousCursorPosition == currentCursorPosition) |
||||||
|
return false; |
||||||
|
delta = currentCursorPosition - previousCursorPosition; |
||||||
|
previousCursorPosition = currentCursorPosition; |
||||||
|
return true; |
||||||
|
} |
Loading…
Reference in new issue