#include "../../../shared_cpp/Renderer2d.h" #include "../../../shared_cpp/types.h" #include "../../../shared_cpp/mathlib.h" struct SoftbodyUpdateVertexData { Vector2 position; SoftbodyUpdateVertexData* left; SoftbodyUpdateVertexData* right; SoftbodyUpdateVertexData* top; SoftbodyUpdateVertexData* bottom; }; struct SoftbodyRectangle { float32 width = 100; float32 height = 100; Vector2 position = Vector2(300, 400); // Represents the density of springs that will be in the rectangle. int32 springDensity = 10; float32 totalTimeSeconds = 0.f; SoftbodyUpdateVertexData* updateData = NULL; Mesh2d mesh; Mesh2d pointsMesh; Vertex2d* vertices = NULL; Vertex2d* pointsVertices = NULL; void load(Renderer2d* renderer) { int32 numVertices = springDensity * springDensity; // Each subdivision is a square. int32 numIndices = 6 * ((springDensity - 1) * (springDensity - 1)); vertices = new Vertex2d[numVertices]; updateData = new SoftbodyUpdateVertexData[numVertices]; auto indices = new GLuint[numIndices]; // Load a square with the desired density int32 vIdx = 0; int32 iIdx = 0; float32 inverseDensity = 1.f / springDensity; float32 halfInv = inverseDensity - (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; if (x != 0) updateData[vIdx].left = &updateData[vIdx - 1]; if (x != springDensity - 1) updateData[vIdx].right = &updateData[vIdx + 1]; if (y != 0) updateData[vIdx].top = &updateData[vIdx - springDensity]; if (y != springDensity - 1) updateData[vIdx].bottom = &updateData[vIdx + springDensity]; if (y != springDensity - 1 && x != springDensity - 1) { indices[iIdx++] = vIdx; indices[iIdx++] = vIdx + 1; indices[iIdx++] = vIdx + springDensity; indices[iIdx++] = vIdx + springDensity; indices[iIdx++] = vIdx + springDensity + 1; indices[iIdx++] = vIdx + 1; } vIdx++; } } mesh.load(vertices, numVertices, indices, numIndices, renderer, GL_DYNAMIC_DRAW); mesh.model = Mat4x4().scale(Vector3(width, height, 0)).translateByVec2(Vector2(300, 400)); 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); } pointsMesh.model = mesh.model; pointsMesh.load(pointsVertices, numVertices, renderer, GL_DYNAMIC_DRAW); delete [] indices; } 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); Vector2 nextPosition = Vector2(updateData[v].position.x, updateData[v].position.y); vertices[v].position = nextPosition; pointsVertices[v].position = nextPosition; } mesh.updateVertices(vertices); pointsMesh.updateVertices(pointsVertices); } void render(Renderer2d* renderer) { mesh.render(renderer); pointsMesh.render(renderer, GL_POINTS); } void unload() { mesh.unload(); pointsMesh.unload(); delete [] vertices; delete [] pointsVertices; } };