From 606d9ee1f0f11727471e133cc001c83c0d47e9df Mon Sep 17 00:00:00 2001 From: mattkae Date: Sun, 23 Jan 2022 12:02:32 -0500 Subject: Able to hover, click, and drag a joint --- 2d/softbody/softbody_2/SpringRectangle.h | 113 +++++++++++++++++++++++++------ 2d/softbody/softbody_2/dist/output.js | 18 +++++ 2d/softbody/softbody_2/dist/output.wasm | Bin 44516 -> 37728 bytes 3 files changed, 110 insertions(+), 21 deletions(-) (limited to '2d/softbody/softbody_2') 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(mouseEvent->targetX), static_cast(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; +} diff --git a/2d/softbody/softbody_2/dist/output.js b/2d/softbody/softbody_2/dist/output.js index 2502d5e..51df416 100644 --- a/2d/softbody/softbody_2/dist/output.js +++ b/2d/softbody/softbody_2/dist/output.js @@ -2095,6 +2095,21 @@ var ASM_CONSTS = { return 0; } + function _emscripten_set_mousedown_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { + registerMouseEventCallback(target, userData, useCapture, callbackfunc, 5, "mousedown", targetThread); + return 0; + } + + function _emscripten_set_mousemove_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { + registerMouseEventCallback(target, userData, useCapture, callbackfunc, 8, "mousemove", targetThread); + return 0; + } + + function _emscripten_set_mouseup_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { + registerMouseEventCallback(target, userData, useCapture, callbackfunc, 6, "mouseup", targetThread); + return 0; + } + function __webgl_enable_ANGLE_instanced_arrays(ctx) { // Extension available in WebGL 1 from Firefox 26 and Google Chrome 30 onwards. Core feature in WebGL 2. var ext = ctx.getExtension('ANGLE_instanced_arrays'); @@ -3059,6 +3074,9 @@ var asmLibraryArg = { "emscripten_resize_heap": _emscripten_resize_heap, "emscripten_set_canvas_element_size": _emscripten_set_canvas_element_size, "emscripten_set_click_callback_on_thread": _emscripten_set_click_callback_on_thread, + "emscripten_set_mousedown_callback_on_thread": _emscripten_set_mousedown_callback_on_thread, + "emscripten_set_mousemove_callback_on_thread": _emscripten_set_mousemove_callback_on_thread, + "emscripten_set_mouseup_callback_on_thread": _emscripten_set_mouseup_callback_on_thread, "emscripten_webgl_create_context": _emscripten_webgl_create_context, "emscripten_webgl_destroy_context": _emscripten_webgl_destroy_context, "emscripten_webgl_init_context_attributes": _emscripten_webgl_init_context_attributes, diff --git a/2d/softbody/softbody_2/dist/output.wasm b/2d/softbody/softbody_2/dist/output.wasm index 35a32bd..cd26200 100755 Binary files a/2d/softbody/softbody_2/dist/output.wasm and b/2d/softbody/softbody_2/dist/output.wasm differ -- cgit v1.2.1