diff --git a/examples/testbed/framework/test.cpp b/examples/testbed/framework/test.cpp index a8304fe..befad6c 100644 --- a/examples/testbed/framework/test.cpp +++ b/examples/testbed/framework/test.cpp @@ -115,6 +115,11 @@ void Test::Step() g_draw->DrawString(b3Color_white, "Convex Cache Hits %d (%f)", b3_convexCacheHits, convexCacheHitRatio); g_draw->DrawString(b3Color_white, "Frame Allocations %d (%d)", b3_allocCalls, b3_maxAllocCalls); } + + if (m_clothDragger.IsDragging() == true) + { + g_draw->DrawSegment(m_clothDragger.GetPointA(), m_clothDragger.GetPointB(), b3Color_white); + } } void Test::MouseMove(const b3Ray3& pw) diff --git a/examples/testbed/tests/cloth_test.h b/examples/testbed/tests/cloth_test.h index dbc1913..946e755 100644 --- a/examples/testbed/tests/cloth_test.h +++ b/examples/testbed/tests/cloth_test.h @@ -41,11 +41,6 @@ public: float32 E = m_cloth->GetEnergy(); g_draw->DrawString(b3Color_white, "E = %f", E); - - if (m_clothDragger.IsDragging() == true) - { - g_draw->DrawSegment(m_clothDragger.GetPointA(), m_clothDragger.GetPointB(), b3Color_white); - } } b3Cloth* m_cloth; diff --git a/include/bounce/dynamics/cloth/cloth.h b/include/bounce/dynamics/cloth/cloth.h index 42b09d2..daeec9d 100644 --- a/include/bounce/dynamics/cloth/cloth.h +++ b/include/bounce/dynamics/cloth/cloth.h @@ -37,7 +37,14 @@ struct b3ClothMesh; class b3RayCastListener; struct b3RayCastInput; -struct b3RayCastSingleClothOutput; +struct b3RayCastOutput; + +struct b3ClothRayCastSingleOutput +{ + u32 triangle; + float32 fraction; + b3Vec3 normal; +}; // Cloth definition // This requires defining a cloth mesh which is typically bound to a render mesh @@ -89,14 +96,14 @@ public: // Destroy a given force. void DestroyForce(b3Force* force); + // Perform a ray cast with the cloth. + void RayCast(b3RayCastListener* listener, const b3Vec3& p1, const b3Vec3& p2); + + // Perform a ray cast with the cloth. + bool RayCastSingle(b3ClothRayCastSingleOutput* output, const b3Vec3& p1, const b3Vec3& p2) const; + // Perform a ray cast with a given cloth mesh triangle. - bool RayCast(b3RayCastSingleClothOutput* output, const b3RayCastInput* input, u32 triangleIndex) const; - - // Perform a ray cast with the cloth. - void RayCast(b3RayCastListener* listener, const b3RayCastInput* input) const; - - // Perform a ray cast with the cloth. - bool RayCastSingle(b3RayCastSingleClothOutput* output, const b3Vec3& p1, const b3Vec3& p2) const; + bool RayCast(b3RayCastOutput* output, const b3RayCastInput* input, u32 triangleIndex) const; // Return the cloth mesh proxy. b3ClothMesh* GetMesh() const; diff --git a/src/bounce/dynamics/cloth/cloth.cpp b/src/bounce/dynamics/cloth/cloth.cpp index 354466e..f13f231 100644 --- a/src/bounce/dynamics/cloth/cloth.cpp +++ b/src/bounce/dynamics/cloth/cloth.cpp @@ -348,14 +348,23 @@ void b3Cloth::ComputeMass() } } -void b3Cloth::RayCast(b3RayCastListener* listener, const b3RayCastInput* input) const +void b3Cloth::RayCast(b3RayCastListener* listener, const b3Vec3& p1, const b3Vec3& p2) { + b3RayCastInput input; + input.p1 = p1; + input.p2 = p2; + input.maxFraction = 1.0f; + for (u32 i = 0; i < m_mesh->triangleCount; ++i) { - b3RayCastSingleClothOutput subOutput; - if (RayCast(&subOutput, input, i)) + b3RayCastOutput subOutput; + if (RayCast(&subOutput, &input, i)) { - float32 newFraction = listener->ReportCloth(subOutput.cloth, subOutput.point, subOutput.normal, subOutput.fraction, subOutput.triangle); + float32 fraction = subOutput.fraction; + b3Vec3 point = (1.0f - fraction) * input.p1 + fraction * input.p2; + b3Vec3 normal = subOutput.normal; + + float32 newFraction = listener->ReportCloth(this, point, normal, fraction, i); if (newFraction == 0.0f) { @@ -366,37 +375,44 @@ void b3Cloth::RayCast(b3RayCastListener* listener, const b3RayCastInput* input) } } -bool b3Cloth::RayCastSingle(b3RayCastSingleClothOutput* output, const b3Vec3& p1, const b3Vec3& p2) const +bool b3Cloth::RayCastSingle(b3ClothRayCastSingleOutput* output, const b3Vec3& p1, const b3Vec3& p2) const { b3RayCastInput input; input.p1 = p1; input.p2 = p2; input.maxFraction = 1.0f; - output->triangle = ~0; - output->fraction = B3_MAX_FLOAT; + u32 triangle0 = ~0; + b3RayCastOutput output0; + output0.fraction = B3_MAX_FLOAT; for (u32 i = 0; i < m_mesh->triangleCount; ++i) { - b3RayCastSingleClothOutput subOutput; + b3RayCastOutput subOutput; if (RayCast(&subOutput, &input, i)) { - if (subOutput.fraction < output->fraction) + if (subOutput.fraction < output0.fraction) { - *output = subOutput; + triangle0 = i; + output0.fraction = subOutput.fraction; + output0.normal = subOutput.normal; } } } - if (output->triangle != ~0) + if (triangle0 != ~0) { + output->triangle = triangle0; + output->fraction = output0.fraction; + output->normal = output0.normal; + return true; } return false; } -bool b3Cloth::RayCast(b3RayCastSingleClothOutput* output, const b3RayCastInput* input, u32 triangleIndex) const +bool b3Cloth::RayCast(b3RayCastOutput* output, const b3RayCastInput* input, u32 triangleIndex) const { B3_ASSERT(triangleIndex < m_mesh->triangleCount); b3ClothMeshTriangle* triangle = m_mesh->triangles + triangleIndex; @@ -468,9 +484,7 @@ bool b3Cloth::RayCast(b3RayCastSingleClothOutput* output, const b3RayCastInput* // Is the intersection on the triangle? if (u > kTol && v > kTol && w > kTol) { - output->triangle = triangleIndex; output->fraction = fraction; - output->point = Q; // Does the ray start from below or above the triangle? if (numerator > 0.0f) diff --git a/src/bounce/dynamics/world.cpp b/src/bounce/dynamics/world.cpp index dfb9660..8981fdb 100644 --- a/src/bounce/dynamics/world.cpp +++ b/src/bounce/dynamics/world.cpp @@ -493,38 +493,44 @@ bool b3World::RayCastSingleShape(b3RayCastSingleShapeOutput* output, const b3Vec void b3World::RayCastCloth(b3RayCastListener* listener, const b3Vec3& p1, const b3Vec3& p2) const { - b3RayCastInput input; - input.p1 = p1; - input.p2 = p2; - input.maxFraction = B3_MAX_FLOAT; - for (b3Cloth* c = m_clothList.m_head; c; c = c->m_next) { - c->RayCast(listener, &input); + c->RayCast(listener, p1, p2); } } bool b3World::RayCastSingleCloth(b3RayCastSingleClothOutput* output, const b3Vec3& p1, const b3Vec3& p2) const { - output->cloth = NULL; - output->triangle = ~0; - output->fraction = B3_MAX_FLOAT; - + b3Cloth* cloth0 = NULL; + b3ClothRayCastSingleOutput output0; + output0.fraction = B3_MAX_FLOAT; + for (b3Cloth* c = m_clothList.m_head; c; c = c->m_next) { - b3RayCastSingleClothOutput subOutput; + b3ClothRayCastSingleOutput subOutput; if (c->RayCastSingle(&subOutput, p1, p2)) { - if (subOutput.fraction < output->fraction) + if (subOutput.fraction < output0.fraction) { - subOutput.cloth = c; - *output = subOutput; + cloth0 = c; + output0 = subOutput; } } } - if (output->cloth != NULL) + if (cloth0 != NULL) { + u32 triangle = output0.triangle; + float32 fraction = output0.fraction; + b3Vec3 point = (1.0f - fraction) * p1 + fraction * p2; + b3Vec3 normal = output0.normal; + + output->triangle = triangle; + output->cloth = cloth0; + output->point = point; + output->normal = normal; + output->fraction = fraction; + return true; }