summaryrefslogtreecommitdiff
path: root/2d/softbody/softbody_2/SpringRectangle.h
diff options
context:
space:
mode:
Diffstat (limited to '2d/softbody/softbody_2/SpringRectangle.h')
-rw-r--r--2d/softbody/softbody_2/SpringRectangle.h113
1 files changed, 92 insertions, 21 deletions
diff --git a/2d/softbody/softbody_2/SpringRectangle.h b/2d/softbody/softbody_2/SpringRectangle.h
index 47f4aff..848db23 100644
--- a/2d/softbody/softbody_2/SpringRectangle.h
+++ b/2d/softbody/softbody_2/SpringRectangle.h
@@ -3,7 +3,11 @@
#include "../../../shared_cpp/mathlib.h"
struct SoftbodyUpdateVertexData {
- Vector2 position;
+ Vector2 position; // Position is in world coordinates, for math's sake.
+ Vector2 displacement;
+ Vector2 initialVelocity;
+ Vector2 initialDisplacement;
+ bool isHovered = false;
SoftbodyUpdateVertexData* left;
SoftbodyUpdateVertexData* right;
@@ -11,24 +15,35 @@ struct SoftbodyUpdateVertexData {
SoftbodyUpdateVertexData* bottom;
};
-struct SoftbodyRectangle {
- float32 width = 100;
- float32 height = 100;
-
- Vector2 position = Vector2(300, 400);
+EM_BOOL onMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
+EM_BOOL onMouseDown(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
+EM_BOOL onMouseUp(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
- // Represents the density of springs that will be in the rectangle.
+struct SoftbodyRectangle {
+ float32 width = 200;
+ float32 height = 200;
+ Vector2 position;
int32 springDensity = 10;
+ float32 springConstant = 4.f; // in N /m
+ float32 jointMassKg = 10;
+ float32 angularVelocity = 0.f;
+
+ // Runtime data
float32 totalTimeSeconds = 0.f;
SoftbodyUpdateVertexData* updateData = NULL;
+ bool hasLastPositionChanged = false;
+ Vector2 lastMousePosition;
+ SoftbodyUpdateVertexData* draggedVertex = NULL;
+ // Render data
Mesh2d mesh;
Mesh2d pointsMesh;
-
Vertex2d* vertices = NULL;
Vertex2d* pointsVertices = NULL;
void load(Renderer2d* renderer) {
+ position = Vector2(800 / 2 - width / 2, 600 / 2 - height / 2);
+ angularVelocity = sqrtf(springConstant / jointMassKg);
int32 numVertices = springDensity * springDensity; // Each subdivision is a square.
int32 numIndices = 6 * ((springDensity - 1) * (springDensity - 1));
vertices = new Vertex2d[numVertices];
@@ -39,12 +54,16 @@ struct SoftbodyRectangle {
int32 vIdx = 0;
int32 iIdx = 0;
float32 inverseDensity = 1.f / springDensity;
- float32 halfInv = inverseDensity - (inverseDensity / 2.f);
+ float32 halfInv = inverseDensity / 2.f;
for (int32 y = 0; y < springDensity; y++) { // Rows
for (int32 x = 0; x < springDensity; x++) { // Columns
- Vector2 position = Vector2(x * inverseDensity - halfInv, y * inverseDensity- halfInv);
- vertices[vIdx] = { position, Vector4(1, 0, 0, 1) };
- updateData[vIdx].position = position;
+ Vector2 vpos = Vector2(x * inverseDensity - halfInv, y * inverseDensity- halfInv);
+ vpos.x = vpos.x * width + position.x;
+ vpos.y = vpos.y * height + position.y;
+ vertices[vIdx] = { vpos, Vector4(1, 0, 0, 1) };
+ updateData[vIdx].position = vpos;
+ updateData[vIdx].initialVelocity = Vector2(randomFloatBetween(0, 1.0) * 0.1, randomFloatBetween(0, 1.0) * 0.1);
+ updateData[vIdx].initialDisplacement = Vector2(randomFloatBetween(0, 1.0) * 0.1, randomFloatBetween(0, 1.0) * 0.1);
if (x != 0) updateData[vIdx].left = &updateData[vIdx - 1];
if (x != springDensity - 1) updateData[vIdx].right = &updateData[vIdx + 1];
@@ -65,32 +84,57 @@ struct SoftbodyRectangle {
}
mesh.load(vertices, numVertices, indices, numIndices, renderer, GL_DYNAMIC_DRAW);
- mesh.model = Mat4x4().scale(Vector3(width, height, 0)).translateByVec2(Vector2(300, 400));
+ // mesh.model = Mat4x4().scale(Vector3(width, height, 0)).translateByVec2(position);
pointsVertices = new Vertex2d[numVertices];
for (int32 v = 0; v < numVertices; v++) {
pointsVertices[v].position = vertices[v].position;
- pointsVertices[v].color = Vector4(1, 1, 0, 1);
+ pointsVertices[v].color = Vector4(0, 0, 0, 1);
}
- pointsMesh.model = mesh.model;
+ //pointsMesh.model = mesh.model;
pointsMesh.load(pointsVertices, numVertices, renderer, GL_DYNAMIC_DRAW);
delete [] indices;
+
+ // Setup callbacks
+ emscripten_set_mousemove_callback("#gl_canvas", this, false, onMouseMove);
+ emscripten_set_mousedown_callback("#gl_canvas", this, false, onMouseDown);
+ emscripten_set_mouseup_callback("#gl_canvas", this, false, onMouseUp);
}
void update(float32 dtSeconds) {
totalTimeSeconds += dtSeconds;
+
for (int32 v = 0; v < pointsMesh.numVertices; v++) {
- float32 r = rand();
- updateData[v].position += (Vector2(cosf(r), sinf(r)) * 0.005f);
+ auto springWeight = &updateData[v];
+
+ //springWeight->displacement.x = springWeight->initialDisplacement.x * cosf(angularVelocity * totalTimeSeconds - springWeight->initialVelocity.x);
+ //springWeight->displacement.y = springWeight->initialDisplacement.y * cosf(angularVelocity * totalTimeSeconds - springWeight->initialVelocity.y);
+ //Vector2 nextPosition = springWeight->position + springWeight->displacement;
+ //vertices[v].position = nextPosition;
+ //pointsVertices[v].position = nextPosition;
- Vector2 nextPosition = Vector2(updateData[v].position.x, updateData[v].position.y);
-
- vertices[v].position = nextPosition;
- pointsVertices[v].position = nextPosition;
+ if (springWeight == draggedVertex && hasLastPositionChanged) {
+ hasLastPositionChanged = false;
+ vertices[v].position = lastMousePosition;
+ pointsVertices[v].position = lastMousePosition;
+ }
+
+ if (!draggedVertex && hasLastPositionChanged) {
+ if ((springWeight->position - lastMousePosition).length() < 10.f) {
+ pointsVertices[v].color = Vector4(1, 1, 0, 1);
+ springWeight->isHovered = true;
+ }
+ else {
+ pointsVertices[v].color = Vector4(0, 0, 0, 1);
+ springWeight->isHovered = false;
+ }
+ }
}
+ if (hasLastPositionChanged) hasLastPositionChanged = false;
+
mesh.updateVertices(vertices);
pointsMesh.updateVertices(pointsVertices);
}
@@ -107,3 +151,30 @@ struct SoftbodyRectangle {
delete [] pointsVertices;
}
};
+
+EM_BOOL onMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) {
+ SoftbodyRectangle* rectangle = (SoftbodyRectangle*)userData;
+ rectangle->hasLastPositionChanged = true;
+ rectangle->lastMousePosition = Vector2(static_cast<float32>(mouseEvent->targetX), static_cast<float32>(600 - mouseEvent->targetY));
+ return true;
+}
+
+EM_BOOL onMouseDown(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) {
+ SoftbodyRectangle* rectangle = (SoftbodyRectangle*)userData;
+
+ for (int32 v = 0; v < rectangle->pointsMesh.numVertices; v++) {
+ auto springWeight = &rectangle->updateData[v];
+ if (springWeight->isHovered) {
+ rectangle->draggedVertex = springWeight;
+ break;
+ }
+ }
+
+ return true;
+}
+
+EM_BOOL onMouseUp(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) {
+ SoftbodyRectangle* rectangle = (SoftbodyRectangle*)userData;
+ rectangle->draggedVertex = NULL;
+ return true;
+}