diff --git a/examples/testbed/framework/test_entries.cpp b/examples/testbed/framework/test_entries.cpp index b2b6596..9224561 100644 --- a/examples/testbed/framework/test_entries.cpp +++ b/examples/testbed/framework/test_entries.cpp @@ -63,7 +63,7 @@ #include #include #include -#include +#include #include #include #include @@ -116,7 +116,7 @@ TestEntry g_tests[] = { "Pinned Cloth", &PinnedCloth::Create }, { "Particle Types", &ParticleTypes::Create }, { "Tension Mapping", &TensionMapping::Create }, - { "Cloth and Capsule", &ClothCapsule::Create }, + { "Cloth Self-Collision", &ClothSelfCollision::Create }, { "Beam", &Beam::Create }, { "Pinned Soft Body", &PinnedSoftBody::Create }, { "Smash Soft Body", &SmashSoftBody::Create }, diff --git a/examples/testbed/tests/cloth_capsule.h b/examples/testbed/tests/cloth_self_collision.h similarity index 75% rename from examples/testbed/tests/cloth_capsule.h rename to examples/testbed/tests/cloth_self_collision.h index 84a4d0e..dfc088e 100644 --- a/examples/testbed/tests/cloth_capsule.h +++ b/examples/testbed/tests/cloth_self_collision.h @@ -16,45 +16,33 @@ * 3. This notice may not be removed or altered from any source distribution. */ -#ifndef CLOTH_CAPSULE_H -#define CLOTH_CAPSULE_H +#ifndef CLOTH_SELF_COLLISION_H +#define CLOTH_SELF_COLLISION_H -class ClothCapsule : public Test +class ClothSelfCollision : public Test { public: - ClothCapsule() : m_rectangleGarment(5.0f, 5.0f) + ClothSelfCollision() { - // Generate 2D mesh - m_rectangleGarmentMesh.Set(&m_rectangleGarment, 1.0f); - - // Create 3D mesh - m_rectangleClothMesh.Set(&m_rectangleGarmentMesh); - - // Rotate and translate the mesh - b3Mat33 rotation = b3Mat33RotationX(0.5f * B3_PI); - for (u32 i = 0; i < m_rectangleClothMesh.vertexCount; ++i) + // Translate the mesh + for (u32 i = 0; i < m_clothMesh.vertexCount; ++i) { - m_rectangleClothMesh.vertices[i] = rotation * m_rectangleClothMesh.vertices[i]; - m_rectangleClothMesh.vertices[i].y += 5.0f; + m_clothMesh.vertices[i].y += 5.0f; } // Create cloth b3ClothDef def; - def.mesh = &m_rectangleClothMesh; + def.mesh = &m_clothMesh; def.density = 1.0f; def.structural = 100000.0f; - + def.thickness = 0.2f; + def.friction = 0.3f; + m_cloth = new b3Cloth(def); m_cloth->SetGravity(b3Vec3(0.0f, -9.8f, 0.0f)); m_cloth->SetWorld(&m_world); - for (b3Particle* p = m_cloth->GetParticleList().m_head; p; p = p->GetNext()) - { - p->SetRadius(0.2f); - p->SetFriction(0.2f); - } - { b3BodyDef bd; bd.type = e_staticBody; @@ -76,7 +64,7 @@ public: m_clothDragger = new b3ClothDragger(&m_ray, m_cloth); } - ~ClothCapsule() + ~ClothSelfCollision() { delete m_cloth; delete m_clothDragger; @@ -141,15 +129,12 @@ public: static Test* Create() { - return new ClothCapsule(); + return new ClothSelfCollision(); } - b3RectangleGarment m_rectangleGarment; - b3GarmentMesh m_rectangleGarmentMesh; - b3GarmentClothMesh m_rectangleClothMesh; - + b3GridClothMesh<10, 10> m_clothMesh; b3Cloth* m_cloth; b3ClothDragger* m_clothDragger; - }; +}; #endif \ No newline at end of file diff --git a/examples/testbed/tests/pinned_cloth.h b/examples/testbed/tests/pinned_cloth.h index 023e662..b6c8543 100644 --- a/examples/testbed/tests/pinned_cloth.h +++ b/examples/testbed/tests/pinned_cloth.h @@ -22,24 +22,11 @@ class PinnedCloth : public Test { public: - PinnedCloth() : m_rectangleGarment(5.0f, 5.0f) + PinnedCloth() { - // Generate 2D mesh - m_rectangleGarmentMesh.Set(&m_rectangleGarment, 1.0f); - - // Create 3D mesh - m_rectangleClothMesh.Set(&m_rectangleGarmentMesh); - - // Rotate the mesh - b3Mat33 rotation = b3Mat33RotationX(0.5f * B3_PI); - for (u32 i = 0; i < m_rectangleClothMesh.vertexCount; ++i) - { - m_rectangleClothMesh.vertices[i] = rotation * m_rectangleClothMesh.vertices[i]; - } - // Create cloth b3ClothDef def; - def.mesh = &m_rectangleClothMesh; + def.mesh = &m_clothMesh; def.density = 0.2f; def.structural = 100000.0f; def.damping = 0.0f; @@ -142,10 +129,7 @@ public: return new PinnedCloth(); } - b3RectangleGarment m_rectangleGarment; - b3GarmentMesh m_rectangleGarmentMesh; - b3GarmentClothMesh m_rectangleClothMesh; - + b3GridClothMesh<10, 10> m_clothMesh; b3Cloth* m_cloth; b3ClothDragger* m_clothDragger; }; diff --git a/examples/testbed/tests/table_cloth.h b/examples/testbed/tests/table_cloth.h index 3040ade..f3329bc 100644 --- a/examples/testbed/tests/table_cloth.h +++ b/examples/testbed/tests/table_cloth.h @@ -22,41 +22,28 @@ class TableCloth : public Test { public: - TableCloth() : m_rectangleGarment(5.0f, 5.0f) + TableCloth() { - // Generate 2D mesh - m_rectangleGarmentMesh.Set(&m_rectangleGarment, 1.0f); - - // Create 3D mesh - m_rectangleClothMesh.Set(&m_rectangleGarmentMesh); - - // Rotate the mesh - b3Mat33 rotation = b3Mat33RotationX(0.5f * B3_PI); - for (u32 i = 0; i < m_rectangleClothMesh.vertexCount; ++i) + // Translate the mesh + for (u32 i = 0; i < m_clothMesh.vertexCount; ++i) { - m_rectangleClothMesh.vertices[i] = rotation * m_rectangleClothMesh.vertices[i]; - m_rectangleClothMesh.vertices[i].y += 5.0f; + m_clothMesh.vertices[i].y += 5.0f; } - + // Create cloth b3ClothDef def; - def.mesh = &m_rectangleClothMesh; + def.mesh = &m_clothMesh; def.density = 0.2f; - //def.bending = 10000.0f; def.structural = 10000.0f; def.damping = 0.0f; + def.thickness = 0.2f; + def.friction = 0.1f; m_cloth = new b3Cloth(def); m_cloth->SetGravity(b3Vec3(0.0f, -9.8f, 0.0f)); m_cloth->SetWorld(&m_world); - for (b3Particle* p = m_cloth->GetParticleList().m_head; p; p = p->GetNext()) - { - p->SetRadius(0.1f); - p->SetFriction(0.2f); - } - { b3BodyDef bd; bd.type = e_staticBody; @@ -146,9 +133,7 @@ public: return new TableCloth(); } - b3RectangleGarment m_rectangleGarment; - b3GarmentMesh m_rectangleGarmentMesh; - b3GarmentClothMesh m_rectangleClothMesh; + b3GridClothMesh<10, 10> m_clothMesh; b3Cloth* m_cloth; b3ClothDragger* m_clothDragger; diff --git a/examples/testbed/tests/tension_mapping.h b/examples/testbed/tests/tension_mapping.h index 3b4f89b..1f074cb 100644 --- a/examples/testbed/tests/tension_mapping.h +++ b/examples/testbed/tests/tension_mapping.h @@ -58,24 +58,11 @@ static inline b3Color Color(float32 x, float32 a, float32 b) class TensionMapping : public Test { public: - TensionMapping() : m_rectangleGarment(5.0f, 5.0f) + TensionMapping() { - // Generate 2D mesh - m_rectangleGarmentMesh.Set(&m_rectangleGarment, 1.0f); - - // Create 3D mesh - m_rectangleClothMesh.Set(&m_rectangleGarmentMesh); - - // Rotate the mesh - b3Mat33 rotation = b3Mat33RotationX(0.5f * B3_PI); - for (u32 i = 0; i < m_rectangleClothMesh.vertexCount; ++i) - { - m_rectangleClothMesh.vertices[i] = rotation * m_rectangleClothMesh.vertices[i]; - } - // Create cloth b3ClothDef def; - def.mesh = &m_rectangleClothMesh; + def.mesh = &m_clothMesh; def.density = 0.2f; def.structural = 10000.0f; @@ -230,10 +217,7 @@ public: return new TensionMapping(); } - b3RectangleGarment m_rectangleGarment; - b3GarmentMesh m_rectangleGarmentMesh; - b3GarmentClothMesh m_rectangleClothMesh; - + b3GridClothMesh<10, 10> m_clothMesh; b3Cloth* m_cloth; b3ClothDragger* m_clothDragger; }; diff --git a/include/bounce/bounce.h b/include/bounce/bounce.h index e3f4335..d392a9d 100644 --- a/include/bounce/bounce.h +++ b/include/bounce/bounce.h @@ -64,6 +64,7 @@ #include #include +#include #include #include #include diff --git a/include/bounce/cloth/grid_cloth_mesh.h b/include/bounce/cloth/grid_cloth_mesh.h new file mode 100644 index 0000000..474daeb --- /dev/null +++ b/include/bounce/cloth/grid_cloth_mesh.h @@ -0,0 +1,96 @@ +/* +* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would be +* appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef B3_GRID_CLOTH_MESH_H +#define B3_GRID_CLOTH_MESH_H + +#include + +// A (H + 1) x (W + 1) grid mesh stored in row-major order. +// v(i, j) = i + (W + 1) + j +template +struct b3GridClothMesh : public b3ClothMesh +{ + b3Vec3 gridVertices[(H + 1) * (W + 1)]; + b3ClothMeshTriangle gridTriangles[2 * H * W]; + b3ClothMeshMesh gridMesh; + + // Set this grid to a W (width) per H (height) dimensioned grid centered at the origin and aligned + // with the world x-z axes. + b3GridClothMesh() + { + vertexCount = 0; + for (u32 i = 0; i <= H; ++i) + { + for (u32 j = 0; j <= W; ++j) + { + gridVertices[vertexCount++].Set(float32(j), 0.0f, float32(i)); + } + } + + B3_ASSERT(vertexCount == (W + 1) * (H + 1)); + + b3Vec3 translation; + translation.x = -0.5f * float32(W); + translation.y = 0.0f; + translation.z = -0.5f * float32(H); + + for (u32 i = 0; i < vertexCount; ++i) + { + gridVertices[i] += translation; + } + + triangleCount = 0; + for (u32 i = 0; i < H; ++i) + { + for (u32 j = 0; j < W; ++j) + { + u32 v1 = i * (W + 1) + j; + u32 v2 = (i + 1) * (W + 1) + j; + u32 v3 = (i + 1) * (W + 1) + (j + 1); + u32 v4 = i * (W + 1) + (j + 1); + + b3ClothMeshTriangle* t1 = gridTriangles + triangleCount++; + t1->v1 = v3; + t1->v2 = v2; + t1->v3 = v1; + + b3ClothMeshTriangle* t2 = gridTriangles + triangleCount++; + t2->v1 = v1; + t2->v2 = v4; + t2->v3 = v3; + } + } + + B3_ASSERT(triangleCount == 2 * H * W); + + gridMesh.startTriangle = 0; + gridMesh.triangleCount = triangleCount; + gridMesh.startVertex = 0; + gridMesh.vertexCount = vertexCount; + + vertices = gridVertices; + triangles = gridTriangles; + meshCount = 1; + meshes = &gridMesh; + sewingLineCount = 0; + sewingLines = nullptr; + } +}; + +#endif \ No newline at end of file diff --git a/include/bounce/collision/shapes/grid_mesh.h b/include/bounce/collision/shapes/grid_mesh.h index 358416d..f334569 100644 --- a/include/bounce/collision/shapes/grid_mesh.h +++ b/include/bounce/collision/shapes/grid_mesh.h @@ -22,6 +22,7 @@ #include // A (H + 1) x (W + 1) grid mesh stored in row-major order. +// v(i, j) = i * (W + 1) + j template struct b3GridMesh : public b3Mesh { @@ -32,61 +33,53 @@ struct b3GridMesh : public b3Mesh // with the world x-z axes. b3GridMesh() { - u32 h = H + 1; - u32 w = W + 1; - - b3Vec3 t; - t.x = -0.5f * float32(w) + 0.5f; - t.y = 0.0f; - t.z = -0.5f * float32(h) + 0.5f; - - for (u32 i = 0; i < h; ++i) + vertexCount = 0; + for (u32 i = 0; i <= H; ++i) { - for (u32 j = 0; j < w; ++j) + for (u32 j = 0; j <= W; ++j) { - u32 v1 = i * w + j; - - b3Vec3 v; - v.x = float32(j); - v.y = 0.0f; - v.z = float32(i); - - v += t; - - gridVertices[v1] = v; + gridVertices[vertexCount++].Set(float32(j), 0.0f, float32(i)); } } - u32 triangleIndex = 0; - for (u32 i = 0; i < h - 1; ++i) + B3_ASSERT(vertexCount == (H + 1) * (W + 1)); + + b3Vec3 translation; + translation.x = -0.5f * float32(W); + translation.y = 0.0f; + translation.z = -0.5f * float32(H); + + for (u32 i = 0; i < vertexCount; ++i) { - for (u32 j = 0; j < w - 1; ++j) + gridVertices[i] += translation; + } + + triangleCount = 0; + for (u32 i = 0; i < H; ++i) + { + for (u32 j = 0; j < W; ++j) { - u32 v1 = i * w + j; - u32 v2 = (i + 1) * w + j; - u32 v3 = (i + 1) * w + (j + 1); - u32 v4 = i * w + (j + 1); - - b3Triangle* t1 = gridTriangles + triangleIndex; - ++triangleIndex; + u32 v1 = i * (W + 1) + j; + u32 v2 = (i + 1) * (W + 1) + j; + u32 v3 = (i + 1) * (W + 1) + (j + 1); + u32 v4 = i * (W + 1) + (j + 1); + b3Triangle* t1 = gridTriangles + triangleCount++; t1->v1 = v3; t1->v2 = v2; t1->v3 = v1; - b3Triangle* t2 = gridTriangles + triangleIndex; - ++triangleIndex; - + b3Triangle* t2 = gridTriangles + triangleCount++; t2->v1 = v1; t2->v2 = v4; t2->v3 = v3; } } + B3_ASSERT(triangleCount == 2 * H * W); + vertices = gridVertices; - vertexCount = (H + 1) * (W + 1); triangles = gridTriangles; - triangleCount = 2 * H * W; } }; diff --git a/include/bounce/softbody/block_softbody_mesh.h b/include/bounce/softbody/block_softbody_mesh.h index 618caaf..19dba1e 100644 --- a/include/bounce/softbody/block_softbody_mesh.h +++ b/include/bounce/softbody/block_softbody_mesh.h @@ -36,7 +36,7 @@ struct b3BlockSoftBodyMesh : public b3SoftBodyMesh { for (u32 z = 0; z <= D; ++z) { - blockVertices[vertexCount++].Set(x, y, z); + blockVertices[vertexCount++].Set(float32(x), float32(y), float32(z)); } } } diff --git a/include/bounce/softbody/softbody.h b/include/bounce/softbody/softbody.h index 08ae969..18508f1 100644 --- a/include/bounce/softbody/softbody.h +++ b/include/bounce/softbody/softbody.h @@ -141,7 +141,7 @@ public: // Debug draw the body using the associated mesh. void Draw() const; private: - friend class b3SoftBodyNode; + friend struct b3SoftBodyNode; friend class b3SoftBodySolver; friend class b3SoftBodyForceSolver; diff --git a/src/bounce/cloth/cloth.cpp b/src/bounce/cloth/cloth.cpp index 936df66..8cac18f 100644 --- a/src/bounce/cloth/cloth.cpp +++ b/src/bounce/cloth/cloth.cpp @@ -170,8 +170,9 @@ b3Cloth::b3Cloth(const b3ClothDef& def) : b3ParticleDef pd; pd.type = e_dynamicParticle; pd.mass = 1.0f; - pd.position = m->vertices[i]; pd.radius = def.thickness; + pd.friction = def.friction; + pd.position = m->vertices[i]; b3Particle* p = CreateParticle(pd);