aboutsummaryrefslogtreecommitdiff
path: root/NvCloth/samples/SampleBase
diff options
context:
space:
mode:
authorMarijn Tamis <[email protected]>2017-04-28 14:19:07 +0200
committerMarijn Tamis <[email protected]>2017-04-28 14:19:07 +0200
commitb350eb5f4d44e8448115796144375d79438d74ae (patch)
tree8e102e8c28f45a1b87bd335ceee4f33c3d4ee7c2 /NvCloth/samples/SampleBase
parentAdd visual samples. (diff)
downloadnvcloth-b350eb5f4d44e8448115796144375d79438d74ae.tar.xz
nvcloth-b350eb5f4d44e8448115796144375d79438d74ae.zip
NvCloth 1.1.0 Release. (22041545)
Diffstat (limited to 'NvCloth/samples/SampleBase')
-rw-r--r--NvCloth/samples/SampleBase/renderer/ClothRenderMesh.cpp25
-rw-r--r--NvCloth/samples/SampleBase/scene/Scene.cpp715
-rw-r--r--NvCloth/samples/SampleBase/scene/Scene.h57
-rw-r--r--NvCloth/samples/SampleBase/scene/SceneController.cpp43
-rw-r--r--NvCloth/samples/SampleBase/scene/SceneController.h15
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/CCDScene.cpp153
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/CCDScene.h37
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/CapsuleScene.cpp129
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/CapsuleScene.h33
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/ConvexCollisionScene.cpp138
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/ConvexCollisionScene.h33
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/DistanceConstraintScene.cpp100
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/DistanceConstraintScene.h32
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/FreeFallScene.cpp12
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/FrictionScene.cpp22
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/FrictionScene.h4
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/GeodesicScene.cpp114
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/GeodesicScene.h36
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/InterCollisionScene.cpp128
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/InterCollisionScene.h33
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/LocalGlobalScene.cpp141
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/LocalGlobalScene.h40
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/MultiSolverScene.cpp131
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/MultiSolverScene.h33
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/PlaneCollisionScene.cpp135
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/PlaneCollisionScene.h33
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/SelfCollisionScene.cpp155
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/SelfCollisionScene.h33
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/SimpleScene.cpp16
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/SphereScene.cpp121
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/SphereScene.h33
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/StiffnessPerConstraintScene.cpp122
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/StiffnessPerConstraintScene.h33
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/TetherScene.cpp26
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/TriangleScene.cpp131
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/TriangleScene.h33
-rw-r--r--NvCloth/samples/SampleBase/scene/scenes/WindScene.cpp49
-rw-r--r--NvCloth/samples/SampleBase/ui/CommonUIController.cpp9
-rw-r--r--NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp56
-rw-r--r--NvCloth/samples/SampleBase/utils/ClothMeshGenerator.h8
-rw-r--r--NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.cpp21
-rw-r--r--NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.h25
-rw-r--r--NvCloth/samples/SampleBase/utils/MeshGenerator.cpp545
-rw-r--r--NvCloth/samples/SampleBase/utils/MeshGenerator.h114
-rw-r--r--NvCloth/samples/SampleBase/utils/Utils.h26
45 files changed, 3827 insertions, 101 deletions
diff --git a/NvCloth/samples/SampleBase/renderer/ClothRenderMesh.cpp b/NvCloth/samples/SampleBase/renderer/ClothRenderMesh.cpp
index 60bb5f3..1183bdb 100644
--- a/NvCloth/samples/SampleBase/renderer/ClothRenderMesh.cpp
+++ b/NvCloth/samples/SampleBase/renderer/ClothRenderMesh.cpp
@@ -158,27 +158,30 @@ ClothRenderMesh::~ClothRenderMesh()
void ClothRenderMesh::update(const PxVec3* positions, uint32_t numVertices)
{
PxStrideIterator<const PxVec3> pIt(positions, sizeof(PxVec3));
+ Vertex* vertices = mVertices.data();
+ const uint16_t* indices = mIndices.data();
for (PxU32 i = 0; i < numVertices; ++i)
{
- mVertices[i].position = *pIt++;
- mVertices[i].normal = PxVec3(0.f);
+ vertices[i].position = *pIt++;
+ vertices[i].normal = PxVec3(0.f);
}
- for (PxU32 i = 0; i < mIndices.size(); i += 3)
+ const PxU32 numIndices = (PxU32)mIndices.size();
+ for (PxU32 i = 0; i < numIndices; i += 3)
{
- auto p0 = mVertices[mIndices[i]].position;
- auto p1 = mVertices[mIndices[i + 1]].position;
- auto p2 = mVertices[mIndices[i + 2]].position;
+ const auto p0 = vertices[indices[i]].position;
+ const auto p1 = vertices[indices[i + 1]].position;
+ const auto p2 = vertices[indices[i + 2]].position;
- auto normal = ((p2 - p0).cross(p1 - p0)).getNormalized();
+ const auto normal = ((p2 - p0).cross(p1 - p0)).getNormalized();
- mVertices[mIndices[i]].normal += normal;
- mVertices[mIndices[i + 1]].normal += normal;
- mVertices[mIndices[i + 2]].normal += normal;
+ vertices[indices[i]].normal += normal;
+ vertices[indices[i + 1]].normal += normal;
+ vertices[indices[i + 2]].normal += normal;
}
for (PxU32 i = 0; i < numVertices; ++i)
- mVertices[i].normal.normalize();
+ vertices[i].normal.normalize();
ID3D11DeviceContext* context;
mDevice->GetImmediateContext(&context);
diff --git a/NvCloth/samples/SampleBase/scene/Scene.cpp b/NvCloth/samples/SampleBase/scene/Scene.cpp
index 130dad3..6296a05 100644
--- a/NvCloth/samples/SampleBase/scene/Scene.cpp
+++ b/NvCloth/samples/SampleBase/scene/Scene.cpp
@@ -13,14 +13,391 @@
#include <NvCloth/Solver.h>
#include <NvCloth/Fabric.h>
#include "Renderer.h"
+#include "imgui.h"
+#include <sstream>
+#include "utils/DebugLineRenderBuffer.h"
+#include <foundation/PxVec2.h>
std::vector<SceneFactory> Scene::sSceneFactories;
+unsigned int Scene::mDebugVisualizationFlags;
+Scene::SceneDebugRenderParams Scene::sSceneDebugRenderParams;
Scene::~Scene()
{
}
+void Scene::UpdateParticleDragging(float dt)
+{
+ physx::PxVec2 screenResolution(
+ mSceneController->getRenderer().getScreenWidth(),
+ mSceneController->getRenderer().getScreenHeight());
+
+ physx::PxMat33 invScreenTransform;
+ {
+ float m[]{2.0f / screenResolution.x, 0.0f, 0.0f, 0.0f, -2.0f / screenResolution.y, 0.0f, -1.0f, 1.0f, 1.0f};
+ invScreenTransform = physx::PxMat33(m);
+ }
+
+ physx::PxVec2 mousePoint;
+ {
+ POINT wpt;
+ GetCursorPos(&wpt);
+ ScreenToClient(GetDeviceManager()->GetHWND(), &wpt);
+ int x, y;
+ x = wpt.x;
+ y = wpt.y;
+ physx::PxVec3 pt(invScreenTransform*physx::PxVec3((float)x, (float)y, 1.0f));
+ mousePoint.x = pt.x;
+ mousePoint.y = pt.y;
+ }
+
+ physx::PxMat44 viewProjectionMatrix;
+ physx::PxVec3 viewDirection;
+ physx::PxVec3 viewPoint;
+ {
+ auto camera = mSceneController->getRenderer().getCamera();
+ auto m1 = camera.GetViewMatrix();
+ auto m2 = camera.GetProjMatrix();
+ viewProjectionMatrix = physx::PxMat44((float*)&m2.r)*physx::PxMat44((float*)&m1.r);
+ auto v1 = camera.GetWorldAhead();
+ viewDirection = physx::PxVec3(*(physx::PxVec3*)&v1);
+ auto v2 = camera.GetEyePt();
+ viewPoint = physx::PxVec3(*(physx::PxVec3*)&v2);
+ }
+
+ if(mDraggingParticle.mTrackedCloth)
+ {
+ nv::cloth::Cloth* cloth = mDraggingParticle.mTrackedCloth->mCloth;
+ physx::PxMat44 modelMatrix = GetDebugDrawTransform(*mDraggingParticle.mTrackedCloth);
+ nv::cloth::Range<physx::PxVec4> particles = cloth->getCurrentParticles();
+ nv::cloth::Range<physx::PxVec4> prevParticles = cloth->getPreviousParticles();
+
+ physx::PxMat44 tmp = viewProjectionMatrix;
+ auto tmp2 = DirectX::XMMatrixInverse(nullptr, DirectX::XMMATRIX(tmp.front()));
+ tmp = physx::PxMat44((float*)&tmp2.r);
+ physx::PxMat44 invMatrix = tmp;
+
+ physx::PxVec3 particleWorld = modelMatrix.transform(particles[mDraggingParticle.mParticleIndex].getXYZ());
+ physx::PxVec4 mousePointWorldT = invMatrix.transform(physx::PxVec4(mousePoint.x, mousePoint.y, 1.0, 1.0));
+ physx::PxVec3 mousePointWorld = mousePointWorldT.getXYZ() / mousePointWorldT.w;
+ physx::PxVec3 mouseRayStart = viewPoint;
+ physx::PxVec3 mouseRayDir = (mousePointWorld - mouseRayStart).getNormalized();
+ //float rayT = -viewDirection.dot(mouseRayStart - particleWorld) / viewDirection.dot(mouseRayDir); //intersect plane
+ float rayT = mDraggingParticle.mDist;
+ physx::PxVec3 mousePointPlane = mouseRayStart + mouseRayDir*rayT;
+
+ physx::PxVec3 offset = mousePointPlane - particleWorld;
+ if(offset.magnitudeSquared() > 2.5f*2.5f)
+ offset = offset.getNormalized()*2.5f;
+
+ for(int i = 0; i < (int)particles.size(); i++)
+ {
+ physx::PxVec4 p = particles[i];
+ float dist = (p.getXYZ() - particleWorld).magnitude();
+
+ if(p.w > 0.0f) //Only move dynamic points
+ {
+ float weight = max(0.0,min(1.0,0.4-dist));
+ physx::PxVec3 point0(prevParticles[i].x, prevParticles[i].y, prevParticles[i].z);
+ point0 = point0 - weight*offset;
+ point0 = point0*0.99f + p.getXYZ()*0.01f;
+ //move previous particle in the opposite direction to avoid invalid configurations in the next solver iteration.
+ prevParticles[i] = physx::PxVec4(point0.x, point0.y, point0.z, prevParticles[i].w);
+ }
+ }
+ }
+}
+
+
+bool Scene::HandleEvent(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ auto camera = mSceneController->getRenderer().getCamera();
+ auto m1 = camera.GetViewMatrix();
+ auto m2 = camera.GetProjMatrix();
+
+ return HandlePickingEvent(uMsg, wParam, lParam, physx::PxMat44((float*)&m2.r)*physx::PxMat44((float*)&m1.r));
+}
+
+bool Scene::HandlePickingEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, physx::PxMat44 viewProjectionMatrix2)
+{
+ if(uMsg != WM_LBUTTONDOWN && uMsg != WM_LBUTTONUP)
+ return false;
+
+ physx::PxVec2 screenResolution(
+ mSceneController->getRenderer().getScreenWidth(),
+ mSceneController->getRenderer().getScreenHeight());
+
+ physx::PxMat33 invScreenTransform;
+ {
+ float m[]{2.0f / screenResolution.x, 0.0f, 0.0f, 0.0f, -2.0f / screenResolution.y, 0.0f, -1.0f, 1.0f, 1.0f};
+ invScreenTransform = physx::PxMat33(m);
+ }
+
+ physx::PxVec2 mousePoint;
+ {
+ int x, y;
+ x = LOWORD(lParam);
+ y = HIWORD(lParam);
+ physx::PxVec3 pt(invScreenTransform*physx::PxVec3((float)x, (float)y, 1.0f));
+ mousePoint.x = pt.x;
+ mousePoint.y = pt.y;
+ }
+
+ physx::PxMat44 viewProjectionMatrix;
+ physx::PxVec3 viewDirection;
+ physx::PxVec3 viewPoint;
+ {
+ auto camera = mSceneController->getRenderer().getCamera();
+ auto m1 = camera.GetViewMatrix();
+ auto m2 = camera.GetProjMatrix();
+ viewProjectionMatrix = physx::PxMat44((float*)&m2.r)*physx::PxMat44((float*)&m1.r);
+ auto v1 = camera.GetWorldAhead();
+ viewDirection = physx::PxVec3(*(physx::PxVec3*)&v1);
+ auto v2 = camera.GetEyePt();
+ viewPoint = physx::PxVec3(*(physx::PxVec3*)&v2);
+ }
+
+ if(uMsg == WM_LBUTTONDOWN)
+ {
+ mDraggingParticle.mDist = 9999999.0f;
+ mDraggingParticle.mOffset = 9999999.0f;
+ mDraggingParticle.mTrackedCloth = nullptr;
+ for(auto it : mClothList)
+ {
+ nv::cloth::Cloth* cloth = it->mCloth;
+ physx::PxMat44 modelMatrix = GetDebugDrawTransform(*it);
+ nv::cloth::Range<physx::PxVec4> particles = cloth->getCurrentParticles();
+
+ physx::PxMat44 tmp = viewProjectionMatrix;
+ auto tmp2 = DirectX::XMMatrixInverse(nullptr, DirectX::XMMATRIX(tmp.front()));
+ tmp = physx::PxMat44((float*)&tmp2.r);
+ physx::PxMat44 invMatrix = tmp;
+
+ physx::PxVec4 mousePointWorldT = invMatrix.transform(physx::PxVec4(mousePoint.x, mousePoint.y, 1.0, 1.0));
+ physx::PxVec3 mousePointWorld = mousePointWorldT.getXYZ() / mousePointWorldT.w;
+ physx::PxVec3 mouseRayStart = viewPoint;
+ physx::PxVec3 mouseRayDir = (mousePointWorld - mouseRayStart).getNormalized();
+
+ for(int i = 0; i<(int)particles.size(); i++)
+ {
+ physx::PxVec4 p = particles[i];
+ physx::PxVec4 point(p.x, p.y, p.z, 1.0f);
+
+ float dist = mouseRayDir.dot(point.getXYZ() - mouseRayStart);
+ float offset = (point.getXYZ() - (dist*mouseRayDir + mouseRayStart)).magnitude();
+
+ if(offset<0.1f)
+ {
+ if(mDraggingParticle.mDist + 0.5f*mDraggingParticle.mOffset>dist + 0.5f*offset)
+ {
+ mDraggingParticle.mTrackedCloth = it;
+ //mDraggingParticle.mOffset = offset;
+ mDraggingParticle.mDist = dist;
+ mDraggingParticle.mParticleIndex = i;
+ }
+ }
+ }
+ }
+ return true;
+ }
+ if(uMsg == WM_LBUTTONUP)
+ {
+ mDraggingParticle.mTrackedCloth = nullptr;
+ return true;
+ }
+ return false;
+}
+
+void Scene::drawUI()
+{
+ static int activeCloth = 0;
+
+ if(ImGui::TreeNode("Cloth Properties"))
+ {
+ activeCloth = min(activeCloth, (int)mClothList.size() - 1);
+ for(int i = 0; i < (int)mClothList.size(); i++)
+ {
+ if(i)
+ ImGui::SameLine();
+ nv::cloth::Cloth* cloth = mClothList[i]->mCloth;
+ std::stringstream clothName;
+ clothName << "Cloth " << i;
+ ImGui::RadioButton(clothName.str().c_str(), &activeCloth, i);
+ }
+
+ nv::cloth::Cloth* cloth = mClothList[activeCloth]->mCloth;
+
+
+ {
+ bool b = cloth->isContinuousCollisionEnabled();
+ if(ImGui::Checkbox("Continuous Collision Detection (CCD)", &b))
+ cloth->enableContinuousCollision(b);
+ }
+ {
+ physx::PxVec3 f3 = cloth->getDamping();
+ if(ImGui::DragFloat3("Damping", &f3.x, 0.02f, 0.0f, 1.0f, "%.2f"))
+ cloth->setDamping(f3);
+ float f = f3.maxElement();
+ if(ImGui::DragFloat("Damping xyz", &f, 0.02f, 0.0f, 1.0f, "%.2f"))
+ cloth->setDamping(physx::PxVec3(f,f,f));
+ }
+ {
+ float f = cloth->getDragCoefficient();
+ if(ImGui::DragFloat("Drag Coefficient", &f, 0.02f, 0.0f, 0.99f, "%.2f"))
+ cloth->setDragCoefficient(f);
+ }
+ {
+ float f = cloth->getFriction();
+ if(ImGui::DragFloat("Friction", &f, 0.04f, 0.0f, 2.0f, "%.2f"))
+ cloth->setFriction(f);
+ }
+ {
+ physx::PxVec3 f3 = cloth->getGravity();
+ if(ImGui::DragFloat3("Gravity", &f3.x, 0.5f, -50.0f, 50.0f, "%.1f"))
+ cloth->setGravity(f3);
+ }
+ {
+ float f = cloth->getLiftCoefficient();
+ if(ImGui::DragFloat("Lift Coefficient", &f, 0.02f, 0.0f, 1.0f, "%.2f"))
+ cloth->setLiftCoefficient(f);
+ }
+ {
+ physx::PxVec3 f3 = cloth->getLinearInertia();
+ if(ImGui::DragFloat3("Linear Inertia", &f3.x, 0.02f, 0.0f, 1.0f, "%.2f"))
+ cloth->setLinearInertia(f3);
+ float f = f3.maxElement();
+ if(ImGui::DragFloat("Linear Inertia xyz", &f, 0.02f, 0.0f, 1.0f, "%.2f"))
+ cloth->setLinearInertia(physx::PxVec3(f, f, f));
+ }
+ {
+ float f = cloth->getMotionConstraintScale();
+ if(ImGui::DragFloat("Motion Constraint Scale", &f, 0.08f, 0.0f, 4.0f, "%.2f"))
+ cloth->setMotionConstraintScaleBias(f, cloth->getMotionConstraintBias());
+ }
+ {
+ float f = cloth->getMotionConstraintBias();
+ if(ImGui::DragFloat("Motion Constraint Bias", &f, 0.16f, 0.0f, 8.0f, "%.2f"))
+ cloth->setMotionConstraintScaleBias(cloth->getMotionConstraintScale(),f);
+ }
+ {
+ float f = cloth->getSelfCollisionDistance();
+ if(ImGui::DragFloat("Self Collision Distance", &f, 0.005f, 0.0f, 0.3f, "%.3f"))
+ cloth->setSelfCollisionDistance(f);
+ }
+ {
+ float f = cloth->getSelfCollisionStiffness();
+ if(ImGui::DragFloat("Self Collision Stiffness", &f, 0.02f, 0.0f, 1.0f, "%.2f"))
+ cloth->setSelfCollisionStiffness(f);
+ }
+ {
+ float f = cloth->getSleepThreshold();
+ if(ImGui::DragFloat("Sleep Threshold", &f, 0.02f, 0.0f, 1.0f, "%.2f"))
+ cloth->setSleepThreshold(f);
+ }
+ {
+ float f = cloth->getStiffnessFrequency();
+ if(ImGui::DragFloat("Stiffness Frequency", &f, 1.0f, 0.0f, 600.0f, "%.0f",1.5f))
+ cloth->setStiffnessFrequency(f);
+ }
+ {
+ float f = cloth->getSolverFrequency();
+ if(ImGui::DragFloat("Solver Frequency", &f, 1.0f, 0.0f, 600.0f, "%.0f", 1.5f))
+ cloth->setSolverFrequency(f);
+ }
+ {
+ float f = cloth->getTetherConstraintScale();
+ if(ImGui::DragFloat("Tether Constraint Scale", &f, 0.08f, 0.0f, 4.0f, "%.2f"))
+ cloth->setTetherConstraintScale(f);
+ }
+ {
+ float f = cloth->getTetherConstraintStiffness();
+ if(ImGui::DragFloat("Tether Constraint Stiffness", &f, 0.02f, 0.0f, 1.0f, "%.2f"))
+ cloth->setTetherConstraintStiffness(f);
+ }
+ {
+ physx::PxVec3 f3 = cloth->getWindVelocity();
+ if(ImGui::DragFloat3("Wind Velocity", &f3.x, 0.5f, -50.0f, 50.0f, "%.1f"))
+ cloth->setWindVelocity(f3);
+ }
+ ImGui::TreePop();
+ }
+
+ if(ImGui::TreeNode("Debug Visualization"))
+ {
+ ImGui::CheckboxFlags("Tethers", &mDebugVisualizationFlags, DEBUG_VIS_TETHERS);
+ ImGui::CheckboxFlags("Constraints", &mDebugVisualizationFlags, DEBUG_VIS_CONSTRAINTS);
+ if(mDebugVisualizationFlags&DEBUG_VIS_CONSTRAINTS)
+ {
+ ImGui::DragInt("Start Constraint Phase Range", &sSceneDebugRenderParams.mVisiblePhaseRangeBegin, 0.05, 0, 30);
+ ImGui::DragInt("End", &sSceneDebugRenderParams.mVisiblePhaseRangeEnd, 0.05, 0, 30);
+ }
+ ImGui::CheckboxFlags("Constraint Stiffness", &mDebugVisualizationFlags, DEBUG_VIS_CONSTRAINTS_STIFFNESS);
+
+ ImGui::CheckboxFlags("Constraint Error", &mDebugVisualizationFlags, DEBUG_VIS_CONSTRAINT_ERROR);
+ ImGui::CheckboxFlags("Position Delta", &mDebugVisualizationFlags, DEBUG_VIS_POSITION_DELTA);
+ ImGui::CheckboxFlags("Bounding Box", &mDebugVisualizationFlags, DEBUG_VIS_BOUNDING_BOX);
+ ImGui::CheckboxFlags("Distance Constraints", &mDebugVisualizationFlags, DEBUG_VIS_DISTANCE_CONSTRAINTS);
+
+ ImGui::TreePop();
+ }
+
+ static int activeSolver = 0;
+
+ if(ImGui::TreeNode("Solver Properties"))
+ {
+ activeSolver = min(activeSolver, (int)mSolverList.size() - 1);
+ for(int i = 0; i < (int)mSolverList.size(); i++)
+ {
+ if(i)
+ ImGui::SameLine();
+ nv::cloth::Solver* solver = mSolverList[i];
+ std::stringstream clothName;
+ clothName << "Solver " << i;
+ ImGui::RadioButton(clothName.str().c_str(), &activeSolver, i);
+ }
+
+ nv::cloth::Solver* solver = mSolverList[activeSolver];
+
+ {
+ float f = solver->getInterCollisionDistance();
+ if(ImGui::DragFloat("Inter Collision Distance", &f, 0.005f, 0.0f, 2.0f, "%.2f"))
+ solver->setInterCollisionDistance(f);
+ }
+ {
+ uint32_t i = solver->getInterCollisionNbIterations();
+ if(ImGui::DragInt("Inter Collision Iterations", (int*)&i, 0.25, 0, 16))
+ solver->setInterCollisionNbIterations(i);
+ }
+ {
+ float f = solver->getInterCollisionStiffness();
+ if(ImGui::DragFloat("Inter Collision Stiffness", &f, 0.005f, 0.0f, 1.0f, "%.2f"))
+ solver->setInterCollisionStiffness(f);
+ }
+ ImGui::TreePop();
+ }
+}
+
+void Scene::drawDebugVisualization()
+{
+ if(mDebugVisualizationFlags & DEBUG_VIS_TETHERS)
+ DebugRenderTethers();
+ if(mDebugVisualizationFlags & DEBUG_VIS_CONSTRAINTS)
+ DebugRenderConstraints();
+ if(mDebugVisualizationFlags & DEBUG_VIS_CONSTRAINTS_STIFFNESS)
+ DebugRenderConstraintStiffness();
+
+ if(mDebugVisualizationFlags & DEBUG_VIS_CONSTRAINT_ERROR)
+ DebugRenderConstraintError();
+ if(mDebugVisualizationFlags & DEBUG_VIS_POSITION_DELTA)
+ DebugRenderPositionDelta();
+ if(mDebugVisualizationFlags & DEBUG_VIS_BOUNDING_BOX)
+ DebugRenderBoundingBox();
+ if(mDebugVisualizationFlags & DEBUG_VIS_DISTANCE_CONSTRAINTS)
+ DebugRenderDistanceConstraints();
+
+}
+
namespace
{
template <typename T> void trackT(std::vector<T>& list, T object)
@@ -127,9 +504,13 @@ void Scene::autoDeinitialize()
void Scene::doSimulationStep(float dt)
{
+ if(dt < FLT_EPSILON)
+ return;
startSimulationStep(dt);
waitForSimulationStep();
updateSimulationGraphics();
+
+ UpdateParticleDragging(dt);
}
void Scene::startSimulationStep(float dt)
@@ -160,3 +541,337 @@ void Scene::updateSimulationGraphics()
}
}
+physx::PxMat44 Scene::GetDebugDrawTransform(const ClothActor& actor)
+{
+ physx::PxMat44 transform;
+ if(actor.mClothRenderable != nullptr)
+ {
+ transform = actor.mClothRenderable->getModelMatrix();
+ }
+ else
+ {
+ physx::PxVec3 translation = actor.mCloth->getTranslation();
+ physx::PxQuat rotation = actor.mCloth->getRotation();
+ transform = physx::PxMat44(rotation);
+ transform[3] = physx::PxVec4(translation.x, translation.y, translation.z, 1.0f);
+ }
+ return transform;
+}
+
+void Scene::DebugRenderDistanceConstraints()
+{
+ DebugLineRenderBuffer* dbl = mSceneController->getDebugLineRenderBuffer();
+
+ for(auto it : mClothList)
+ {
+ nv::cloth::Cloth& cloth = *it->mCloth;
+ if(cloth.getNumMotionConstraints() == 0)
+ continue;
+
+ nv::cloth::Factory& factory = cloth.getFactory();
+
+ physx::PxMat44 transform = GetDebugDrawTransform(*it);
+
+ nv::cloth::MappedRange<physx::PxVec4> particles = cloth.getCurrentParticles();
+ std::vector<physx::PxVec4> motionConstraints;
+ motionConstraints.reserve(cloth.getNumMotionConstraints() * 2);
+ motionConstraints.resize(cloth.getNumMotionConstraints());
+ factory.extractMotionConstraints(cloth, nv::cloth::Range<physx::PxVec4>(&motionConstraints[0], &motionConstraints[0] + motionConstraints.size()));
+ motionConstraints.resize(cloth.getNumMotionConstraints() * 2);
+
+ nv::cloth::MappedRange<physx::PxVec4> positions = cloth.getCurrentParticles();
+
+ assert(positions.size() == cloth.getNumMotionConstraints());
+
+
+ //Set to 1 to color code lines based on distance constraint length (as % of max constraint distance in cloth)
+ //Set to 0 to color code lines based on how close the particle is to the distance constraint (as % of max distance per constraint)
+#define SHOW_DISTANCE_COLOR 0
+#if SHOW_DISTANCE_COLOR
+ float maxDist = 0.0f;
+ for(int i = (int)(motionConstraints.size() >> 1) - 1; i >= 0; i--)
+ {
+ maxDist = max(maxDist, motionConstraints[i].w);
+ }
+#endif
+
+ for(int i = ((int)motionConstraints.size() >> 1) - 1; i >= 0; i--)
+ {
+ float l = motionConstraints[i].w;
+ physx::PxVec3 a = motionConstraints[i].getXYZ();
+ physx::PxVec3 b = positions[i].getXYZ();
+ physx::PxVec3 d = b - a;
+ float currentDist = d.magnitude();
+ if(d.magnitudeSquared() < 0.00001f)
+ {
+ d = physx::PxVec3(0.0f, 0.0f, 1.0f);
+ }
+ else
+ {
+ d.normalize();
+ }
+ unsigned char clerp;
+#if SHOW_DISTANCE_COLOR
+ clerp = (unsigned char)(max(0.0f,min(1.0f,(l / maxDist)))*255.0f);
+#else
+ clerp = (unsigned char)(max(0.0f, min(1.0f, (currentDist / l)))*255.0f);
+#endif
+ unsigned int c = ((255-clerp) << 8) + clerp;
+ dbl->addLine(transform, a, a+d*l, c);
+ }
+ }
+}
+
+void Scene::DebugRenderTethers()
+{
+ DebugLineRenderBuffer* dbl = mSceneController->getDebugLineRenderBuffer();
+
+ for(auto it : mClothList)
+ {
+ nv::cloth::Cloth& cloth = *it->mCloth;
+ nv::cloth::Fabric& fabric = cloth.getFabric();
+ if(fabric.getNumTethers() == 0)
+ continue;
+
+ nv::cloth::Factory& factory = cloth.getFactory();
+
+ physx::PxMat44 transform = GetDebugDrawTransform(*it);
+
+ nv::cloth::MappedRange<physx::PxVec4> particles = cloth.getCurrentParticles();
+
+ std::vector<float> tetherLengths;
+ tetherLengths.resize(fabric.getNumTethers());
+ std::vector<uint32_t> anchors;
+ anchors.resize(fabric.getNumTethers());
+
+ factory.extractFabricData(fabric, nv::cloth::Range<uint32_t>(0, 0), nv::cloth::Range<uint32_t>(0, 0), nv::cloth::Range<float>(0, 0), nv::cloth::Range<float>(0, 0), nv::cloth::Range<uint32_t>(0, 0),
+ nv::cloth::Range<uint32_t>(&anchors[0], &anchors[0] + anchors.size()), nv::cloth::Range<float>(&tetherLengths[0], &tetherLengths[0] + tetherLengths.size()), nv::cloth::Range<uint32_t>(0, 0));
+
+ int particleCount = fabric.getNumParticles();
+
+ for(int i = 0; i < (int)anchors.size(); i++)
+ {
+ float lengthDiff = (particles[anchors[i]].getXYZ() - particles[i].getXYZ()).magnitude() - tetherLengths[i];
+ dbl->addLine(transform, particles[anchors[i]].getXYZ(), particles[i%particleCount].getXYZ(), lengthDiff>0.0f?0x0000FF:0x00FFFF);
+ }
+ }
+}
+
+void Scene::DebugRenderConstraints()
+{
+ DebugLineRenderBuffer* dbl = mSceneController->getDebugLineRenderBuffer();
+
+ for(auto it : mClothList)
+ {
+ nv::cloth::Cloth& cloth = *it->mCloth;
+ nv::cloth::Fabric& fabric = cloth.getFabric();
+ if(fabric.getNumIndices() == 0)
+ continue;
+
+ nv::cloth::Factory& factory = cloth.getFactory();
+
+ physx::PxMat44 transform = GetDebugDrawTransform(*it);
+
+ nv::cloth::MappedRange<physx::PxVec4> particles = cloth.getCurrentParticles();
+
+ if(sSceneDebugRenderParams.mVisiblePhaseRangeBegin >= sSceneDebugRenderParams.mVisiblePhaseRangeEnd)
+ {
+ //then simply render all constraints in one go
+ std::vector<uint32_t> indices;
+ indices.resize(fabric.getNumIndices());
+
+ factory.extractFabricData(fabric, nv::cloth::Range<uint32_t>(0, 0), nv::cloth::Range<uint32_t>(0, 0), nv::cloth::Range<float>(0, 0), nv::cloth::Range<float>(0, 0), nv::cloth::Range<uint32_t>(&indices[0], &indices[0] + indices.size()),
+ nv::cloth::Range<uint32_t>(0, 0), nv::cloth::Range<float>(0, 0), nv::cloth::Range<uint32_t>(0, 0));
+
+ for(int i = 1; i < (int)indices.size(); i+=2)
+ {
+ dbl->addLine(transform, particles[indices[i]].getXYZ(), particles[indices[i-1]].getXYZ(), 0x991919);
+ }
+ }
+ else
+ {
+ //otherwise we render individual phases
+ std::vector<uint32_t> indices;
+ indices.resize(fabric.getNumIndices());
+ std::vector<uint32_t> phases;
+ phases.resize(fabric.getNumPhases());
+ std::vector<uint32_t> sets;
+ sets.resize(fabric.getNumSets());
+
+ factory.extractFabricData(fabric, nv::cloth::Range<uint32_t>(&phases[0], &phases[0] + phases.size()), nv::cloth::Range<uint32_t>(&sets[0], &sets[0] + sets.size()), nv::cloth::Range<float>(0, 0), nv::cloth::Range<float>(0, 0), nv::cloth::Range<uint32_t>(&indices[0], &indices[0] + indices.size()),
+ nv::cloth::Range<uint32_t>(0, 0), nv::cloth::Range<float>(0, 0), nv::cloth::Range<uint32_t>(0, 0));
+
+ uint32_t* iIt = &indices[0];
+ for(int phaseIndex = 0; phaseIndex < (int)fabric.getNumPhases(); phaseIndex++)
+ {
+ uint32_t* sIt = &sets[phases[phaseIndex]];
+ uint32_t* iEnd = &indices[0] + (sIt[0] * 2);
+ uint32_t* iStart = iIt;
+
+ if(!(phaseIndex >= sSceneDebugRenderParams.mVisiblePhaseRangeBegin && phaseIndex < sSceneDebugRenderParams.mVisiblePhaseRangeEnd))
+ {
+ iIt = iEnd;
+ continue;
+ }
+
+ for(iIt; iIt < iEnd; iIt+=2)
+ {
+ float c = (float)(iIt - iStart) / (float)(iEnd - iStart);
+ unsigned char c255 = (unsigned char)(c*255.0f);
+
+ unsigned int colorTable[3]
+ {
+ 0xFF0000,
+ 0x00FF00,
+ 0x0000FF
+ };
+ unsigned int shiftTable[3]
+ {
+ 8,
+ 0,
+ 16
+ };
+
+ dbl->addLine(transform, particles[*iIt].getXYZ(), particles[*(iIt+1)].getXYZ(), colorTable[phaseIndex%3] + (c255<< shiftTable[phaseIndex%3]));
+ }
+ }
+ }
+ }
+}
+
+void Scene::DebugRenderConstraintStiffness()
+{
+ DebugLineRenderBuffer* dbl = mSceneController->getDebugLineRenderBuffer();
+
+ for(auto it : mClothList)
+ {
+ nv::cloth::Cloth& cloth = *it->mCloth;
+ nv::cloth::Fabric& fabric = cloth.getFabric();
+ if(fabric.getNumIndices() == 0)
+ continue;
+
+ if(!fabric.getNumStiffnessValues())
+ continue;
+
+ nv::cloth::Factory& factory = cloth.getFactory();
+
+ physx::PxMat44 transform = GetDebugDrawTransform(*it);
+
+ nv::cloth::MappedRange<physx::PxVec4> particles = cloth.getCurrentParticles();
+
+ std::vector<uint32_t> indices;
+ indices.resize(fabric.getNumIndices());
+ std::vector<float> stiffness;
+ stiffness.resize(fabric.getNumRestvalues());
+
+ factory.extractFabricData(fabric, nv::cloth::Range<uint32_t>(0, 0), nv::cloth::Range<uint32_t>(0, 0), nv::cloth::Range<float>(0, 0), nv::cloth::Range<float>(&stiffness[0], &stiffness[0] + stiffness.size()), nv::cloth::Range<uint32_t>(&indices[0], &indices[0] + indices.size()),
+ nv::cloth::Range<uint32_t>(0, 0), nv::cloth::Range<float>(0, 0), nv::cloth::Range<uint32_t>(0, 0));
+
+ for(int i = 1; i < (int)indices.size(); i+=2)
+ {
+ float c = 1.0f - exp2f(stiffness[i >> 1]);
+
+ unsigned char ca255 = (unsigned char)(c*255.0f*0.8f);
+ unsigned char cb255 = (unsigned char)((1.0f-c)*255.0f*0.8f);
+ dbl->addLine(transform, particles[indices[i-1]].getXYZ(), particles[indices[i]].getXYZ(), (ca255<<8) + (cb255<<0));
+ }
+ }
+}
+
+void Scene::DebugRenderConstraintError()
+{
+ DebugLineRenderBuffer* dbl = mSceneController->getDebugLineRenderBuffer();
+
+ for(auto it : mClothList)
+ {
+ nv::cloth::Cloth& cloth = *it->mCloth;
+ nv::cloth::Fabric& fabric = cloth.getFabric();
+ if(fabric.getNumRestvalues() == 0) { continue; }
+ nv::cloth::Factory& factory = cloth.getFactory();
+
+ physx::PxMat44 transform = GetDebugDrawTransform(*it);
+
+ nv::cloth::MappedRange<physx::PxVec4> particles = cloth.getCurrentParticles();
+
+ std::vector<uint32_t> indices;
+ indices.resize(fabric.getNumIndices());
+ std::vector<float> restLengths;
+ restLengths.resize(fabric.getNumRestvalues());
+
+ factory.extractFabricData(fabric, nv::cloth::Range<uint32_t>(0, 0), nv::cloth::Range<uint32_t>(0, 0), nv::cloth::Range<float>(&restLengths[0], &restLengths[0] + restLengths.size()), nv::cloth::Range<float>(0, 0), nv::cloth::Range<uint32_t>(&indices[0], &indices[0] + indices.size()),
+ nv::cloth::Range<uint32_t>(0, 0), nv::cloth::Range<float>(0, 0), nv::cloth::Range<uint32_t>(0, 0));
+
+ for(int i = 0; i < (int)indices.size(); i += 2)
+ {
+ physx::PxVec4 p0 = particles[indices[i]];
+ physx::PxVec4 p1 = particles[indices[i + 1]];
+ float restLength = restLengths[i >> 1];
+ float length = (p0 - p1).magnitude();
+ const float scale = 2.0f;
+ float error = (length / restLength * 0.5f - 0.5f) * scale + 0.5f;
+ error = max(0.0f, min(1.0f, error));
+ unsigned char c255 = (unsigned char)(error*255.0f*0.8f);
+ dbl->addLine(transform, p0.getXYZ(), p1.getXYZ(), ((255-c255) << 8) + (c255 << 0));
+ }
+ }
+}
+
+void Scene::DebugRenderPositionDelta()
+{
+ DebugLineRenderBuffer* dbl = mSceneController->getDebugLineRenderBuffer();
+
+ for(auto it : mClothList)
+ {
+ nv::cloth::Cloth& cloth = *it->mCloth;
+
+ physx::PxMat44 transform = GetDebugDrawTransform(*it);
+
+ nv::cloth::MappedRange<physx::PxVec4> particles1 = cloth.getCurrentParticles();
+ nv::cloth::MappedRange<physx::PxVec4> particles0 = cloth.getPreviousParticles();
+
+ std::vector<physx::PxVec4> lines;
+
+ //scale so that the solver frequency doesn't affect the position delta length assuming 60fps
+ float iterationsPerFrame = max(1, int(1.0f / 60.0f * cloth.getSolverFrequency() + 0.5f));
+
+ for(int i = 0; i < (int)particles1.size(); i++)
+ {
+ dbl->addVector(transform, particles1[i].getXYZ(), (particles1[i] - particles0[i]).getXYZ()*iterationsPerFrame * 2.0f,0xFFFF00);
+ }
+ }
+}
+
+void Scene::DebugRenderBoundingBox()
+{
+ DebugLineRenderBuffer* dbl = mSceneController->getDebugLineRenderBuffer();
+
+ for(auto it : mClothList)
+ {
+ nv::cloth::Cloth& cloth = *it->mCloth;
+
+ physx::PxMat44 transform = GetDebugDrawTransform(*it);
+
+ physx::PxVec3 c = cloth.getBoundingBoxCenter();
+ physx::PxVec3 d = cloth.getBoundingBoxScale();
+ physx::PxVec3 dx = physx::PxVec3(d.x, 0.0f, 0.0f);
+ physx::PxVec3 dy = physx::PxVec3(0.0f, d.y, 0.0f);
+ physx::PxVec3 dz = physx::PxVec3(0.0f, 0.0f, d.z);
+
+ dbl->addLine(transform,c + dy + dz - dx,c + dy + dz + dx, 0x00FFFF);
+ dbl->addLine(transform,c + dy - dz - dx,c + dy - dz + dx, 0x00FFFF);
+ dbl->addLine(transform,c - dy + dz - dx,c - dy + dz + dx, 0x00FFFF);
+ dbl->addLine(transform,c - dy - dz - dx,c - dy - dz + dx, 0x00FFFF);
+ dbl->addLine(transform,c + dy + dx - dz,c + dy + dx + dz, 0x00FFFF);
+ dbl->addLine(transform,c + dy - dx - dz,c + dy - dx + dz, 0x00FFFF);
+ dbl->addLine(transform,c - dy + dx - dz,c - dy + dx + dz, 0x00FFFF);
+ dbl->addLine(transform,c - dy - dx - dz,c - dy - dx + dz, 0x00FFFF);
+ dbl->addLine(transform,c + dz + dx - dy,c + dz + dx + dy, 0x00FFFF);
+ dbl->addLine(transform,c + dz - dx - dy,c + dz - dx + dy, 0x00FFFF);
+ dbl->addLine(transform,c - dz + dx - dy,c - dz + dx + dy, 0x00FFFF);
+ dbl->addLine(transform,c - dz - dx - dy,c - dz - dx + dy, 0x00FFFF);
+ dbl->addLine(transform,c + dy + dz + dx,c - dy - dz - dx, 0x007777);
+ dbl->addLine(transform,c + dy + dz - dx,c - dy - dz + dx, 0x007777);
+ dbl->addLine(transform,c - dy + dz + dx,c + dy - dz - dx, 0x007777);
+ dbl->addLine(transform,c - dy + dz - dx,c + dy - dz + dx, 0x007777);
+ }
+} \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/Scene.h b/NvCloth/samples/SampleBase/scene/Scene.h
index 3a11ec7..1c14fbd 100644
--- a/NvCloth/samples/SampleBase/scene/Scene.h
+++ b/NvCloth/samples/SampleBase/scene/Scene.h
@@ -14,6 +14,7 @@
#include <vector>
#include <map>
#include "scene/SceneController.h"
+#include "foundation/PxMat44.h"
namespace nv
{
namespace cloth
@@ -33,7 +34,7 @@ struct SceneFactory
const char* mName;
};
-#define DECLARE_SCENE_NAME(classname, name) static int classname##id = Scene::AddSceneFactory([](SceneController* c) {return (Scene*)new classname(c); }, name);
+#define DECLARE_SCENE_NAME(classname, name) static int classname##id = Scene::AddSceneFactory([](SceneController* c) {return static_cast<Scene*>(new classname(c)); }, name);
#define DECLARE_SCENE(classname) DECLARE_SCENE_NAME(classname,#classname)
class Scene
@@ -43,9 +44,13 @@ public:
Scene(SceneController* sceneController):mSceneController(sceneController) {}
virtual ~Scene();
- virtual void Animate(double dt) { doSimulationStep(dt); }
- virtual void drawUI() {}
+ virtual void Animate(double dt) { doSimulationStep(dt); drawDebugVisualization(); }
+ void UpdateParticleDragging(float dt);
+ virtual bool HandleEvent(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ bool HandlePickingEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, physx::PxMat44 viewProjectionMatrix);
+ virtual void drawUI();
virtual void drawStatsUI() {}
+ virtual void drawDebugVisualization();
virtual void onInitialize() = 0;
virtual void onTerminate() { autoDeinitialize(); }
@@ -86,6 +91,15 @@ protected:
private:
Scene& operator= (Scene&); // not implemented
+ physx::PxMat44 GetDebugDrawTransform(const ClothActor& actor);
+ void DebugRenderDistanceConstraints();
+ void DebugRenderTethers();
+ void DebugRenderConstraints();
+ void DebugRenderConstraintStiffness();
+ void DebugRenderConstraintError();
+ void DebugRenderPositionDelta();
+ void DebugRenderBoundingBox();
+
private:
SceneController* mSceneController;
@@ -98,6 +112,43 @@ private:
static std::vector<SceneFactory> sSceneFactories;
+ enum
+ {
+ DEBUG_VIS_DISTANCE_CONSTRAINTS = 1,
+ DEBUG_VIS_TETHERS = 2,
+ DEBUG_VIS_CONSTRAINTS = 4,
+ DEBUG_VIS_CONSTRAINTS_STIFFNESS = 8,
+ DEBUG_VIS_NORMALS = 16,
+ DEBUG_VIS_TANGENTS = 32,
+ DEBUG_VIS_BITANGENTS = 64,
+ DEBUG_VIS_CONSTRAINT_ERROR = 128,
+ DEBUG_VIS_POSITION_DELTA = 256,
+ DEBUG_VIS_ACCELERATION = 512,
+ DEBUG_VIS_BOUNDING_BOX = 1024,
+ DEBUG_VIS_LAST
+ };
+
+ static unsigned int mDebugVisualizationFlags;
+
+ struct SceneDebugRenderParams
+ {
+ //Constraint render params
+ int mVisiblePhaseRangeBegin;
+ int mVisiblePhaseRangeEnd;
+ };
+
+ static SceneDebugRenderParams sSceneDebugRenderParams;
+
+ //Particle dragging
+ struct DraggingParticle
+ {
+ DraggingParticle() { mTrackedCloth = nullptr; }
+ ClothActor* mTrackedCloth;
+ float mDist;
+ float mOffset;
+ int mParticleIndex;
+ };
+ DraggingParticle mDraggingParticle;
};
diff --git a/NvCloth/samples/SampleBase/scene/SceneController.cpp b/NvCloth/samples/SampleBase/scene/SceneController.cpp
index 90b499c..fa35d5d 100644
--- a/NvCloth/samples/SampleBase/scene/SceneController.cpp
+++ b/NvCloth/samples/SampleBase/scene/SceneController.cpp
@@ -40,6 +40,8 @@
#include "scene/scenes/SimpleScene.h"
#include "scene/scenes/WindScene.h"
+#include "utils/DebugLineRenderBuffer.h"
+
JobManager SceneController::sJobManager;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -51,6 +53,9 @@ SceneController::SceneController() : mTimeScale(1.0f), mStartDelay(0.f)
mActivePlatform = (int)nv::cloth::Platform::CPU;
mCUDAInitialized = false;
mDXInitialized = false;
+ mLeftOverTime = 0.0;
+ mPaused = false;
+ mSingleStep = 0;
}
SceneController::~SceneController()
@@ -137,6 +142,8 @@ void SceneController::onInitialize()
mFactories[(int)nv::cloth::Platform::DX11] = NvClothCreateFactoryDX11(mGraphicsContextManager);
mDXInitialized &= mFactories[(int)nv::cloth::Platform::DX11] != nullptr;
} while(false);
+
+ mDebugLineRenderBuffer = new DebugLineRenderBuffer;
}
void SceneController::onSampleStop()
@@ -181,16 +188,38 @@ void SceneController::changeScene(int index)
void SceneController::Animate(double dt)
{
- double simulationStep = dt * mTimeScale;
- if(simulationStep > 1.0 / 60.0)
+ if(mPaused && (mSingleStep <= 0))
+ {
+ //Re render debug lines from last frame
+ getRenderer().queueRenderBuffer(mDebugLineRenderBuffer);
+ return;
+ }
+ if(mSingleStep > 0)
+ {
+ mSingleStep--;
+ dt = 1.0 / 60.0;
+ }
+
+ mDebugLineRenderBuffer->clear();
+
+ mLeftOverTime += dt * mTimeScale;
+
+ double simulationStep = 0.0;
+ while(mLeftOverTime > 1.0 / 60.0)
+ simulationStep += 1.0 / 60.0, mLeftOverTime -= 1.0 / 60.0;
+ if(simulationStep >= 1.0 / 60.0)
simulationStep = 1.0 / 60.0;
mActiveScene->Animate(simulationStep);
+ getRenderer().queueRenderBuffer(mDebugLineRenderBuffer);
}
LRESULT SceneController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
+ if(mActiveScene->HandleEvent(uMsg, wParam, lParam))
+ return 1;
+
if (uMsg == WM_KEYDOWN)
{
int iKeyPressed = static_cast<int>(wParam);
@@ -202,10 +231,12 @@ LRESULT SceneController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
switch (iKeyPressed)
{
- case 'R':
- return 0;
- case 'F':
- return 0;
+ case 'P':
+ mPaused = !mPaused;
+ break;
+ case 'O':
+ mSingleStep++;
+ break;
default:
break;
}
diff --git a/NvCloth/samples/SampleBase/scene/SceneController.h b/NvCloth/samples/SampleBase/scene/SceneController.h
index d527597..9f4f428 100644
--- a/NvCloth/samples/SampleBase/scene/SceneController.h
+++ b/NvCloth/samples/SampleBase/scene/SceneController.h
@@ -37,6 +37,7 @@ namespace nv
class RenderMaterial;
class Renderable;
+class DebugLineRenderBuffer;
struct ClothActor
{
@@ -91,6 +92,10 @@ public:
return mPhysXPlaneRenderMaterial;
}
+ DebugLineRenderBuffer* getDebugLineRenderBuffer()
+ {
+ return mDebugLineRenderBuffer;
+ }
private:
SceneController& operator= (SceneController&); // not implemented
@@ -104,6 +109,7 @@ private:
Renderable* mPlane;
std::vector<Renderable*> mBoxes;
+ DebugLineRenderBuffer* mDebugLineRenderBuffer;
float mTimeScale;
float mStartDelay;
@@ -121,8 +127,13 @@ private:
ID3D11DeviceContext* mDXDeviceContext;
nv::cloth::DxContextManagerCallback* mGraphicsContextManager;
- Scene* mActiveScene;
- int mActiveSceneIndex;
+ Scene* mActiveScene;
+ int mActiveSceneIndex;
+ double mLeftOverTime;
+
+ bool mPaused;
+ int mSingleStep;
+
};
#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/scenes/CCDScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/CCDScene.cpp
new file mode 100644
index 0000000..2d0eaa8
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/CCDScene.cpp
@@ -0,0 +1,153 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "CCDScene.h"
+#include "Scene/SceneController.h"
+#include <NvClothExt/ClothFabricCooker.h>
+#include "ClothMeshGenerator.h"
+#include <NvCloth/Fabric.h>
+#include <NvCloth/Solver.h>
+#include <NvCloth/Cloth.h>
+#include <NvCloth/Factory.h>
+#include "Renderer.h"
+#include "renderer/RenderUtils.h"
+#include "windows.h"
+#include "utils/MeshGenerator.h"
+
+DECLARE_SCENE_NAME(CCDScene, "CCD Scene")
+
+void CCDScene::Animate(double dt)
+{
+ static float time = 0.0f;
+ time += dt;
+
+ physx::PxTransform invTranslation(-mOffset - physx::PxVec3(0.f, 10.f, -2.f));
+ physx::PxTransform rotation(physx::PxQuat(cosf(time)*physx::PxHalfPi-physx::PxHalfPi,physx::PxVec3(0.0f,1.0f,0.0f)));
+ physx::PxTransform translation(mOffset + physx::PxVec3(0.f, 10.f, -2.f) + physx::PxVec3(0.0f,0.0f,10.0f*sinf(time)));
+ physx::PxTransform totalTransform = translation.transform(rotation.transform(invTranslation));
+
+ physx::PxVec4 spheres[2] = {physx::PxVec4(totalTransform.transform(physx::PxVec3(0.f, 10.f, -2.f) + mOffset),2.0),
+ physx::PxVec4(totalTransform.transform(physx::PxVec3(0.f, 11.f, 3.f) + mOffset),0.5)};
+
+ mClothActor[0]->mCloth->setSpheres(nv::cloth::Range<physx::PxVec4>(spheres, spheres + 2), 0, mClothActor[0]->mCloth->getNumSpheres());
+
+ mCollisionMehs->setTransform(totalTransform);
+
+ Scene::Animate(dt);
+}
+
+void CCDScene::initializeCloth(int index, physx::PxVec3 offset)
+{
+ mOffset = offset;
+
+ ///////////////////////////////////////////////////////////////////////
+ ClothMeshData clothMesh;
+
+ physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f)+ mOffset, PxQuat(0, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(5.f, 6.f, 69, 79, false, transform);
+ clothMesh.AttachClothPlaneByAngles(69, 79);
+ clothMesh.SetInvMasses(0.5f + (float)index * 2.0f);
+
+ mClothActor[index] = new ClothActor;
+ nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
+ {
+ mClothActor[index]->mClothRenderMesh = new ClothRenderMesh(meshDesc);
+ mClothActor[index]->mClothRenderable = getSceneController()->getRenderer().createRenderable(*(static_cast<IRenderMesh*>(mClothActor[index]->mClothRenderMesh)), *getSceneController()->getDefaultMaterial());
+
+ float r, g, b;
+ r = index == 0 ? 1.0f : 0.3f;
+ g = index == 1 ? 1.0f : 0.3f;
+ b = index == 2 ? 1.0f : 0.3f;
+
+ mClothActor[index]->mClothRenderable->setColor(DirectX::XMFLOAT4(r, g, b, 1.0f));
+ }
+
+ nv::cloth::Vector<int32_t>::Type phaseTypeInfo;
+ mFabric[index] = NvClothCookFabricFromMesh(getSceneController()->getFactory(), meshDesc, physx::PxVec3(0.0f, 0.0f, 1.0f), &phaseTypeInfo, false);
+ trackFabric(mFabric[index]);
+
+ // Initialize start positions and masses for the actual cloth instance
+ // (note: the particle/vertex positions do not have to match the mesh description here. Set the positions to the initial shape of this cloth instance)
+ std::vector<physx::PxVec4> particlesCopy;
+ particlesCopy.resize(clothMesh.mVertices.size());
+
+ physx::PxVec3 clothOffset = transform.getPosition();
+ for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ {
+ // To put attachment point closer to each other
+ if(clothMesh.mInvMasses[i] < 1e-6)
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.95f + clothOffset;
+
+ particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
+ }
+
+ // Create the cloth from the initial positions/masses and the fabric
+ mClothActor[index]->mCloth = getSceneController()->getFactory()->createCloth(nv::cloth::Range<physx::PxVec4>(&particlesCopy[0], &particlesCopy[0] + particlesCopy.size()), *mFabric[index]);
+ particlesCopy.clear(); particlesCopy.shrink_to_fit();
+
+ mClothActor[index]->mCloth->setGravity(physx::PxVec3(0.0f, -9.8f, 0.0f));
+ mClothActor[index]->mCloth->setDamping(physx::PxVec3(0.1f, 0.1f, 0.1f));
+ mClothActor[index]->mCloth->setSelfCollisionDistance(0.07f);
+ mClothActor[index]->mCloth->enableContinuousCollision(true);
+ mClothActor[index]->mCloth->setSolverFrequency(240);
+
+
+ physx::PxVec4 spheres[2] = {physx::PxVec4(physx::PxVec3(0.f, 10.f, -2.f) + mOffset,2.0),
+ physx::PxVec4(physx::PxVec3(0.f, 11.f, 3.f) + mOffset,0.5)};
+
+ mClothActor[index]->mCloth->setSpheres(nv::cloth::Range<physx::PxVec4>(spheres, spheres + 2), 0, mClothActor[index]->mCloth->getNumSpheres());
+
+ uint32_t caps[4];
+ caps[0] = 0;
+ caps[1] = 1;
+
+ mClothActor[index]->mCloth->setCapsules(nv::cloth::Range<uint32_t>(caps, caps + 2), 0, mClothActor[index]->mCloth->getNumCapsules());
+
+ //create render mesh
+ auto mesh = MeshGenerator::generateCollisionCapsules(spheres,2,caps,2,-0.05f);
+ auto renderMesh = new MeshGenerator::MeshGeneratorRenderMesh(mesh);
+ mCollisionMehs = getSceneController()->getRenderer().createRenderable(*renderMesh, *getSceneController()->getDefaultMaterial());
+ trackRenderable(mCollisionMehs);
+
+ // Setup phase configs
+ std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
+ for(int i = 0; i < (int)phases.size(); i++)
+ {
+ phases[i].mPhaseIndex = i;
+ phases[i].mStiffness = 1.0f;
+ phases[i].mStiffnessMultiplier = 1.0f;
+ phases[i].mCompressionLimit = 1.0f;
+ phases[i].mStretchLimit = 1.0f;
+ }
+ mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
+ mClothActor[index]->mCloth->setDragCoefficient(0.5f);
+ mClothActor[index]->mCloth->setLiftCoefficient(0.6f);
+
+ trackClothActor(mClothActor[index]);
+
+ // Add the cloth to the solver for simulation
+ addClothToSolver(mClothActor[index], mSolver);
+}
+
+void CCDScene::onInitialize()
+{
+ mSolver = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver);
+
+ initializeCloth(0, physx::PxVec3(0.0f, 0.0f, 0.0f));
+
+ {
+ IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
+ Renderable* plane = getSceneController()->getRenderer().createRenderable(*mesh, *getSceneController()->getDefaultPlaneMaterial());
+ plane->setTransform(PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxPiDivTwo, PxVec3(0.f, 0.f, 1.f))));
+ plane->setScale(PxVec3(1000.f));
+ trackRenderable(plane);
+ }
+}
diff --git a/NvCloth/samples/SampleBase/scene/scenes/CCDScene.h b/NvCloth/samples/SampleBase/scene/scenes/CCDScene.h
new file mode 100644
index 0000000..e988fb7
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/CCDScene.h
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef CCD_SCENE_H
+#define CCD_SCENE_H
+
+#include "scene/Scene.h"
+#include <foundation/PxVec3.h>
+
+class CCDScene : public Scene
+{
+public:
+
+ CCDScene(SceneController* sceneController): Scene(sceneController) {}
+
+ virtual void Animate(double dt) override;
+ void initializeCloth(int index, physx::PxVec3 offset);
+ virtual void onInitialize() override;
+
+private:
+ nv::cloth::Fabric* mFabric[1];
+ nv::cloth::Solver* mSolver;
+ ClothActor* mClothActor[1];
+
+ physx::PxVec3 mOffset;
+ Renderable* mCollisionMehs;
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/scenes/CapsuleScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/CapsuleScene.cpp
new file mode 100644
index 0000000..e16899c
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/CapsuleScene.cpp
@@ -0,0 +1,129 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "CapsuleScene.h"
+#include "Scene/SceneController.h"
+#include <NvClothExt/ClothFabricCooker.h>
+#include "ClothMeshGenerator.h"
+#include <NvCloth/Fabric.h>
+#include <NvCloth/Solver.h>
+#include <NvCloth/Cloth.h>
+#include <NvCloth/Factory.h>
+#include "Renderer.h"
+#include "renderer/RenderUtils.h"
+#include "windows.h"
+#include "utils/MeshGenerator.h"
+
+DECLARE_SCENE_NAME(CapsuleScene, "Capsule Scene")
+
+
+void CapsuleScene::initializeCloth(int index, physx::PxVec3 offset)
+{
+ ///////////////////////////////////////////////////////////////////////
+ ClothMeshData clothMesh;
+
+ physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f)+ offset, PxQuat(0, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(5.f, 6.f, 69, 79, false, transform);
+ clothMesh.AttachClothPlaneByAngles(69, 79);
+ clothMesh.SetInvMasses(0.5f + (float)index * 2.0f);
+
+ mClothActor[index] = new ClothActor;
+ nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
+ {
+ mClothActor[index]->mClothRenderMesh = new ClothRenderMesh(meshDesc);
+ mClothActor[index]->mClothRenderable = getSceneController()->getRenderer().createRenderable(*(static_cast<IRenderMesh*>(mClothActor[index]->mClothRenderMesh)), *getSceneController()->getDefaultMaterial());
+
+ float r, g, b;
+ r = index == 0 ? 1.0f : 0.3f;
+ g = index == 1 ? 1.0f : 0.3f;
+ b = index == 2 ? 1.0f : 0.3f;
+
+ mClothActor[index]->mClothRenderable->setColor(DirectX::XMFLOAT4(r, g, b, 1.0f));
+ }
+
+ nv::cloth::Vector<int32_t>::Type phaseTypeInfo;
+ mFabric[index] = NvClothCookFabricFromMesh(getSceneController()->getFactory(), meshDesc, physx::PxVec3(0.0f, 0.0f, 1.0f), &phaseTypeInfo, false);
+ trackFabric(mFabric[index]);
+
+ // Initialize start positions and masses for the actual cloth instance
+ // (note: the particle/vertex positions do not have to match the mesh description here. Set the positions to the initial shape of this cloth instance)
+ std::vector<physx::PxVec4> particlesCopy;
+ particlesCopy.resize(clothMesh.mVertices.size());
+
+ physx::PxVec3 clothOffset = transform.getPosition();
+ for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ {
+ // To put attachment point closer to each other
+ if(clothMesh.mInvMasses[i] < 1e-6)
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.95f + clothOffset;
+
+ particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
+ }
+
+ // Create the cloth from the initial positions/masses and the fabric
+ mClothActor[index]->mCloth = getSceneController()->getFactory()->createCloth(nv::cloth::Range<physx::PxVec4>(&particlesCopy[0], &particlesCopy[0] + particlesCopy.size()), *mFabric[index]);
+ particlesCopy.clear(); particlesCopy.shrink_to_fit();
+
+ mClothActor[index]->mCloth->setGravity(physx::PxVec3(0.0f, -9.8f, 0.0f));
+ mClothActor[index]->mCloth->setDamping(physx::PxVec3(0.1f, 0.1f, 0.1f));
+
+
+ physx::PxVec4 spheres[2] = {physx::PxVec4(physx::PxVec3(0.f, 10.f, -2.f) + offset,3.0),
+ physx::PxVec4(physx::PxVec3(0.f, 10.f, 2.f) + offset,1.0)};
+
+ mClothActor[index]->mCloth->setSpheres(nv::cloth::Range<physx::PxVec4>(spheres, spheres + 2), 0, mClothActor[index]->mCloth->getNumSpheres());
+
+ uint32_t caps[4];
+ caps[0] = 0;
+ caps[1] = 1;
+
+ mClothActor[index]->mCloth->setCapsules(nv::cloth::Range<uint32_t>(caps, caps + 2), 0, mClothActor[index]->mCloth->getNumCapsules());
+
+ //create render mesh
+ auto mesh = MeshGenerator::generateCollisionCapsules(spheres,2,caps,2,-0.05f);
+ auto renderMesh = new MeshGenerator::MeshGeneratorRenderMesh(mesh);
+ Renderable* renderable = getSceneController()->getRenderer().createRenderable(*renderMesh, *getSceneController()->getDefaultMaterial());
+ trackRenderable(renderable);
+
+ // Setup phase configs
+ std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
+ for(int i = 0; i < (int)phases.size(); i++)
+ {
+ phases[i].mPhaseIndex = i;
+ phases[i].mStiffness = 1.0f;
+ phases[i].mStiffnessMultiplier = 1.0f;
+ phases[i].mCompressionLimit = 1.0f;
+ phases[i].mStretchLimit = 1.0f;
+ }
+ mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
+ mClothActor[index]->mCloth->setDragCoefficient(0.5f);
+ mClothActor[index]->mCloth->setLiftCoefficient(0.6f);
+
+ trackClothActor(mClothActor[index]);
+
+ // Add the cloth to the solver for simulation
+ addClothToSolver(mClothActor[index], mSolver);
+}
+
+void CapsuleScene::onInitialize()
+{
+ mSolver = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver);
+
+ initializeCloth(0, physx::PxVec3(0.0f, 0.0f, 0.0f));
+
+ {
+ IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
+ Renderable* plane = getSceneController()->getRenderer().createRenderable(*mesh, *getSceneController()->getDefaultPlaneMaterial());
+ plane->setTransform(PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxPiDivTwo, PxVec3(0.f, 0.f, 1.f))));
+ plane->setScale(PxVec3(1000.f));
+ trackRenderable(plane);
+ }
+}
diff --git a/NvCloth/samples/SampleBase/scene/scenes/CapsuleScene.h b/NvCloth/samples/SampleBase/scene/scenes/CapsuleScene.h
new file mode 100644
index 0000000..f1f68fd
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/CapsuleScene.h
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef CAPSULE_SCENE_H
+#define CAPSULE_SCENE_H
+
+#include "scene/Scene.h"
+#include <foundation/PxVec3.h>
+
+class CapsuleScene : public Scene
+{
+public:
+
+ CapsuleScene(SceneController* sceneController): Scene(sceneController) {}
+
+ void initializeCloth(int index, physx::PxVec3 offset);
+ virtual void onInitialize() override;
+
+private:
+ nv::cloth::Fabric* mFabric[1];
+ nv::cloth::Solver* mSolver;
+ ClothActor* mClothActor[1];
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/scenes/ConvexCollisionScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/ConvexCollisionScene.cpp
new file mode 100644
index 0000000..28df734
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/ConvexCollisionScene.cpp
@@ -0,0 +1,138 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "ConvexCollisionScene.h"
+#include "Scene/SceneController.h"
+#include <NvClothExt/ClothFabricCooker.h>
+#include "ClothMeshGenerator.h"
+#include <NvCloth/Fabric.h>
+#include <NvCloth/Solver.h>
+#include <NvCloth/Cloth.h>
+#include <NvCloth/Factory.h>
+#include "Renderer.h"
+#include "renderer/RenderUtils.h"
+#include "windows.h"
+#include "utils/MeshGenerator.h"
+
+DECLARE_SCENE_NAME(ConvexCollisionScene, "Convex Collision Scene")
+
+
+void ConvexCollisionScene::initializeCloth(int index, physx::PxVec3 offset)
+{
+ ///////////////////////////////////////////////////////////////////////
+ ClothMeshData clothMesh;
+
+ physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f)+ offset, PxQuat(0, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(5.f, 6.f, 59, 69, false, transform);
+ clothMesh.AttachClothPlaneByAngles(59, 69);
+ clothMesh.SetInvMasses(0.5f + (float)index * 2.0f);
+
+ mClothActor[index] = new ClothActor;
+ nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
+ {
+ mClothActor[index]->mClothRenderMesh = new ClothRenderMesh(meshDesc);
+ mClothActor[index]->mClothRenderable = getSceneController()->getRenderer().createRenderable(*(static_cast<IRenderMesh*>(mClothActor[index]->mClothRenderMesh)), *getSceneController()->getDefaultMaterial());
+
+ float r, g, b;
+ r = index == 0 ? 1.0f : 0.3f;
+ g = index == 1 ? 1.0f : 0.3f;
+ b = index == 2 ? 1.0f : 0.3f;
+
+ mClothActor[index]->mClothRenderable->setColor(DirectX::XMFLOAT4(r, g, b, 1.0f));
+ }
+
+ nv::cloth::Vector<int32_t>::Type phaseTypeInfo;
+ mFabric[index] = NvClothCookFabricFromMesh(getSceneController()->getFactory(), meshDesc, physx::PxVec3(0.0f, 0.0f, 1.0f), &phaseTypeInfo, false);
+ trackFabric(mFabric[index]);
+
+ // Initialize start positions and masses for the actual cloth instance
+ // (note: the particle/vertex positions do not have to match the mesh description here. Set the positions to the initial shape of this cloth instance)
+ std::vector<physx::PxVec4> particlesCopy;
+ particlesCopy.resize(clothMesh.mVertices.size());
+
+ physx::PxVec3 clothOffset = transform.getPosition();
+ for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ {
+ // To put attachment point closer to each other
+ if(clothMesh.mInvMasses[i] < 1e-6)
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.95f + clothOffset;
+
+ particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
+ }
+
+ // Create the cloth from the initial positions/masses and the fabric
+ mClothActor[index]->mCloth = getSceneController()->getFactory()->createCloth(nv::cloth::Range<physx::PxVec4>(&particlesCopy[0], &particlesCopy[0] + particlesCopy.size()), *mFabric[index]);
+ particlesCopy.clear(); particlesCopy.shrink_to_fit();
+
+ mClothActor[index]->mCloth->setGravity(physx::PxVec3(0.0f, -9.8f, 0.0f));
+ mClothActor[index]->mCloth->setDamping(physx::PxVec3(0.1f, 0.1f, 0.1f));
+
+ //Generate collision planes
+ std::vector<physx::PxVec4> planes;
+ uint32_t mask1 = MeshGenerator::generateConvexPolyhedronPlanes(4, 4, physx::PxVec3(0.7f, 10.0f, -1.0f), 1.0f, &planes);
+ uint32_t mask2 = MeshGenerator::generateConvexPolyhedronPlanes(4, 4, physx::PxVec3(-0.7f, 10.0f, 0.0f), 1.0f, &planes);
+ MeshGenerator::Mesh mesh1 = MeshGenerator::generateCollisionConvex(planes.data(),mask1,-0.05f,false);
+ MeshGenerator::Mesh mesh2 = MeshGenerator::generateCollisionConvex(planes.data(), mask2, -0.05f, false);
+
+ //assign as collision data
+ nv::cloth::Range<const physx::PxVec4> planesR(&planes[0], &planes[0] + planes.size());
+ mClothActor[index]->mCloth->setPlanes(planesR, 0, mClothActor[index]->mCloth->getNumPlanes());
+
+ //assign convex indices
+ std::vector<uint32_t> indices;
+ indices.push_back(mask1);
+ indices.push_back(mask2);
+ nv::cloth::Range<uint32_t> cind(&indices[0], &indices[0] + indices.size());
+ mClothActor[index]->mCloth->setConvexes(cind, 0, mClothActor[index]->mCloth->getNumConvexes());
+
+ //create render mesh
+ //scale down the render model to not intersect the triangles so much
+ auto renderMesh1 = new MeshGenerator::MeshGeneratorRenderMesh(mesh1);
+ Renderable* renderable1 = getSceneController()->getRenderer().createRenderable(*renderMesh1, *getSceneController()->getDefaultMaterial());
+ trackRenderable(renderable1);
+ auto renderMesh2 = new MeshGenerator::MeshGeneratorRenderMesh(mesh2);
+ Renderable* renderable2 = getSceneController()->getRenderer().createRenderable(*renderMesh2, *getSceneController()->getDefaultMaterial());
+ trackRenderable(renderable2);
+
+ // Setup phase configs
+ std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
+ for(int i = 0; i < (int)phases.size(); i++)
+ {
+ phases[i].mPhaseIndex = i;
+ phases[i].mStiffness = 1.0f;
+ phases[i].mStiffnessMultiplier = 1.0f;
+ phases[i].mCompressionLimit = 1.0f;
+ phases[i].mStretchLimit = 1.0f;
+ }
+ mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
+ mClothActor[index]->mCloth->setDragCoefficient(0.1f);
+ mClothActor[index]->mCloth->setLiftCoefficient(0.1f);
+
+ trackClothActor(mClothActor[index]);
+
+ // Add the cloth to the solver for simulation
+ addClothToSolver(mClothActor[index], mSolver);
+}
+
+void ConvexCollisionScene::onInitialize()
+{
+ mSolver = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver);
+
+ initializeCloth(0, physx::PxVec3(0.0f, 0.0f, 0.0f));
+
+ {
+ IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
+ Renderable* plane = getSceneController()->getRenderer().createRenderable(*mesh, *getSceneController()->getDefaultPlaneMaterial());
+ plane->setTransform(PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxPiDivTwo, PxVec3(0.f, 0.f, 1.f))));
+ plane->setScale(PxVec3(1000.f));
+ trackRenderable(plane);
+ }
+}
diff --git a/NvCloth/samples/SampleBase/scene/scenes/ConvexCollisionScene.h b/NvCloth/samples/SampleBase/scene/scenes/ConvexCollisionScene.h
new file mode 100644
index 0000000..7c9d062
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/ConvexCollisionScene.h
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef CONVEX_COLLISION_SCENE_H
+#define CONVEX_COLLISION_SCENE_H
+
+#include "scene/Scene.h"
+#include <foundation/PxVec3.h>
+
+class ConvexCollisionScene : public Scene
+{
+public:
+
+ ConvexCollisionScene(SceneController* sceneController): Scene(sceneController) {}
+
+ void initializeCloth(int index, physx::PxVec3 offset);
+ virtual void onInitialize() override;
+
+private:
+ nv::cloth::Fabric* mFabric[1];
+ nv::cloth::Solver* mSolver;
+ ClothActor* mClothActor[1];
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/scenes/DistanceConstraintScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/DistanceConstraintScene.cpp
new file mode 100644
index 0000000..eaac8e1
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/DistanceConstraintScene.cpp
@@ -0,0 +1,100 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "DistanceConstraintScene.h"
+#include "Scene/SceneController.h"
+#include <NvClothExt/ClothFabricCooker.h>
+#include "ClothMeshGenerator.h"
+#include <NvCloth/Fabric.h>
+#include <NvCloth/Solver.h>
+#include <NvCloth/Cloth.h>
+#include <NvCloth/Factory.h>
+#include "Renderer.h"
+#include "renderer/RenderUtils.h"
+
+DECLARE_SCENE_NAME(DistanceConstraintScene,"Distance Constraint Scene")
+
+void DistanceConstraintScene::onInitialize()
+{
+ ///////////////////////////////////////////////////////////////////////
+ ClothMeshData clothMesh;
+
+ physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f), physx::PxQuat(-0.9f, physx::PxVec3(0.0f, 1.0f, 0.0f)) * physx::PxQuat(PxPiDivFour, physx::PxVec3(1.0f, 0.0f, 0.0f)));
+ clothMesh.GeneratePlaneCloth(6.f, 7.f, 39, 39, false, transform);
+ clothMesh.AttachClothPlaneByAngles(39, 39);
+
+ mClothActor = new ClothActor;
+ nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
+ {
+ mClothActor->mClothRenderMesh = new ClothRenderMesh(meshDesc);
+ mClothActor->mClothRenderable = getSceneController()->getRenderer().createRenderable(*(static_cast<IRenderMesh*>(mClothActor->mClothRenderMesh)), *getSceneController()->getDefaultMaterial());
+ mClothActor->mClothRenderable->setColor(getRandomPastelColor());
+ }
+
+ nv::cloth::Vector<int32_t>::Type phaseTypeInfo;
+ mFabric = NvClothCookFabricFromMesh(getSceneController()->getFactory(), meshDesc, physx::PxVec3(0.0f, -1.0f, 0.0f), &phaseTypeInfo, false);
+ trackFabric(mFabric);
+
+ // Initialize start positions and masses for the actual cloth instance
+ // (note: the particle/vertex positions do not have to match the mesh description here. Set the positions to the initial shape of this cloth instance)
+ std::vector<physx::PxVec4> particlesCopy;
+ particlesCopy.resize(clothMesh.mVertices.size());
+
+ for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ {
+ particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
+ }
+
+ // Create the cloth from the initial positions/masses and the fabric
+ mClothActor->mCloth = getSceneController()->getFactory()->createCloth(nv::cloth::Range<physx::PxVec4>(&particlesCopy[0], &particlesCopy[0] + particlesCopy.size()), *mFabric);
+
+
+ ////////////////////////////////////
+ //// Set distance constraints ////
+ ////////////////////////////////////
+ nv::cloth::Range<physx::PxVec4> distanceConstraints = mClothActor->mCloth->getMotionConstraints();
+ for(int i = 0; i < (int)distanceConstraints.size(); i++)
+ {
+ distanceConstraints[i] = physx::PxVec4(particlesCopy[i].getXYZ(), 0.002f*(i % 800) * 0.002f*(i % 800));
+ }
+
+ particlesCopy.clear(); particlesCopy.shrink_to_fit();
+
+ mClothActor->mCloth->setGravity(physx::PxVec3(0.0f, -9.8f, 0.0f));
+
+ // Setup phase configs
+ std::vector<nv::cloth::PhaseConfig> phases(mFabric->getNumPhases());
+ for(int i = 0; i < (int)phases.size(); i++)
+ {
+ phases[i].mPhaseIndex = i;
+ phases[i].mStiffness = 1.0f;
+ phases[i].mStiffnessMultiplier = 1.0f;
+ phases[i].mCompressionLimit = 1.0f;
+ phases[i].mStretchLimit = 1.0f;
+ }
+ mClothActor->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
+// mClothActor->mCloth->setDragCoefficient(0.1f);
+// mClothActor->mCloth->setDragCoefficient(0.1f);
+
+ mSolver = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver);
+ trackClothActor(mClothActor);
+
+ // Add the cloth to the solver for simulation
+ addClothToSolver(mClothActor, mSolver);
+
+ {
+ IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
+ Renderable* plane = getSceneController()->getRenderer().createRenderable(*mesh, *getSceneController()->getDefaultPlaneMaterial());
+ plane->setTransform(PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxPiDivTwo, PxVec3(0.f, 0.f, 1.f))));
+ plane->setScale(PxVec3(1000.f));
+ trackRenderable(plane);
+ }
+}
diff --git a/NvCloth/samples/SampleBase/scene/scenes/DistanceConstraintScene.h b/NvCloth/samples/SampleBase/scene/scenes/DistanceConstraintScene.h
new file mode 100644
index 0000000..5c61195
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/DistanceConstraintScene.h
@@ -0,0 +1,32 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef DISTANCE_CONSTRAINT_SCENE_H
+#define DISTANCE_CONSTRAINT_SCENE_H
+
+#include "scene/Scene.h"
+
+class DistanceConstraintScene : public Scene
+{
+public:
+
+ DistanceConstraintScene(SceneController* sceneController):Scene(sceneController) {}
+
+ virtual void onInitialize() override;
+
+private:
+ nv::cloth::Fabric* mFabric;
+ nv::cloth::Solver* mSolver;
+ ClothActor* mClothActor;
+
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/scenes/FreeFallScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/FreeFallScene.cpp
index c1f6a00..9cd1121 100644
--- a/NvCloth/samples/SampleBase/scene/scenes/FreeFallScene.cpp
+++ b/NvCloth/samples/SampleBase/scene/scenes/FreeFallScene.cpp
@@ -74,7 +74,7 @@ void FreeFallScene::initializeCloth(int index, physx::PxVec3 offset)
mClothActor[index]->mCloth->setGravity(physx::PxVec3(0.0f, -1.0f, 0.0f));
mClothActor[index]->mCloth->setFriction(0.1);
- mClothActor[index]->mCloth->setDragCoefficient(0.5);
+ mClothActor[index]->mCloth->setDragCoefficient(0.1);
mClothActor[index]->mCloth->setLiftCoefficient(0.0);
// Setup phase configs
@@ -89,8 +89,6 @@ void FreeFallScene::initializeCloth(int index, physx::PxVec3 offset)
}
mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
- mSolver = getSceneController()->getFactory()->createSolver();
- trackSolver(mSolver);
trackClothActor(mClothActor[index]);
// Add the cloth to the solver for simulation
@@ -99,12 +97,12 @@ void FreeFallScene::initializeCloth(int index, physx::PxVec3 offset)
void FreeFallScene::onInitialize()
{
- float spaceX = -1.5f;
+ mSolver = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver);
+ float spaceX = -1.1f;
for(int i = 0; i < 4; ++i)
- {
- initializeCloth(i, physx::PxVec3(16.f + float((i+1)*(i+1)) * spaceX, 2.f, -7.f));
- }
+ initializeCloth(i, physx::PxVec3(8.f + float((i+1)*(i+1)) * spaceX, 2.f, -7.f));
{
IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
diff --git a/NvCloth/samples/SampleBase/scene/scenes/FrictionScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/FrictionScene.cpp
index 3c181ea..3848c6f 100644
--- a/NvCloth/samples/SampleBase/scene/scenes/FrictionScene.cpp
+++ b/NvCloth/samples/SampleBase/scene/scenes/FrictionScene.cpp
@@ -26,8 +26,8 @@ void FrictionScene::initializeCloth(int index, physx::PxVec3 offset, float frict
///////////////////////////////////////////////////////////////////////
ClothMeshData clothMesh;
- physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f)+ offset, PxQuat(PxPi / 6.f, PxVec3(1.f, 0.f, 0.f)));
- clothMesh.GeneratePlaneCloth(3.f, 3.f, 29, 29, false, transform);
+ physx::PxMat44 transform = PxTransform(PxVec3(0.f, 9.f, 0.f) + offset, PxQuat(PxPi / 6.f, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(4.f, 5.f, 29, 34, false, transform);
mClothActor[index] = new ClothActor;
nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
@@ -47,7 +47,7 @@ void FrictionScene::initializeCloth(int index, physx::PxVec3 offset, float frict
particlesCopy.resize(clothMesh.mVertices.size());
physx::PxVec3 clothOffset = transform.getPosition();
- for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ for (int i = 0; i < (int)clothMesh.mVertices.size(); i++)
{
// To put attachment point closer to each other
if(clothMesh.mInvMasses[i] < 1e-6)
@@ -67,7 +67,7 @@ void FrictionScene::initializeCloth(int index, physx::PxVec3 offset, float frict
mClothActor[index]->mCloth->setPlanes(planesR, 0, mClothActor[index]->mCloth->getNumPlanes());
std::vector<uint32_t> indices;
indices.resize(planes.size());
- for(int i = 0; i < (int)indices.size(); i++)
+ for (int i = 0; i < (int)indices.size(); i++)
indices[i] = 1 << i;
nv::cloth::Range<uint32_t> cind(&indices[0], &indices[0] + indices.size());
mClothActor[index]->mCloth->setConvexes(cind, 0, mClothActor[index]->mCloth->getNumConvexes());
@@ -76,7 +76,7 @@ void FrictionScene::initializeCloth(int index, physx::PxVec3 offset, float frict
// Setup phase configs
std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
- for(int i = 0; i < (int)phases.size(); i++)
+ for (int i = 0; i < (int)phases.size(); i++)
{
phases[i].mPhaseIndex = i;
phases[i].mStiffness = 1.0f;
@@ -87,8 +87,6 @@ void FrictionScene::initializeCloth(int index, physx::PxVec3 offset, float frict
mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
mClothActor[index]->mCloth->setFriction(frictionCoef);
- mSolver = getSceneController()->getFactory()->createSolver();
- trackSolver(mSolver);
trackClothActor(mClothActor[index]);
// Add the cloth to the solver for simulation
@@ -97,15 +95,15 @@ void FrictionScene::initializeCloth(int index, physx::PxVec3 offset, float frict
void FrictionScene::onInitialize()
{
-
+ mSolver = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver);
- float spaceX = -4.f;
+ float spaceX = -5.f;
float frictionDelta = 0.2f;
- for(int i = 0; i < 4; ++i)
+ for (int i = 0; i < 5; ++i)
{
- float friction = i > 0 ? float(i) * frictionDelta : 0.f; // 0.0, 0.2, 0.4, 0.6
-
+ float friction = i > 0 ? float(i) * frictionDelta : 0.f; // 0.0, 0.2, 0.4, 0.6, 0.8
initializeCloth(i, physx::PxVec3(4.f + float(i) * spaceX, 4.f, -18.f), friction);
}
diff --git a/NvCloth/samples/SampleBase/scene/scenes/FrictionScene.h b/NvCloth/samples/SampleBase/scene/scenes/FrictionScene.h
index 4173e09..8d03307 100644
--- a/NvCloth/samples/SampleBase/scene/scenes/FrictionScene.h
+++ b/NvCloth/samples/SampleBase/scene/scenes/FrictionScene.h
@@ -24,9 +24,9 @@ public:
virtual void onInitialize() override;
private:
- nv::cloth::Fabric* mFabric[4];
+ nv::cloth::Fabric* mFabric[5];
nv::cloth::Solver* mSolver;
- ClothActor* mClothActor[4];
+ ClothActor* mClothActor[5];
};
diff --git a/NvCloth/samples/SampleBase/scene/scenes/GeodesicScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/GeodesicScene.cpp
new file mode 100644
index 0000000..3216dca
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/GeodesicScene.cpp
@@ -0,0 +1,114 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "GeodesicScene.h"
+#include "Scene/SceneController.h"
+#include <NvClothExt/ClothFabricCooker.h>
+#include "ClothMeshGenerator.h"
+#include <NvCloth/Fabric.h>
+#include <NvCloth/Solver.h>
+#include <NvCloth/Cloth.h>
+#include <NvCloth/Factory.h>
+#include "Renderer.h"
+#include "renderer/RenderUtils.h"
+
+DECLARE_SCENE_NAME(GeodesicScene, "Geodesic Scene")
+
+void GeodesicScene::initializeCloth(int index, physx::PxVec3 offset, bool geodesic)
+{
+ ///////////////////////////////////////////////////////////////////////
+ ClothMeshData clothMesh;
+
+ physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f) + offset, PxQuat(0, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(6.f, 10.0f, 39, 59, false, transform,true,true);
+ clothMesh.AttachClothPlaneByAngles(39, 59);
+
+ /*for(int y = 0; y < 60; y++)
+ {
+ for(int x = 0; x < 40; x++)
+ {
+ //clothMesh.mVertices[x + y * 40].y = transform.transform(PxVec3(0.0f, y&2?0.25f:-0.25f, 0.0f)).y;
+ PxVec3 pos = transform.transform(PxVec3(0.0f, y & 1 ? 0.1f : -0.1f, 10.0f * (float)(y>>2)/(float)60.0f));
+ clothMesh.mVertices[x + y * 40].y = pos.y;
+ clothMesh.mVertices[x + y * 40].z = pos.z;
+ }
+ }*/
+
+ mClothActor[index] = new ClothActor;
+ nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
+ {
+ mClothActor[index]->mClothRenderMesh = new ClothRenderMesh(meshDesc);
+ mClothActor[index]->mClothRenderable = getSceneController()->getRenderer().createRenderable(*(static_cast<IRenderMesh*>(mClothActor[index]->mClothRenderMesh)), *getSceneController()->getDefaultMaterial());
+ mClothActor[index]->mClothRenderable->setColor(getRandomPastelColor());
+ }
+
+ nv::cloth::Vector<int32_t>::Type phaseTypeInfo;
+ mFabric[index] = NvClothCookFabricFromMesh(getSceneController()->getFactory(), meshDesc, physx::PxVec3(0.0f, 0.0f, 1.0f),
+ &phaseTypeInfo, geodesic);
+ trackFabric(mFabric[index]);
+
+ // Initialize start positions and masses for the actual cloth instance
+ // (note: the particle/vertex positions do not have to match the mesh description here. Set the positions to the initial shape of this cloth instance)
+ std::vector<physx::PxVec4> particlesCopy;
+ particlesCopy.resize(clothMesh.mVertices.size());
+
+ physx::PxVec3 clothOffset = transform.getPosition();
+ for (int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ {
+ // To put attachment point closer to each other
+ if(clothMesh.mInvMasses[i] < 1e-6)
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.99f + clothOffset;
+
+ particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
+ }
+
+ // Create the cloth from the initial positions/masses and the fabric
+ mClothActor[index]->mCloth = getSceneController()->getFactory()->createCloth(nv::cloth::Range<physx::PxVec4>(&particlesCopy[0], &particlesCopy[0] + particlesCopy.size()), *mFabric[index]);
+ particlesCopy.clear(); particlesCopy.shrink_to_fit();
+
+ mClothActor[index]->mCloth->setGravity(physx::PxVec3(0.0f, -9.8f, 0.0f));
+ mClothActor[index]->mCloth->setTetherConstraintStiffness(1.0f);
+
+ // Setup phase configs
+ std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
+ for (int i = 0; i < (int)phases.size(); i++)
+ {
+ phases[i].mPhaseIndex = i;
+ phases[i].mStiffness = 1.0f;
+ phases[i].mStiffnessMultiplier = 1.0f;
+ phases[i].mCompressionLimit = 1.0f;
+ phases[i].mStretchLimit = 1.0f;
+ }
+ mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
+
+ trackClothActor(mClothActor[index]);
+
+ // Add the cloth to the solver for simulation
+ addClothToSolver(mClothActor[index], mSolver);
+}
+
+void GeodesicScene::onInitialize()
+{
+ mSolver = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver);
+
+ initializeCloth(0, physx::PxVec3(-5.0f, 0.0f, 0.0f), false);
+ initializeCloth(1, physx::PxVec3(4.0f, 0.0f, 0.0f), true);
+
+ mTime = 0.0f;
+
+ {
+ IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
+ Renderable* plane = getSceneController()->getRenderer().createRenderable(*mesh, *getSceneController()->getDefaultPlaneMaterial());
+ plane->setTransform(PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxPiDivTwo, PxVec3(0.f, 0.f, 1.f))));
+ plane->setScale(PxVec3(1000.f));
+ trackRenderable(plane);
+ }
+}
diff --git a/NvCloth/samples/SampleBase/scene/scenes/GeodesicScene.h b/NvCloth/samples/SampleBase/scene/scenes/GeodesicScene.h
new file mode 100644
index 0000000..3a0822e
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/GeodesicScene.h
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef GEODESIC_SCENE_H
+#define GEODESIC_SCENE_H
+
+#include "scene/Scene.h"
+#include <foundation/PxVec3.h>
+
+class GeodesicScene : public Scene
+{
+public:
+
+ GeodesicScene(SceneController* sceneController): Scene(sceneController) {}
+
+ void initializeCloth(int index, physx::PxVec3 offset, bool geodesic);
+ virtual void onInitialize() override;
+
+private:
+ nv::cloth::Fabric* mFabric[2];
+ nv::cloth::Solver* mSolver;
+ ClothActor* mClothActor[2];
+
+ float mTime;
+
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/scenes/InterCollisionScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/InterCollisionScene.cpp
new file mode 100644
index 0000000..b75facd
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/InterCollisionScene.cpp
@@ -0,0 +1,128 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "InterCollisionScene.h"
+#include "Scene/SceneController.h"
+#include <NvClothExt/ClothFabricCooker.h>
+#include "ClothMeshGenerator.h"
+#include <NvCloth/Fabric.h>
+#include <NvCloth/Solver.h>
+#include <NvCloth/Cloth.h>
+#include <NvCloth/Factory.h>
+#include "Renderer.h"
+#include "renderer/RenderUtils.h"
+
+DECLARE_SCENE_NAME(InterCollisionScene, "Inter Collision Scene")
+
+void InterCollisionScene::initializeCloth(int index, physx::PxMat44 transform)
+{
+ ///////////////////////////////////////////////////////////////////////
+ ClothMeshData clothMesh;
+ float w = 5.f - index;
+ float h = 6.f + index;
+ transform *= PxTransform(PxVec3(0.f, 13.f, 0.f), PxQuat(0, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(w,h, 5*w, 5*h, false, transform);
+ clothMesh.AttachClothPlaneByAngles(5 * w, 5 * h);
+ //clothMesh.SetInvMasses(1.0f / (1000.0f / (5.0f*w*5.0f*h)));
+
+ mClothActor[index] = new ClothActor;
+ nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
+ {
+ mClothActor[index]->mClothRenderMesh = new ClothRenderMesh(meshDesc);
+ mClothActor[index]->mClothRenderable = getSceneController()->getRenderer().createRenderable(*(static_cast<IRenderMesh*>(mClothActor[index]->mClothRenderMesh)), *getSceneController()->getDefaultMaterial());
+ mClothActor[index]->mClothRenderable->setColor(getRandomPastelColor());
+ }
+
+ nv::cloth::Vector<int32_t>::Type phaseTypeInfo;
+ mFabric[index] = NvClothCookFabricFromMesh(getSceneController()->getFactory(), meshDesc, physx::PxVec3(0.0f, 0.0f, 1.0f), &phaseTypeInfo, false);
+ trackFabric(mFabric[index]);
+
+ // Initialize start positions and masses for the actual cloth instance
+ // (note: the particle/vertex positions do not have to match the mesh description here. Set the positions to the initial shape of this cloth instance)
+ std::vector<physx::PxVec4> particlesCopy;
+ particlesCopy.resize(clothMesh.mVertices.size());
+
+ physx::PxVec3 clothOffset = transform.getPosition();
+ for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ {
+ // To put attachment point closer to each other
+ if(clothMesh.mInvMasses[i] < 1e-6)
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.9f + clothOffset;
+
+ particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
+ }
+
+ // Create the cloth from the initial positions/masses and the fabric
+ mClothActor[index]->mCloth = getSceneController()->getFactory()->createCloth(nv::cloth::Range<physx::PxVec4>(&particlesCopy[0], &particlesCopy[0] + particlesCopy.size()), *mFabric[index]);
+ particlesCopy.clear(); particlesCopy.shrink_to_fit();
+
+ std::vector<physx::PxVec4> planes;
+ planes.push_back(physx::PxVec4(physx::PxVec3(0.0f, 1.f, 0.0f), -0.01f));
+
+ nv::cloth::Range<const physx::PxVec4> planesR(&planes[0], &planes[0] + planes.size());
+ mClothActor[index]->mCloth->setPlanes(planesR, 0, mClothActor[index]->mCloth->getNumPlanes());
+ std::vector<uint32_t> indices;
+ indices.resize(planes.size());
+ for(int i = 0; i < (int)indices.size(); i++)
+ indices[i] = 1 << i;
+ nv::cloth::Range<uint32_t> cind(&indices[0], &indices[0] + indices.size());
+ mClothActor[index]->mCloth->setConvexes(cind, 0, mClothActor[index]->mCloth->getNumConvexes());
+
+ mClothActor[index]->mCloth->setGravity(physx::PxVec3(0.0f, -1.0f, 0.0f));
+ mClothActor[index]->mCloth->setFriction(0.1);
+ mClothActor[index]->mCloth->setDragCoefficient(0.1f);
+ mClothActor[index]->mCloth->setLiftCoefficient(0.1f);
+ mClothActor[index]->mCloth->setSolverFrequency(120.0f);
+
+ // Setup phase configs
+ std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
+ for(int i = 0; i < (int)phases.size(); i++)
+ {
+ phases[i].mPhaseIndex = i;
+ phases[i].mStiffness = 1.0f;
+ phases[i].mStiffnessMultiplier = 1.0f;
+ phases[i].mCompressionLimit = 1.0f;
+ phases[i].mStretchLimit = 1.0f;
+ }
+ mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
+
+ trackClothActor(mClothActor[index]);
+
+ // Add the cloth to the solver for simulation
+ addClothToSolver(mClothActor[index], mSolver);
+}
+
+void InterCollisionScene::onInitialize()
+{
+ mSolver = getSceneController()->getFactory()->createSolver();
+ mSolver->setInterCollisionNbIterations(8);
+ mSolver->setInterCollisionDistance(0.4f);
+ mSolver->setInterCollisionStiffness(0.95f);
+ mSolver->setInterCollisionFilter(
+ [](void* a, void* b) {
+ return true;
+ }
+ );
+ trackSolver(mSolver);
+
+ physx::PxMat44 posTrans(physx::PxIdentity);
+ posTrans.setPosition(physx::PxVec3(0.0f, 0.f, -1.0f));
+ initializeCloth(0, posTrans);
+ posTrans.setPosition(physx::PxVec3(0.0f, 0.8f, -1.2f));
+ initializeCloth(1, posTrans);
+
+ {
+ IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
+ Renderable* plane = getSceneController()->getRenderer().createRenderable(*mesh, *getSceneController()->getDefaultPlaneMaterial());
+ plane->setTransform(PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxPiDivTwo, PxVec3(0.f, 0.f, 1.f))));
+ plane->setScale(PxVec3(1000.f));
+ trackRenderable(plane);
+ }
+}
diff --git a/NvCloth/samples/SampleBase/scene/scenes/InterCollisionScene.h b/NvCloth/samples/SampleBase/scene/scenes/InterCollisionScene.h
new file mode 100644
index 0000000..1ef0b45
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/InterCollisionScene.h
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef INTER_COLLISION_SCENE_H
+#define INTER_COLLISION_SCENE_H
+
+#include "scene/Scene.h"
+#include <foundation/PxVec3.h>
+
+class InterCollisionScene : public Scene
+{
+public:
+
+ InterCollisionScene(SceneController* sceneController): Scene(sceneController) {}
+
+ void initializeCloth(int index, physx::PxMat44 transform);
+ virtual void onInitialize() override;
+
+private:
+ nv::cloth::Fabric* mFabric[2];
+ nv::cloth::Solver* mSolver;
+ ClothActor* mClothActor[2];
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/scenes/LocalGlobalScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/LocalGlobalScene.cpp
new file mode 100644
index 0000000..57cd1a2
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/LocalGlobalScene.cpp
@@ -0,0 +1,141 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "LocalGlobalScene.h"
+#include "Scene/SceneController.h"
+#include <NvClothExt/ClothFabricCooker.h>
+#include "ClothMeshGenerator.h"
+#include <NvCloth/Fabric.h>
+#include <NvCloth/Solver.h>
+#include <NvCloth/Cloth.h>
+#include <NvCloth/Factory.h>
+#include "Renderer.h"
+#include "renderer/RenderUtils.h"
+#include "windows.h"
+
+DECLARE_SCENE_NAME(LocalGlobalScene, "Local/Global Scene")
+
+void LocalGlobalScene::Animate(double dt)
+{
+ physx::PxVec3 position(sin(mTime * 2.0f) * 3.0f, sinf(mTime) * 2.0f, cosf(mTime) - 1.0f);
+ physx::PxQuat rotation(sin(mTime * 1.0f) * 4.0f, physx::PxVec3(0.0f, 1.0f, 0.0f));
+
+
+ mTime += dt;
+
+ mClothActor[0]->mCloth->setTranslation(position);
+ mClothActor[0]->mCloth->setRotation(rotation);
+ mClothActor[0]->mClothRenderable->setTransform(physx::PxTransform(position + physx::PxVec3(-4.f, 0.f, 0.f), rotation));
+
+ mClothActor[1]->mClothRenderable->setTransform(physx::PxTransform(physx::PxVec3(4.f, 0.f, 0.f), physx::PxQuat(1.f)));
+ {
+ nv::cloth::MappedRange<physx::PxVec4> particles = mClothActor[1]->mCloth->getCurrentParticles();
+ for (int i = 0; i < 2; i++)
+ {
+ particles[mAttachmentVertices[i]] = physx::PxVec4(physx::PxTransform(position, rotation).transform(mAttachmentVertexOriginalPositions[i].getXYZ()), mAttachmentVertexOriginalPositions[i].w);
+ }
+ }
+ Scene::Animate(dt);
+}
+
+void LocalGlobalScene::initializeCloth(int index, physx::PxVec3 offset)
+{
+ ///////////////////////////////////////////////////////////////////////
+ ClothMeshData clothMesh;
+
+ physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f)+ offset, PxQuat(PxPi / 2.0f, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(5.f, 6.f, 69, 79, false, transform);
+ clothMesh.AttachClothPlaneByAngles(69, 79);
+ clothMesh.SetInvMasses(0.5f + (float)index * 2.0f);
+
+ mClothActor[index] = new ClothActor;
+ nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
+ {
+ mClothActor[index]->mClothRenderMesh = new ClothRenderMesh(meshDesc);
+ mClothActor[index]->mClothRenderable = getSceneController()->getRenderer().createRenderable(*(static_cast<IRenderMesh*>(mClothActor[index]->mClothRenderMesh)), *getSceneController()->getDefaultMaterial());
+
+ float r, g, b;
+ r = index == 0 ? 1.0f : 0.3f;
+ g = index == 1 ? 1.0f : 0.3f;
+ b = index == 2 ? 1.0f : 0.3f;
+
+ mClothActor[index]->mClothRenderable->setColor(DirectX::XMFLOAT4(r, g, b, 1.0f));
+ }
+
+ nv::cloth::Vector<int32_t>::Type phaseTypeInfo;
+ mFabric[index] = NvClothCookFabricFromMesh(getSceneController()->getFactory(), meshDesc, physx::PxVec3(0.0f, 0.0f, 1.0f), &phaseTypeInfo, false);
+ trackFabric(mFabric[index]);
+
+ // Initialize start positions and masses for the actual cloth instance
+ // (note: the particle/vertex positions do not have to match the mesh description here. Set the positions to the initial shape of this cloth instance)
+ std::vector<physx::PxVec4> particlesCopy;
+ particlesCopy.resize(clothMesh.mVertices.size());
+
+ physx::PxVec3 clothOffset = transform.getPosition();
+ for (int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ {
+ // To put attachment point closer to each other
+ if(clothMesh.mInvMasses[i] < 1e-6)
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.95f + clothOffset;
+
+ particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
+ }
+
+ if(index == 1)
+ {
+ mAttachmentVertices[0] = 0;
+ mAttachmentVertices[1] = 69;
+ mAttachmentVertexOriginalPositions[0] = particlesCopy[mAttachmentVertices[0]];
+ mAttachmentVertexOriginalPositions[1] = particlesCopy[mAttachmentVertices[1]];
+ }
+
+ // Create the cloth from the initial positions/masses and the fabric
+ mClothActor[index]->mCloth = getSceneController()->getFactory()->createCloth(nv::cloth::Range<physx::PxVec4>(&particlesCopy[0], &particlesCopy[0] + particlesCopy.size()), *mFabric[index]);
+ particlesCopy.clear(); particlesCopy.shrink_to_fit();
+
+ mClothActor[index]->mCloth->setGravity(physx::PxVec3(0.0f, -9.8f, 0.0f));
+
+ // Setup phase configs
+ std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
+ for (int i = 0; i < (int)phases.size(); i++)
+ {
+ phases[i].mPhaseIndex = i;
+ phases[i].mStiffness = 1.0f;
+ phases[i].mStiffnessMultiplier = 1.0f;
+ phases[i].mCompressionLimit = 1.0f;
+ phases[i].mStretchLimit = 1.0f;
+ }
+ mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
+ mClothActor[index]->mCloth->setDragCoefficient(0.1f);
+ mClothActor[index]->mCloth->setLiftCoefficient(0.2f);
+
+ mSolver[index] = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver[index]);
+ trackClothActor(mClothActor[index]);
+
+ // Add the cloth to the solver for simulation
+ addClothToSolver(mClothActor[index], mSolver[index]);
+}
+
+void LocalGlobalScene::onInitialize()
+{
+ initializeCloth(1, physx::PxVec3(0.0f, 0.0f, 0.0f));
+ initializeCloth(0, physx::PxVec3(0.0f, 0.0f, 0.0f));
+
+ mTime = 0.0f;
+
+ {
+ IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
+ Renderable* plane = getSceneController()->getRenderer().createRenderable(*mesh, *getSceneController()->getDefaultPlaneMaterial());
+ plane->setTransform(PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxPiDivTwo, PxVec3(0.f, 0.f, 1.f))));
+ plane->setScale(PxVec3(1000.f));
+ trackRenderable(plane);
+ }
+}
diff --git a/NvCloth/samples/SampleBase/scene/scenes/LocalGlobalScene.h b/NvCloth/samples/SampleBase/scene/scenes/LocalGlobalScene.h
new file mode 100644
index 0000000..3b2bfa6
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/LocalGlobalScene.h
@@ -0,0 +1,40 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef LOCAL_GLOBAL_SCENE_H
+#define LOCAL_GLOBAL_SCENE_H
+
+#include "scene/Scene.h"
+#include <foundation/PxVec3.h>
+
+class LocalGlobalScene : public Scene
+{
+public:
+
+ LocalGlobalScene(SceneController* sceneController): Scene(sceneController) {}
+
+ virtual void Animate(double dt) override;
+ void initializeCloth(int index, physx::PxVec3 offset);
+ virtual void onInitialize() override;
+
+private:
+ nv::cloth::Fabric* mFabric[2];
+ nv::cloth::Solver* mSolver[2];
+ ClothActor* mClothActor[2];
+
+ int mAttachmentVertices[2];
+ physx::PxVec4 mAttachmentVertexOriginalPositions[2];
+
+ float mTime;
+
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/scenes/MultiSolverScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/MultiSolverScene.cpp
new file mode 100644
index 0000000..d708069
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/MultiSolverScene.cpp
@@ -0,0 +1,131 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "MultiSolverScene.h"
+#include "Scene/SceneController.h"
+#include <NvClothExt/ClothFabricCooker.h>
+#include "ClothMeshGenerator.h"
+#include <NvCloth/Fabric.h>
+#include <NvCloth/Solver.h>
+#include <NvCloth/Cloth.h>
+#include <NvCloth/Factory.h>
+#include "Renderer.h"
+#include "renderer/RenderUtils.h"
+#include "windows.h"
+#include "utils/MeshGenerator.h"
+
+DECLARE_SCENE_NAME(MultiSolverScene, "Multi Solver Scene")
+
+
+void MultiSolverScene::initializeCloth(int index, physx::PxVec3 offset)
+{
+ mSolver[index] = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver[index]);
+
+ ///////////////////////////////////////////////////////////////////////
+ ClothMeshData clothMesh;
+
+ physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f)+ offset, PxQuat(0, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(5.f, 6.f, 69, 79, false, transform);
+ clothMesh.AttachClothPlaneByAngles(69, 79);
+ clothMesh.SetInvMasses(0.5f + (float)index * 2.0f);
+
+ mClothActor[index] = new ClothActor;
+ nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
+ {
+ mClothActor[index]->mClothRenderMesh = new ClothRenderMesh(meshDesc);
+ mClothActor[index]->mClothRenderable = getSceneController()->getRenderer().createRenderable(*(static_cast<IRenderMesh*>(mClothActor[index]->mClothRenderMesh)), *getSceneController()->getDefaultMaterial());
+
+ float r, g, b;
+ r = index == 0 ? 1.0f : 0.3f;
+ g = index == 1 ? 1.0f : 0.3f;
+ b = index == 2 ? 1.0f : 0.3f;
+
+ mClothActor[index]->mClothRenderable->setColor(DirectX::XMFLOAT4(r, g, b, 1.0f));
+ }
+
+ nv::cloth::Vector<int32_t>::Type phaseTypeInfo;
+ mFabric[index] = NvClothCookFabricFromMesh(getSceneController()->getFactory(), meshDesc, physx::PxVec3(0.0f, 0.0f, 1.0f), &phaseTypeInfo, false);
+ trackFabric(mFabric[index]);
+
+ // Initialize start positions and masses for the actual cloth instance
+ // (note: the particle/vertex positions do not have to match the mesh description here. Set the positions to the initial shape of this cloth instance)
+ std::vector<physx::PxVec4> particlesCopy;
+ particlesCopy.resize(clothMesh.mVertices.size());
+
+ physx::PxVec3 clothOffset = transform.getPosition();
+ for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ {
+ // To put attachment point closer to each other
+ if(clothMesh.mInvMasses[i] < 1e-6)
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.95f + clothOffset;
+
+ particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
+ }
+
+ // Create the cloth from the initial positions/masses and the fabric
+ mClothActor[index]->mCloth = getSceneController()->getFactory()->createCloth(nv::cloth::Range<physx::PxVec4>(&particlesCopy[0], &particlesCopy[0] + particlesCopy.size()), *mFabric[index]);
+ particlesCopy.clear(); particlesCopy.shrink_to_fit();
+
+ mClothActor[index]->mCloth->setGravity(physx::PxVec3(0.0f, -9.8f, 0.0f));
+ mClothActor[index]->mCloth->setDamping(physx::PxVec3(0.1f, 0.1f, 0.1f));
+ mClothActor[index]->mCloth->setFriction(0.5f);
+
+
+ physx::PxVec4 spheres[2] = {physx::PxVec4(physx::PxVec3(0.f, 11.f, -2.f) + offset,1.5),
+ physx::PxVec4(physx::PxVec3(0.f, 11.f, 2.f) + offset,1.0)};
+
+ mClothActor[index]->mCloth->setSpheres(nv::cloth::Range<physx::PxVec4>(spheres, spheres + 2), 0, mClothActor[index]->mCloth->getNumSpheres());
+
+ uint32_t caps[4];
+ caps[0] = 0;
+ caps[1] = 1;
+
+ mClothActor[index]->mCloth->setCapsules(nv::cloth::Range<uint32_t>(caps, caps + 2), 0, mClothActor[index]->mCloth->getNumCapsules());
+
+ //create render mesh
+ auto mesh = MeshGenerator::generateCollisionCapsules(spheres,2,caps,2,-0.05f);
+ auto renderMesh = new MeshGenerator::MeshGeneratorRenderMesh(mesh);
+ Renderable* renderable = getSceneController()->getRenderer().createRenderable(*renderMesh, *getSceneController()->getDefaultMaterial());
+ trackRenderable(renderable);
+
+ // Setup phase configs
+ std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
+ for(int i = 0; i < (int)phases.size(); i++)
+ {
+ phases[i].mPhaseIndex = i;
+ phases[i].mStiffness = 1.0f;
+ phases[i].mStiffnessMultiplier = 1.0f;
+ phases[i].mCompressionLimit = 1.0f;
+ phases[i].mStretchLimit = 1.0f;
+ }
+ mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
+ mClothActor[index]->mCloth->setDragCoefficient(0.5f);
+ mClothActor[index]->mCloth->setLiftCoefficient(0.6f);
+
+ trackClothActor(mClothActor[index]);
+
+ // Add the cloth to the solver for simulation
+ addClothToSolver(mClothActor[index], mSolver[index]);
+}
+
+void MultiSolverScene::onInitialize()
+{
+ initializeCloth(0, physx::PxVec3(-5.0f, 0.0f, 0.0f));
+ initializeCloth(0, physx::PxVec3(5.0f, 0.0f, 0.0f));
+
+ {
+ IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
+ Renderable* plane = getSceneController()->getRenderer().createRenderable(*mesh, *getSceneController()->getDefaultPlaneMaterial());
+ plane->setTransform(PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxPiDivTwo, PxVec3(0.f, 0.f, 1.f))));
+ plane->setScale(PxVec3(1000.f));
+ trackRenderable(plane);
+ }
+}
diff --git a/NvCloth/samples/SampleBase/scene/scenes/MultiSolverScene.h b/NvCloth/samples/SampleBase/scene/scenes/MultiSolverScene.h
new file mode 100644
index 0000000..f95c54e
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/MultiSolverScene.h
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef MULTI_SOLVER_SCENE_H
+#define MULTI_SOLVER_SCENE_H
+
+#include "scene/Scene.h"
+#include <foundation/PxVec3.h>
+
+class MultiSolverScene : public Scene
+{
+public:
+
+ MultiSolverScene(SceneController* sceneController): Scene(sceneController) {}
+
+ void initializeCloth(int index, physx::PxVec3 offset);
+ virtual void onInitialize() override;
+
+private:
+ nv::cloth::Fabric* mFabric[1];
+ nv::cloth::Solver* mSolver[2];
+ ClothActor* mClothActor[1];
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/scenes/PlaneCollisionScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/PlaneCollisionScene.cpp
new file mode 100644
index 0000000..fcf4060
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/PlaneCollisionScene.cpp
@@ -0,0 +1,135 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "PlaneCollisionScene.h"
+#include "Scene/SceneController.h"
+#include <NvClothExt/ClothFabricCooker.h>
+#include "ClothMeshGenerator.h"
+#include <NvCloth/Fabric.h>
+#include <NvCloth/Solver.h>
+#include <NvCloth/Cloth.h>
+#include <NvCloth/Factory.h>
+#include "Renderer.h"
+#include "renderer/RenderUtils.h"
+#include "windows.h"
+#include "utils/MeshGenerator.h"
+
+DECLARE_SCENE_NAME(PlaneCollisionScene, "Plane Collision Scene")
+
+
+void PlaneCollisionScene::initializeCloth(int index, physx::PxVec3 offset)
+{
+ ///////////////////////////////////////////////////////////////////////
+ ClothMeshData clothMesh;
+
+ physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f)+ offset, PxQuat(0, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(5.f, 6.f, 59, 69, false, transform);
+ clothMesh.AttachClothPlaneByAngles(59, 69);
+ clothMesh.SetInvMasses(0.5f + (float)index * 2.0f);
+
+ mClothActor[index] = new ClothActor;
+ nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
+ {
+ mClothActor[index]->mClothRenderMesh = new ClothRenderMesh(meshDesc);
+ mClothActor[index]->mClothRenderable = getSceneController()->getRenderer().createRenderable(*(static_cast<IRenderMesh*>(mClothActor[index]->mClothRenderMesh)), *getSceneController()->getDefaultMaterial());
+
+ float r, g, b;
+ r = index == 0 ? 1.0f : 0.3f;
+ g = index == 1 ? 1.0f : 0.3f;
+ b = index == 2 ? 1.0f : 0.3f;
+
+ mClothActor[index]->mClothRenderable->setColor(DirectX::XMFLOAT4(r, g, b, 1.0f));
+ }
+
+ nv::cloth::Vector<int32_t>::Type phaseTypeInfo;
+ mFabric[index] = NvClothCookFabricFromMesh(getSceneController()->getFactory(), meshDesc, physx::PxVec3(0.0f, 0.0f, 1.0f), &phaseTypeInfo, false);
+ trackFabric(mFabric[index]);
+
+ // Initialize start positions and masses for the actual cloth instance
+ // (note: the particle/vertex positions do not have to match the mesh description here. Set the positions to the initial shape of this cloth instance)
+ std::vector<physx::PxVec4> particlesCopy;
+ particlesCopy.resize(clothMesh.mVertices.size());
+
+ physx::PxVec3 clothOffset = transform.getPosition();
+ for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ {
+ // To put attachment point closer to each other
+ if(clothMesh.mInvMasses[i] < 1e-6)
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.95f + clothOffset;
+
+ particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
+ }
+
+ // Create the cloth from the initial positions/masses and the fabric
+ mClothActor[index]->mCloth = getSceneController()->getFactory()->createCloth(nv::cloth::Range<physx::PxVec4>(&particlesCopy[0], &particlesCopy[0] + particlesCopy.size()), *mFabric[index]);
+ particlesCopy.clear(); particlesCopy.shrink_to_fit();
+
+ mClothActor[index]->mCloth->setGravity(physx::PxVec3(0.0f, -9.8f, 0.0f));
+ mClothActor[index]->mCloth->setDamping(physx::PxVec3(0.1f, 0.1f, 0.1f));
+
+ //Generate collision planes
+ std::vector<physx::PxVec4> planes;
+ planes.push_back(physx::PxVec4(physx::PxVec3(-0.5f, 0.4f, 0.0f).getNormalized(), -4.0f));
+ planes.push_back(physx::PxVec4(physx::PxVec3(0.0f, 0.4f, 0.5f).getNormalized(), -4.0f));
+ uint32_t mask = 3;
+ MeshGenerator::Mesh mesh = MeshGenerator::generateCollisionConvex(planes.data(), mask, -0.01f, true);
+
+ //assign as collision data
+ nv::cloth::Range<const physx::PxVec4> planesR(&planes[0], &planes[0] + planes.size());
+ mClothActor[index]->mCloth->setPlanes(planesR, 0, mClothActor[index]->mCloth->getNumPlanes());
+
+ //assign convex indices
+ std::vector<uint32_t> indices;
+ indices.push_back(1);
+ indices.push_back(2);
+ nv::cloth::Range<uint32_t> cind(&indices[0], &indices[0] + indices.size());
+ mClothActor[index]->mCloth->setConvexes(cind, 0, mClothActor[index]->mCloth->getNumConvexes());
+
+ //create render mesh
+ //scale down the render model to not intersect the triangles so much
+ auto renderMesh = new MeshGenerator::MeshGeneratorRenderMesh(mesh);
+ Renderable* renderable = getSceneController()->getRenderer().createRenderable(*renderMesh, *getSceneController()->getDefaultMaterial());
+ trackRenderable(renderable);
+
+ // Setup phase configs
+ std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
+ for(int i = 0; i < (int)phases.size(); i++)
+ {
+ phases[i].mPhaseIndex = i;
+ phases[i].mStiffness = 1.0f;
+ phases[i].mStiffnessMultiplier = 1.0f;
+ phases[i].mCompressionLimit = 1.0f;
+ phases[i].mStretchLimit = 1.0f;
+ }
+ mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
+ mClothActor[index]->mCloth->setDragCoefficient(0.1f);
+ mClothActor[index]->mCloth->setLiftCoefficient(0.1f);
+
+ trackClothActor(mClothActor[index]);
+
+ // Add the cloth to the solver for simulation
+ addClothToSolver(mClothActor[index], mSolver);
+}
+
+void PlaneCollisionScene::onInitialize()
+{
+ mSolver = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver);
+
+ initializeCloth(0, physx::PxVec3(0.0f, 0.0f, 0.0f));
+
+ {
+ IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
+ Renderable* plane = getSceneController()->getRenderer().createRenderable(*mesh, *getSceneController()->getDefaultPlaneMaterial());
+ plane->setTransform(PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxPiDivTwo, PxVec3(0.f, 0.f, 1.f))));
+ plane->setScale(PxVec3(1000.f));
+ trackRenderable(plane);
+ }
+}
diff --git a/NvCloth/samples/SampleBase/scene/scenes/PlaneCollisionScene.h b/NvCloth/samples/SampleBase/scene/scenes/PlaneCollisionScene.h
new file mode 100644
index 0000000..32ff35b
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/PlaneCollisionScene.h
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef PLANE_COLLISION_SCENE_H
+#define PLANE_COLLISION_SCENE_H
+
+#include "scene/Scene.h"
+#include <foundation/PxVec3.h>
+
+class PlaneCollisionScene : public Scene
+{
+public:
+
+ PlaneCollisionScene(SceneController* sceneController): Scene(sceneController) {}
+
+ void initializeCloth(int index, physx::PxVec3 offset);
+ virtual void onInitialize() override;
+
+private:
+ nv::cloth::Fabric* mFabric[1];
+ nv::cloth::Solver* mSolver;
+ ClothActor* mClothActor[1];
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/scenes/SelfCollisionScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/SelfCollisionScene.cpp
new file mode 100644
index 0000000..6a407ea
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/SelfCollisionScene.cpp
@@ -0,0 +1,155 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "SelfCollisionScene.h"
+#include "Scene/SceneController.h"
+#include <NvClothExt/ClothFabricCooker.h>
+#include "ClothMeshGenerator.h"
+#include <NvCloth/Fabric.h>
+#include <NvCloth/Solver.h>
+#include <NvCloth/Cloth.h>
+#include <NvCloth/Factory.h>
+#include "Renderer.h"
+#include "renderer/RenderUtils.h"
+
+DECLARE_SCENE_NAME(SelfCollisionScene, "Self Collision Scene")
+
+void SelfCollisionScene::initializeCloth(int index, physx::PxMat44 transform)
+{
+ ///////////////////////////////////////////////////////////////////////
+
+ float w = 5.f - index;
+ float h = 6.f + index;
+ transform *= PxTransform(PxVec3(0.f, 13.f, 0.f), PxQuat(0, PxVec3(1.f, 0.f, 0.f)));
+ ClothMeshData clothMesh;
+ clothMesh.GeneratePlaneCloth(w, h, 5 * w, 5 * h, false, transform);
+ clothMesh.AttachClothPlaneByAngles(5 * w, 5 * h);
+ clothMesh.SetInvMasses(1.0f / (1000.0f / (5.0f*w*5.0f*h)));
+
+ float w2 = w - 1.0f;
+ float h2 = h + 1.0f;
+ transform *= PxTransform(PxVec3(0.f, 0.8f, -0.2f), PxQuat(0, PxVec3(1.f, 0.f, 0.f)));
+ ClothMeshData clothMesh2;
+ clothMesh2.GeneratePlaneCloth(w2, h2, 5 * w2, 5 * h2, false, transform);
+ clothMesh2.AttachClothPlaneByAngles(5 * w2, 5 * h2);
+ clothMesh2.SetInvMasses(1.0f / (1000.0f / (5.0f*w2*5.0f*h2)));
+ int FirstParticleIndexCloth2 = (int)clothMesh.mVertices.size();
+ clothMesh.Merge(clothMesh2);
+
+ mClothActor[index] = new ClothActor;
+ nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
+ {
+ mClothActor[index]->mClothRenderMesh = new ClothRenderMesh(meshDesc);
+ mClothActor[index]->mClothRenderable = getSceneController()->getRenderer().createRenderable(*(static_cast<IRenderMesh*>(mClothActor[index]->mClothRenderMesh)), *getSceneController()->getDefaultMaterial());
+ mClothActor[index]->mClothRenderable->setColor(getRandomPastelColor());
+ }
+
+ nv::cloth::Vector<int32_t>::Type phaseTypeInfo;
+ mFabric[index] = NvClothCookFabricFromMesh(getSceneController()->getFactory(), meshDesc, physx::PxVec3(0.0f, 0.0f, 1.0f), &phaseTypeInfo, false);
+ trackFabric(mFabric[index]);
+
+ // Initialize start positions and masses for the actual cloth instance
+ // (note: the particle/vertex positions do not have to match the mesh description here. Set the positions to the initial shape of this cloth instance)
+ std::vector<physx::PxVec4> particlesCopy;
+ particlesCopy.resize(clothMesh.mVertices.size());
+
+ physx::PxVec3 clothOffset = transform.getPosition();
+ for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ {
+ // To put attachment point closer to each other
+ if(clothMesh.mInvMasses[i] < 1e-6)
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.9f + clothOffset;
+
+ particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
+ }
+
+ // Create the cloth from the initial positions/masses and the fabric
+ mClothActor[index]->mCloth = getSceneController()->getFactory()->createCloth(nv::cloth::Range<physx::PxVec4>(&particlesCopy[0], &particlesCopy[0] + particlesCopy.size()), *mFabric[index]);
+ particlesCopy.clear(); particlesCopy.shrink_to_fit();
+
+ std::vector<physx::PxVec4> planes;
+ planes.push_back(physx::PxVec4(physx::PxVec3(0.0f, 1.f, 0.0f), -0.01f));
+
+ nv::cloth::Range<const physx::PxVec4> planesR(&planes[0], &planes[0] + planes.size());
+ mClothActor[index]->mCloth->setPlanes(planesR, 0, mClothActor[index]->mCloth->getNumPlanes());
+ std::vector<uint32_t> indices;
+ indices.resize(planes.size());
+ for(int i = 0; i < (int)indices.size(); i++)
+ indices[i] = 1 << i;
+ nv::cloth::Range<uint32_t> cind(&indices[0], &indices[0] + indices.size());
+ mClothActor[index]->mCloth->setConvexes(cind, 0, mClothActor[index]->mCloth->getNumConvexes());
+
+ mClothActor[index]->mCloth->setGravity(physx::PxVec3(0.0f, -1.0f, 0.0f));
+ mClothActor[index]->mCloth->setFriction(0.1);
+ mClothActor[index]->mCloth->setDragCoefficient(0.1f);
+ mClothActor[index]->mCloth->setLiftCoefficient(0.1f);
+ mClothActor[index]->mCloth->setSolverFrequency(120.0f);
+ mClothActor[index]->mCloth->setSelfCollisionDistance(0.26);
+ mClothActor[index]->mCloth->setSelfCollisionStiffness(0.95);
+
+ std::vector<uint32_t> selfCollisionIndices;
+
+ //only enable every other particle for self collision
+ for(int y = 0; y < 5*h + 1; y++)
+ for(int x = 0; x < 5 * w + 1; x++)
+ if((x & 1) ^ (y & 1)) selfCollisionIndices.push_back(x + y*(5 * w + 1));
+
+ for(int y = 0; y < 5 * h2 + 1; y++)
+ for(int x = 0; x < 5 * w2 + 1; x++)
+ if((x & 1) ^ (y & 1)) selfCollisionIndices.push_back(FirstParticleIndexCloth2 + x + y*(5 * w2 + 1));
+
+ nv::cloth::Range<uint32_t> selfCollisionIndicesRange (&selfCollisionIndices[0], &selfCollisionIndices[0] + selfCollisionIndices.size());
+ mClothActor[index]->mCloth->setSelfCollisionIndices(selfCollisionIndicesRange);
+
+ // Setup phase configs
+ std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
+ for(int i = 0; i < (int)phases.size(); i++)
+ {
+ phases[i].mPhaseIndex = i;
+ phases[i].mStiffness = 1.0f;
+ phases[i].mStiffnessMultiplier = 1.0f;
+ phases[i].mCompressionLimit = 1.0f;
+ phases[i].mStretchLimit = 1.0f;
+ }
+ mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
+
+ trackClothActor(mClothActor[index]);
+
+ // Add the cloth to the solver for simulation
+ addClothToSolver(mClothActor[index], mSolver);
+}
+
+void SelfCollisionScene::onInitialize()
+{
+ mSolver = getSceneController()->getFactory()->createSolver();
+ /*mSolver->setInterCollisionNbIterations(8);
+ mSolver->setInterCollisionDistance(0.4f);
+ mSolver->setInterCollisionStiffness(0.95f);
+ mSolver->setInterCollisionFilter(
+ [](void* a, void* b) {
+ return true;
+ }
+ );*/
+ trackSolver(mSolver);
+
+ physx::PxMat44 posTrans(physx::PxIdentity);
+ posTrans.setPosition(physx::PxVec3(0.0f, 0.f, -1.0f));
+ initializeCloth(0, posTrans);
+ //posTrans.setPosition(physx::PxVec3(0.0f, 0.8f, -1.2f));
+ //initializeCloth(1, posTrans);
+
+ {
+ IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
+ Renderable* plane = getSceneController()->getRenderer().createRenderable(*mesh, *getSceneController()->getDefaultPlaneMaterial());
+ plane->setTransform(PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxPiDivTwo, PxVec3(0.f, 0.f, 1.f))));
+ plane->setScale(PxVec3(1000.f));
+ trackRenderable(plane);
+ }
+}
diff --git a/NvCloth/samples/SampleBase/scene/scenes/SelfCollisionScene.h b/NvCloth/samples/SampleBase/scene/scenes/SelfCollisionScene.h
new file mode 100644
index 0000000..0fcdeac
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/SelfCollisionScene.h
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef SELF_COLLISION_SCENE_H
+#define SELF_COLLISION_SCENE_H
+
+#include "scene/Scene.h"
+#include <foundation/PxVec3.h>
+
+class SelfCollisionScene : public Scene
+{
+public:
+
+ SelfCollisionScene(SceneController* sceneController): Scene(sceneController) {}
+
+ void initializeCloth(int index, physx::PxMat44 transform);
+ virtual void onInitialize() override;
+
+private:
+ nv::cloth::Fabric* mFabric[2];
+ nv::cloth::Solver* mSolver;
+ ClothActor* mClothActor[2];
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/scenes/SimpleScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/SimpleScene.cpp
index 68bb96b..b52e2c6 100644
--- a/NvCloth/samples/SampleBase/scene/scenes/SimpleScene.cpp
+++ b/NvCloth/samples/SampleBase/scene/scenes/SimpleScene.cpp
@@ -26,9 +26,9 @@ void SimpleScene::onInitialize()
///////////////////////////////////////////////////////////////////////
ClothMeshData clothMesh;
- physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f), PxQuat(PxPi / 6.f, PxVec3(1.f, 0.f, 0.f)));
- clothMesh.GeneratePlaneCloth(6.f, 7.f, 59, 69, false, transform);
- clothMesh.AttachClothPlaneByAngles(59, 69);
+ physx::PxMat44 transform = PxTransform(PxVec3(-2.f, 13.f, 0.f), PxQuat(PxPi / 6.f, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(6.f, 7.f, 49, 59, false, transform);
+ clothMesh.AttachClothPlaneByAngles(49, 59);
mClothActor = new ClothActor;
nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
@@ -48,11 +48,11 @@ void SimpleScene::onInitialize()
particlesCopy.resize(clothMesh.mVertices.size());
physx::PxVec3 center = transform.transform(physx::PxVec3(0.0f, 0.0f, 0.0f));
- for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ for (int i = 0; i < (int)clothMesh.mVertices.size(); i++)
{
// To put attachment point closer to each other
if(clothMesh.mInvMasses[i] < 1e-6)
- clothMesh.mVertices[i] = (clothMesh.mVertices[i] - center)*0.85f + center;
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - center) * 0.85f + center;
particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
}
@@ -65,7 +65,7 @@ void SimpleScene::onInitialize()
// Setup phase configs
std::vector<nv::cloth::PhaseConfig> phases(mFabric->getNumPhases());
- for(int i = 0; i < (int)phases.size(); i++)
+ for (int i = 0; i < (int)phases.size(); i++)
{
phases[i].mPhaseIndex = i;
phases[i].mStiffness = 1.0f;
@@ -74,8 +74,8 @@ void SimpleScene::onInitialize()
phases[i].mStretchLimit = 1.0f;
}
mClothActor->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
- mClothActor->mCloth->setDragCoefficient(0.5f);
- mClothActor->mCloth->setDragCoefficient(0.5f);
+ mClothActor->mCloth->setDragCoefficient(0.1f);
+ mClothActor->mCloth->setDragCoefficient(0.1f);
mSolver = getSceneController()->getFactory()->createSolver();
trackSolver(mSolver);
diff --git a/NvCloth/samples/SampleBase/scene/scenes/SphereScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/SphereScene.cpp
new file mode 100644
index 0000000..d963011
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/SphereScene.cpp
@@ -0,0 +1,121 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "SphereScene.h"
+#include "Scene/SceneController.h"
+#include <NvClothExt/ClothFabricCooker.h>
+#include "ClothMeshGenerator.h"
+#include <NvCloth/Fabric.h>
+#include <NvCloth/Solver.h>
+#include <NvCloth/Cloth.h>
+#include <NvCloth/Factory.h>
+#include "Renderer.h"
+#include "renderer/RenderUtils.h"
+#include "windows.h"
+
+DECLARE_SCENE_NAME(SphereScene, "Sphere Scene")
+
+
+void SphereScene::initializeCloth(int index, physx::PxVec3 offset)
+{
+ ///////////////////////////////////////////////////////////////////////
+ ClothMeshData clothMesh;
+
+ physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f)+ offset, PxQuat(0, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(5.f, 6.f, 69, 79, false, transform);
+ clothMesh.AttachClothPlaneByAngles(69, 79);
+ clothMesh.SetInvMasses(0.5f + (float)index * 2.0f);
+
+ mClothActor[index] = new ClothActor;
+ nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
+ {
+ mClothActor[index]->mClothRenderMesh = new ClothRenderMesh(meshDesc);
+ mClothActor[index]->mClothRenderable = getSceneController()->getRenderer().createRenderable(*(static_cast<IRenderMesh*>(mClothActor[index]->mClothRenderMesh)), *getSceneController()->getDefaultMaterial());
+
+ float r, g, b;
+ r = index == 0 ? 1.0f : 0.3f;
+ g = index == 1 ? 1.0f : 0.3f;
+ b = index == 2 ? 1.0f : 0.3f;
+
+ mClothActor[index]->mClothRenderable->setColor(DirectX::XMFLOAT4(r, g, b, 1.0f));
+ }
+
+ nv::cloth::Vector<int32_t>::Type phaseTypeInfo;
+ mFabric[index] = NvClothCookFabricFromMesh(getSceneController()->getFactory(), meshDesc, physx::PxVec3(0.0f, 0.0f, 1.0f), &phaseTypeInfo, false);
+ trackFabric(mFabric[index]);
+
+ // Initialize start positions and masses for the actual cloth instance
+ // (note: the particle/vertex positions do not have to match the mesh description here. Set the positions to the initial shape of this cloth instance)
+ std::vector<physx::PxVec4> particlesCopy;
+ particlesCopy.resize(clothMesh.mVertices.size());
+
+ physx::PxVec3 clothOffset = transform.getPosition();
+ for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ {
+ // To put attachment point closer to each other
+ if(clothMesh.mInvMasses[i] < 1e-6)
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.95f + clothOffset;
+
+ particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
+ }
+
+ // Create the cloth from the initial positions/masses and the fabric
+ mClothActor[index]->mCloth = getSceneController()->getFactory()->createCloth(nv::cloth::Range<physx::PxVec4>(&particlesCopy[0], &particlesCopy[0] + particlesCopy.size()), *mFabric[index]);
+ particlesCopy.clear(); particlesCopy.shrink_to_fit();
+
+ mClothActor[index]->mCloth->setGravity(physx::PxVec3(0.0f, -9.8f, 0.0f));
+ mClothActor[index]->mCloth->setDamping(physx::PxVec3(0.1f, 0.1f, 0.1f));
+
+
+ {
+ IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Sphere);
+ Renderable* sphere = getSceneController()->getRenderer().createRenderable(*mesh, *getSceneController()->getDefaultMaterial());
+ sphere->setTransform(PxTransform(PxVec3(0.f, 10.f, -1.f) + offset, PxQuat(PxPiDivTwo, PxVec3(0.f, 0.f, 1.f))));
+ sphere->setScale(PxVec3(1.5f));
+ trackRenderable(sphere);
+ }
+
+ physx::PxVec4 spheres[1] = {physx::PxVec4(physx::PxVec3(0.f, 10.f, -1.f) + offset,1.5)};
+
+ mClothActor[index]->mCloth->setSpheres(nv::cloth::Range<physx::PxVec4>(spheres, spheres + 1), 0, mClothActor[index]->mCloth->getNumSpheres());
+
+ // Setup phase configs
+ std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
+ for(int i = 0; i < (int)phases.size(); i++)
+ {
+ phases[i].mPhaseIndex = i;
+ phases[i].mStiffness = 1.0f;
+ phases[i].mStiffnessMultiplier = 1.0f;
+ phases[i].mCompressionLimit = 1.0f;
+ phases[i].mStretchLimit = 1.0f;
+ }
+ mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
+
+ trackClothActor(mClothActor[index]);
+
+ // Add the cloth to the solver for simulation
+ addClothToSolver(mClothActor[index], mSolver);
+}
+
+void SphereScene::onInitialize()
+{
+ mSolver = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver);
+
+ initializeCloth(0, physx::PxVec3(0.0f, 0.0f, 0.0f));
+
+ {
+ IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
+ Renderable* plane = getSceneController()->getRenderer().createRenderable(*mesh, *getSceneController()->getDefaultPlaneMaterial());
+ plane->setTransform(PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxPiDivTwo, PxVec3(0.f, 0.f, 1.f))));
+ plane->setScale(PxVec3(1000.f));
+ trackRenderable(plane);
+ }
+}
diff --git a/NvCloth/samples/SampleBase/scene/scenes/SphereScene.h b/NvCloth/samples/SampleBase/scene/scenes/SphereScene.h
new file mode 100644
index 0000000..60d7753
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/SphereScene.h
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef SPHERE_SCENE_H
+#define SPHERE_SCENE_H
+
+#include "scene/Scene.h"
+#include <foundation/PxVec3.h>
+
+class SphereScene : public Scene
+{
+public:
+
+ SphereScene(SceneController* sceneController): Scene(sceneController) {}
+
+ void initializeCloth(int index, physx::PxVec3 offset);
+ virtual void onInitialize() override;
+
+private:
+ nv::cloth::Fabric* mFabric[1];
+ nv::cloth::Solver* mSolver;
+ ClothActor* mClothActor[1];
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/scenes/StiffnessPerConstraintScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/StiffnessPerConstraintScene.cpp
new file mode 100644
index 0000000..4ed9daf
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/StiffnessPerConstraintScene.cpp
@@ -0,0 +1,122 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "StiffnessPerConstraintScene.h"
+#include "Scene/SceneController.h"
+#include <NvClothExt/ClothFabricCooker.h>
+#include "ClothMeshGenerator.h"
+#include <NvCloth/Fabric.h>
+#include <NvCloth/Solver.h>
+#include <NvCloth/Cloth.h>
+#include <NvCloth/Factory.h>
+#include "Renderer.h"
+#include "renderer/RenderUtils.h"
+#include "windows.h"
+
+DECLARE_SCENE_NAME(StiffnessPerConstraintScene, "Stiffness per constraint scene")
+
+void StiffnessPerConstraintScene::initializeCloth(int index, physx::PxVec3 offset)
+{
+ ///////////////////////////////////////////////////////////////////////
+ ClothMeshData clothMesh;
+
+ physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f)+ offset, PxQuat(0, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(5.f, 6.25f, 39, 49, false, transform);
+ clothMesh.AttachClothPlaneByAngles(39, 39);
+ clothMesh.SetInvMasses(0.5f + (float)index * 2.0f);
+
+ mClothActor[index] = new ClothActor;
+ nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
+ {
+ meshDesc.pointsStiffness.stride = sizeof(float);
+ meshDesc.pointsStiffness.count = meshDesc.points.count;
+ float* stiffnessValues = new float[meshDesc.pointsStiffness.count];
+ meshDesc.pointsStiffness.data = stiffnessValues;
+ for(int y = 0; y<50; y++)
+ for(int x = 0; x<40; x++)
+ {
+ stiffnessValues[x + y * 40] = ((y) % 8)<5 ? 1.0f : 0.1f;
+ }
+
+ mClothActor[index]->mClothRenderMesh = new ClothRenderMesh(meshDesc);
+ mClothActor[index]->mClothRenderable = getSceneController()->getRenderer().createRenderable(*(static_cast<IRenderMesh*>(mClothActor[index]->mClothRenderMesh)), *getSceneController()->getDefaultMaterial());
+
+ float r, g, b;
+ r = index == 0 ? 1.0f : 0.3f;
+ g = index == 1 ? 1.0f : 0.3f;
+ b = index == 2 ? 1.0f : 0.3f;
+
+ mClothActor[index]->mClothRenderable->setColor(DirectX::XMFLOAT4(r, g, b, 1.0f));
+ }
+
+ nv::cloth::Vector<int32_t>::Type phaseTypeInfo;
+ mFabric[index] = NvClothCookFabricFromMesh(getSceneController()->getFactory(), meshDesc, physx::PxVec3(0.0f, 0.0f, 1.0f), &phaseTypeInfo, false);
+ trackFabric(mFabric[index]);
+
+ // Initialize start positions and masses for the actual cloth instance
+ // (note: the particle/vertex positions do not have to match the mesh description here. Set the positions to the initial shape of this cloth instance)
+ std::vector<physx::PxVec4> particlesCopy;
+ particlesCopy.resize(clothMesh.mVertices.size());
+
+ physx::PxVec3 clothOffset = transform.getPosition();
+ for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ {
+ // To put attachment point closer to each other
+ if(clothMesh.mInvMasses[i] < 1e-6)
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.95f + clothOffset;
+
+ particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
+ }
+
+ // Create the cloth from the initial positions/masses and the fabric
+ mClothActor[index]->mCloth = getSceneController()->getFactory()->createCloth(nv::cloth::Range<physx::PxVec4>(&particlesCopy[0], &particlesCopy[0] + particlesCopy.size()), *mFabric[index]);
+ particlesCopy.clear(); particlesCopy.shrink_to_fit();
+
+ mClothActor[index]->mCloth->setGravity(physx::PxVec3(0.0f, -9.8f, 0.0f));
+ mClothActor[index]->mCloth->setTetherConstraintStiffness(0.1);
+ mClothActor[index]->mCloth->setTetherConstraintScale(1.5f);
+ mClothActor[index]->mCloth->setDragCoefficient(0.1);
+ mClothActor[index]->mCloth->setSolverFrequency(120.0f);
+ mClothActor[index]->mCloth->setDamping(physx::PxVec3(0.1f, 0.1f, 0.1f));
+
+ // Setup phase configs
+ std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
+ for(int i = 0; i < (int)phases.size(); i++)
+ {
+ phases[i].mPhaseIndex = i;
+ phases[i].mStiffness = 1.0f;
+ phases[i].mStiffnessMultiplier = 1.0f;
+ phases[i].mCompressionLimit = 1.0f;
+ phases[i].mStretchLimit = 1.0f;
+ }
+ mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
+ mClothActor[index]->mCloth->setDragCoefficient(0.1f);
+ mClothActor[index]->mCloth->setLiftCoefficient(0.1f);
+
+ trackClothActor(mClothActor[index]);
+
+ // Add the cloth to the solver for simulation
+ addClothToSolver(mClothActor[index], mSolver);
+}
+
+void StiffnessPerConstraintScene::onInitialize()
+{
+ mSolver = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver);
+ initializeCloth(0, physx::PxVec3(0.0f, 0.0f, 0.0f));
+
+ {
+ IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
+ Renderable* plane = getSceneController()->getRenderer().createRenderable(*mesh, *getSceneController()->getDefaultPlaneMaterial());
+ plane->setTransform(PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxPiDivTwo, PxVec3(0.f, 0.f, 1.f))));
+ plane->setScale(PxVec3(1000.f));
+ trackRenderable(plane);
+ }
+}
diff --git a/NvCloth/samples/SampleBase/scene/scenes/StiffnessPerConstraintScene.h b/NvCloth/samples/SampleBase/scene/scenes/StiffnessPerConstraintScene.h
new file mode 100644
index 0000000..bd56a13
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/StiffnessPerConstraintScene.h
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef STIFFNESS_PER_CONSTRAINT_SCENE_H
+#define STIFFNESS_PER_CONSTRAINT_SCENE_H
+
+#include "scene/Scene.h"
+#include <foundation/PxVec3.h>
+
+class StiffnessPerConstraintScene : public Scene
+{
+public:
+
+ StiffnessPerConstraintScene(SceneController* sceneController): Scene(sceneController) {}
+
+ void initializeCloth(int index, physx::PxVec3 offset);
+ virtual void onInitialize() override;
+
+private:
+ nv::cloth::Fabric* mFabric[1];
+ nv::cloth::Solver* mSolver;
+ ClothActor* mClothActor[1];
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/scenes/TetherScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/TetherScene.cpp
index b818d9d..ecd0850 100644
--- a/NvCloth/samples/SampleBase/scene/scenes/TetherScene.cpp
+++ b/NvCloth/samples/SampleBase/scene/scenes/TetherScene.cpp
@@ -23,12 +23,11 @@ DECLARE_SCENE_NAME(TetherScene, "Tether Scene")
void TetherScene::initializeCloth(int index, physx::PxVec3 offset, float tetherStiffness)
{
- ///////////////////////////////////////////////////////////////////////
ClothMeshData clothMesh;
- physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f)+ offset, PxQuat(PxPi / 6.f, PxVec3(1.f, 0.f, 0.f)));
- clothMesh.GeneratePlaneCloth(6.f, 7.5f, 39, 59, false, transform);
- clothMesh.AttachClothPlaneByAngles(39, 59);
+ physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f) + offset, PxQuat(PxPi / 6.f, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(6.f, 7.f, 49, 59, false, transform);
+ clothMesh.AttachClothPlaneByAngles(49, 59);
mClothActor[index] = new ClothActor;
nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
@@ -48,13 +47,13 @@ void TetherScene::initializeCloth(int index, physx::PxVec3 offset, float tetherS
particlesCopy.resize(clothMesh.mVertices.size());
physx::PxVec3 clothOffset = transform.getPosition();
- for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ for (int i = 0; i < (int)clothMesh.mVertices.size(); i++)
{
// To put attachment point closer to each other
if(clothMesh.mInvMasses[i] < 1e-6)
- clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.8f + clothOffset;
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset) * 0.8f + clothOffset;
- particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
+ particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], 0.5f * clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
}
// Create the cloth from the initial positions/masses and the fabric
@@ -66,19 +65,16 @@ void TetherScene::initializeCloth(int index, physx::PxVec3 offset, float tetherS
// Setup phase configs
std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
- for(int i = 0; i < (int)phases.size(); i++)
+ for (int i = 0; i < (int)phases.size(); i++)
{
phases[i].mPhaseIndex = i;
- phases[i].mStiffness = 1.0f;
+ phases[i].mStiffness = 0.75f;
phases[i].mStiffnessMultiplier = 1.0f;
phases[i].mCompressionLimit = 1.0f;
phases[i].mStretchLimit = 1.0f;
}
mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
-
- mSolver = getSceneController()->getFactory()->createSolver();
- trackSolver(mSolver);
trackClothActor(mClothActor[index]);
// Add the cloth to the solver for simulation
@@ -87,9 +83,11 @@ void TetherScene::initializeCloth(int index, physx::PxVec3 offset, float tetherS
void TetherScene::onInitialize()
{
+ mSolver = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver);
- initializeCloth(0,physx::PxVec3(-5.0f,0.0f,0.0f),0);
- initializeCloth(1, physx::PxVec3(4.0f, 0.0f, 0.0f),1);
+ initializeCloth(0,physx::PxVec3(-7.0f, 2.0f, 0.0f), 0.0f);
+ initializeCloth(1, physx::PxVec3(2.0f, 2.0f, 0.0f), 1.0f);
mTime = 0.0f;
diff --git a/NvCloth/samples/SampleBase/scene/scenes/TriangleScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/TriangleScene.cpp
new file mode 100644
index 0000000..1822bb9
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/TriangleScene.cpp
@@ -0,0 +1,131 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "TriangleScene.h"
+#include "Scene/SceneController.h"
+#include <NvClothExt/ClothFabricCooker.h>
+#include "ClothMeshGenerator.h"
+#include <NvCloth/Fabric.h>
+#include <NvCloth/Solver.h>
+#include <NvCloth/Cloth.h>
+#include <NvCloth/Factory.h>
+#include "Renderer.h"
+#include "renderer/RenderUtils.h"
+#include "windows.h"
+#include "utils/MeshGenerator.h"
+
+DECLARE_SCENE_NAME(TriangleScene, "Triangle Scene")
+
+
+void TriangleScene::initializeCloth(int index, physx::PxVec3 offset)
+{
+ ///////////////////////////////////////////////////////////////////////
+ ClothMeshData clothMesh;
+
+ physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f)+ offset, PxQuat(0, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(5.f, 6.f, 39, 44, false, transform);
+ clothMesh.AttachClothPlaneByAngles(39, 44);
+ clothMesh.SetInvMasses(0.5f + (float)index * 2.0f);
+
+ mClothActor[index] = new ClothActor;
+ nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
+ {
+ mClothActor[index]->mClothRenderMesh = new ClothRenderMesh(meshDesc);
+ mClothActor[index]->mClothRenderable = getSceneController()->getRenderer().createRenderable(*(static_cast<IRenderMesh*>(mClothActor[index]->mClothRenderMesh)), *getSceneController()->getDefaultMaterial());
+
+ float r, g, b;
+ r = index == 0 ? 1.0f : 0.3f;
+ g = index == 1 ? 1.0f : 0.3f;
+ b = index == 2 ? 1.0f : 0.3f;
+
+ mClothActor[index]->mClothRenderable->setColor(DirectX::XMFLOAT4(r, g, b, 1.0f));
+ }
+
+ nv::cloth::Vector<int32_t>::Type phaseTypeInfo;
+ mFabric[index] = NvClothCookFabricFromMesh(getSceneController()->getFactory(), meshDesc, physx::PxVec3(0.0f, 0.0f, 1.0f), &phaseTypeInfo, false);
+ trackFabric(mFabric[index]);
+
+ // Initialize start positions and masses for the actual cloth instance
+ // (note: the particle/vertex positions do not have to match the mesh description here. Set the positions to the initial shape of this cloth instance)
+ std::vector<physx::PxVec4> particlesCopy;
+ particlesCopy.resize(clothMesh.mVertices.size());
+
+ physx::PxVec3 clothOffset = transform.getPosition();
+ for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ {
+ // To put attachment point closer to each other
+ if(clothMesh.mInvMasses[i] < 1e-6)
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.95f + clothOffset;
+
+ particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
+ }
+
+ // Create the cloth from the initial positions/masses and the fabric
+ mClothActor[index]->mCloth = getSceneController()->getFactory()->createCloth(nv::cloth::Range<physx::PxVec4>(&particlesCopy[0], &particlesCopy[0] + particlesCopy.size()), *mFabric[index]);
+ particlesCopy.clear(); particlesCopy.shrink_to_fit();
+
+ mClothActor[index]->mCloth->setGravity(physx::PxVec3(0.0f, -9.8f, 0.0f));
+ mClothActor[index]->mCloth->setDamping(physx::PxVec3(0.1f, 0.1f, 0.1f));
+
+ //Generate triangle sphere
+ physx::PxVec3 meshOffset(0.0f, 11.0f, -1.0f);
+ auto mesh = MeshGenerator::generateIcosahedron(1.5f,1);
+ mesh.applyTransfom(physx::PxMat44(physx::PxTransform(meshOffset)));
+
+ //assign as collision data
+ physx::PxVec3* collisionTriangles;
+ int vertexCount = mesh.generateTriangleList(&collisionTriangles);
+ nv::cloth::Range<const physx::PxVec3> trRange(&collisionTriangles[0], &collisionTriangles[0] + vertexCount);
+ mClothActor[index]->mCloth->setTriangles(trRange, 0, 0);
+
+ //create render mesh
+ //scale down the render model to not intersect the triangles so much
+ mesh.applyTransfom( physx::PxMat44(physx::PxTransform(meshOffset))* //redo translation
+ physx::PxMat44(physx::PxVec4(0.97,0.97,0.97,1.0f))* //scale
+ physx::PxMat44(physx::PxTransform(-meshOffset))); //undo translation
+ auto renderMesh = new MeshGenerator::MeshGeneratorRenderMesh(mesh);
+ Renderable* renderable = getSceneController()->getRenderer().createRenderable(*renderMesh, *getSceneController()->getDefaultMaterial());
+ trackRenderable(renderable);
+
+ // Setup phase configs
+ std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
+ for(int i = 0; i < (int)phases.size(); i++)
+ {
+ phases[i].mPhaseIndex = i;
+ phases[i].mStiffness = 1.0f;
+ phases[i].mStiffnessMultiplier = 1.0f;
+ phases[i].mCompressionLimit = 1.0f;
+ phases[i].mStretchLimit = 1.0f;
+ }
+ mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
+ mClothActor[index]->mCloth->setDragCoefficient(0.1f);
+ mClothActor[index]->mCloth->setLiftCoefficient(0.1f);
+
+ trackClothActor(mClothActor[index]);
+
+ // Add the cloth to the solver for simulation
+ addClothToSolver(mClothActor[index], mSolver);
+}
+
+void TriangleScene::onInitialize()
+{
+ mSolver = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver);
+
+ initializeCloth(0, physx::PxVec3(0.0f, 0.0f, 0.0f));
+
+ {
+ IRenderMesh* mesh = getSceneController()->getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
+ Renderable* plane = getSceneController()->getRenderer().createRenderable(*mesh, *getSceneController()->getDefaultPlaneMaterial());
+ plane->setTransform(PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxPiDivTwo, PxVec3(0.f, 0.f, 1.f))));
+ plane->setScale(PxVec3(1000.f));
+ trackRenderable(plane);
+ }
+}
diff --git a/NvCloth/samples/SampleBase/scene/scenes/TriangleScene.h b/NvCloth/samples/SampleBase/scene/scenes/TriangleScene.h
new file mode 100644
index 0000000..35cfefb
--- /dev/null
+++ b/NvCloth/samples/SampleBase/scene/scenes/TriangleScene.h
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef TRIANGLE_SCENE_H
+#define TRIANGLE_SCENE_H
+
+#include "scene/Scene.h"
+#include <foundation/PxVec3.h>
+
+class TriangleScene : public Scene
+{
+public:
+
+ TriangleScene(SceneController* sceneController): Scene(sceneController) {}
+
+ void initializeCloth(int index, physx::PxVec3 offset);
+ virtual void onInitialize() override;
+
+private:
+ nv::cloth::Fabric* mFabric[1];
+ nv::cloth::Solver* mSolver;
+ ClothActor* mClothActor[1];
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/scene/scenes/WindScene.cpp b/NvCloth/samples/SampleBase/scene/scenes/WindScene.cpp
index 51cec1d..232316d 100644
--- a/NvCloth/samples/SampleBase/scene/scenes/WindScene.cpp
+++ b/NvCloth/samples/SampleBase/scene/scenes/WindScene.cpp
@@ -18,6 +18,7 @@
#include <NvCloth/Factory.h>
#include "Renderer.h"
#include "renderer/RenderUtils.h"
+#include "windows.h"
DECLARE_SCENE_NAME(WindScene, "Wind Scene")
@@ -27,17 +28,19 @@ void WindScene::Animate(double dt)
if(mTime > 3.7f)
{
- float dvx = 3.f * cos(25.f * mTime);
- float vy = max(0.f, 0.9f * cos(11.f * mTime));
- float dvz = 1.5f * sin(19.f * mTime);
+ float dvx = 6.0f * sin((1.f + sinf(mTime) * 0.5f) * mTime);
+ float vy = 0;
+ float dvz = 50.0f + 7.0f * sin((9.f + sinf(mTime + 2.0f) * 0.5f) * mTime)
+ + 4.0f * sin((7.f + sinf(mTime * 0.9f) * 0.5f) * mTime);
+
for(int i = 0; i < 3; i++)
{
- physx::PxVec3 wind = physx::PxVec3(2.5f + dvx, vy, 15.f + dvz);
+ physx::PxVec3 wind = physx::PxVec3(dvx, vy, dvz);
mClothActor[i]->mCloth->setWindVelocity(wind);
}
}
- doSimulationStep(dt);
+ Scene::Animate(dt);
}
void WindScene::initializeCloth(int index, physx::PxVec3 offset)
@@ -45,17 +48,23 @@ void WindScene::initializeCloth(int index, physx::PxVec3 offset)
///////////////////////////////////////////////////////////////////////
ClothMeshData clothMesh;
- physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f)+ offset, PxQuat(PxPi / 6.f, PxVec3(1.f, 0.f, 0.f)));
- clothMesh.GeneratePlaneCloth(5.f, 6.f, 49, 59, false, transform);
- clothMesh.AttachClothPlaneByAngles(49, 59);
- clothMesh.SetInvMasses(0.2f + (float)index * 1.4f);
+ physx::PxMat44 transform = PxTransform(PxVec3(0.f, 13.f, 0.f) + offset, PxQuat(PxPi / 2.0f, PxVec3(1.f, 0.f, 0.f)));
+ clothMesh.GeneratePlaneCloth(5.f, 6.f, 69, 79, false, transform);
+ clothMesh.AttachClothPlaneByAngles(69, 79);
+ clothMesh.SetInvMasses(0.5f + (float)index * 2.0f);
mClothActor[index] = new ClothActor;
nv::cloth::ClothMeshDesc meshDesc = clothMesh.GetClothMeshDesc();
{
mClothActor[index]->mClothRenderMesh = new ClothRenderMesh(meshDesc);
mClothActor[index]->mClothRenderable = getSceneController()->getRenderer().createRenderable(*(static_cast<IRenderMesh*>(mClothActor[index]->mClothRenderMesh)), *getSceneController()->getDefaultMaterial());
- mClothActor[index]->mClothRenderable->setColor(getRandomPastelColor());
+
+ float r, g, b;
+ r = index == 0 ? 1.0f : 0.3f;
+ g = index == 1 ? 1.0f : 0.3f;
+ b = index == 2 ? 1.0f : 0.3f;
+
+ mClothActor[index]->mClothRenderable->setColor(DirectX::XMFLOAT4(r, g, b, 1.0f));
}
nv::cloth::Vector<int32_t>::Type phaseTypeInfo;
@@ -68,11 +77,11 @@ void WindScene::initializeCloth(int index, physx::PxVec3 offset)
particlesCopy.resize(clothMesh.mVertices.size());
physx::PxVec3 clothOffset = transform.getPosition();
- for(int i = 0; i < (int)clothMesh.mVertices.size(); i++)
+ for (int i = 0; i < (int)clothMesh.mVertices.size(); i++)
{
// To put attachment point closer to each other
if(clothMesh.mInvMasses[i] < 1e-6)
- clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.9f + clothOffset;
+ clothMesh.mVertices[i] = (clothMesh.mVertices[i] - clothOffset)*0.95f + clothOffset;
particlesCopy[i] = physx::PxVec4(clothMesh.mVertices[i], clothMesh.mInvMasses[i]); // w component is 1/mass, or 0.0f for anchored/fixed particles
}
@@ -85,7 +94,7 @@ void WindScene::initializeCloth(int index, physx::PxVec3 offset)
// Setup phase configs
std::vector<nv::cloth::PhaseConfig> phases(mFabric[index]->getNumPhases());
- for(int i = 0; i < (int)phases.size(); i++)
+ for (int i = 0; i < (int)phases.size(); i++)
{
phases[i].mPhaseIndex = i;
phases[i].mStiffness = 1.0f;
@@ -94,11 +103,9 @@ void WindScene::initializeCloth(int index, physx::PxVec3 offset)
phases[i].mStretchLimit = 1.0f;
}
mClothActor[index]->mCloth->setPhaseConfig(nv::cloth::Range<nv::cloth::PhaseConfig>(&phases.front(), &phases.back()));
- mClothActor[index]->mCloth->setDragCoefficient(0.5f);
- mClothActor[index]->mCloth->setLiftCoefficient(0.6f);
+ mClothActor[index]->mCloth->setDragCoefficient(0.4f);
+ mClothActor[index]->mCloth->setLiftCoefficient(0.25f);
- mSolver = getSceneController()->getFactory()->createSolver();
- trackSolver(mSolver);
trackClothActor(mClothActor[index]);
// Add the cloth to the solver for simulation
@@ -107,10 +114,12 @@ void WindScene::initializeCloth(int index, physx::PxVec3 offset)
void WindScene::onInitialize()
{
+ mSolver = getSceneController()->getFactory()->createSolver();
+ trackSolver(mSolver);
- initializeCloth(2,physx::PxVec3(-9.0f,0.0f,0.0f));
- initializeCloth(1, physx::PxVec3(-2.0f, 0.0f, 0.0f));
- initializeCloth(0, physx::PxVec3(5.0f, 0.0f, 0.0f));
+ initializeCloth(2,physx::PxVec3(-11.0f, 0.0f,0.0f));
+ initializeCloth(1, physx::PxVec3(-4.0f, 0.0f, 0.0f));
+ initializeCloth(0, physx::PxVec3(3.0f, 0.0f, 0.0f));
mTime = 0.0f;
diff --git a/NvCloth/samples/SampleBase/ui/CommonUIController.cpp b/NvCloth/samples/SampleBase/ui/CommonUIController.cpp
index 0c0cac8..63284a2 100644
--- a/NvCloth/samples/SampleBase/ui/CommonUIController.cpp
+++ b/NvCloth/samples/SampleBase/ui/CommonUIController.cpp
@@ -89,12 +89,7 @@ LRESULT CommonUIController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
int iKeyPressed = static_cast<int>(wParam);
switch (iKeyPressed)
{
- case 'P':
- {
- //getPhysXController().setPaused(!getPhysXController().isPaused());
- break;
- }
- case 'O':
+ case 'B':
{
getRenderer().setWireframeMode(!getRenderer().getWireframeMode());
break;
@@ -226,7 +221,7 @@ void CommonUIController::drawUI()
{
// WireFrame
bool wireFrameEnabled = getRenderer().getWireframeMode();
- if (ImGui::Checkbox("WireFrame (O)", &wireFrameEnabled))
+ if (ImGui::Checkbox("WireFrame (B)", &wireFrameEnabled))
{
getRenderer().setWireframeMode(wireFrameEnabled);
}
diff --git a/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp b/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp
index d75bb25..49f9ada 100644
--- a/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp
+++ b/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp
@@ -17,9 +17,8 @@ void ClothMeshData::Clear()
mQuads.clear();
}
-void ClothMeshData::GeneratePlaneCloth(float width, float height, int segmentsX, int segmentsY, bool createQuads, physx::PxMat44 transform, bool alternatingDiagonals)
+void ClothMeshData::GeneratePlaneCloth(float width, float height, int segmentsX, int segmentsY, bool createQuads, physx::PxMat44 transform, bool alternatingDiagonals, int zigzag)
{
-
/*
GeneratePlaneCloth(x,y,2,2) generates:
@@ -61,14 +60,30 @@ GeneratePlaneCloth(x,y,2,2) generates:
{
for(int x = 0; x < segmentsX + 1; x++)
{
- mVertices[x + y * (segmentsX + 1)] = transform.transform(topLeft + physx::PxVec3( ((float)x / (float)segmentsX) * width,
- 0.f,
- ((float)y / (float)segmentsY) * height));
+ physx::PxVec3 pos;
+ switch(zigzag)
+ {
+ case 1:
+ pos = physx::PxVec3(((float)x / (float)segmentsX) * width,
+ sinf(y*0.5)/(float)segmentsY * height,
+ ((float)y / (float)segmentsY) * height);
+ break;
+ case 2:
+ pos = physx::PxVec3(((float)x / (float)segmentsX) * width,
+ ((float)(y&2) / (float)segmentsY) * height,
+ ((float)((y+1)&~1) / (float)segmentsY) * height);
+ default:
+ pos = physx::PxVec3(((float)x / (float)segmentsX) * width,
+ 0.f,
+ ((float)y / (float)segmentsY) * height);
+ }
+
+ mVertices[x + y * (segmentsX + 1)] = transform.transform(topLeft + pos);
+
mInvMasses[x + y * (segmentsX + 1)] = 1.0f;
- mMesh.vertices[x + y * (segmentsX + 1)].position = transform.transform(topLeft + physx::PxVec3(((float)x / (float)segmentsX) * width,
- 0.f,
- ((float)y / (float)segmentsY) * height));
+ mMesh.vertices[x + y * (segmentsX + 1)].position = transform.transform(topLeft + pos);
+
mMesh.vertices[x + y * (segmentsX + 1)].normal = transform.transform(physx::PxVec3(0.f, 1.f, 0.f));
mMesh.vertices[x + y * (segmentsX + 1)].uv = physx::PxVec2(uvOx + uvSx*(float)x / (float)segmentsX, uvOy + uvSy*(1.0f - (float)y / (float)segmentsY));
@@ -190,4 +205,29 @@ nv::cloth::ClothMeshDesc ClothMeshData::GetClothMeshDesc()
SimpleMesh ClothMeshData::GetRenderMesh()
{
return mMesh;
+}
+
+void ClothMeshData::Merge(const ClothMeshData& other)
+{
+ uint32_t firstVertex = (uint32_t)mVertices.size();
+ uint32_t firstTriangle = (uint32_t)mTriangles.size();
+ uint32_t firstQuad = (uint32_t)mQuads.size();
+
+ mVertices.insert(mVertices.end(), other.mVertices.begin(), other.mVertices.end());
+ mUvs.insert(mUvs.end(), other.mUvs.begin(), other.mUvs.end());
+ mInvMasses.insert(mInvMasses.end(), other.mInvMasses.begin(), other.mInvMasses.end());
+
+ mMesh.vertices.insert(mMesh.vertices.end(), mMesh.vertices.begin(), mMesh.vertices.end());
+
+ for(const auto& t : other.mTriangles)
+ {
+ mTriangles.push_back(t + firstVertex);
+ }
+ for(const auto& q : other.mQuads)
+ {
+ mQuads.push_back(q + firstVertex);
+ mMesh.indices.push_back(mQuads.back().a);
+ mMesh.indices.push_back(mQuads.back().b);
+ mMesh.indices.push_back(mQuads.back().c);
+ }
} \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.h b/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.h
index 0f57230..d6cf0fd 100644
--- a/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.h
+++ b/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.h
@@ -24,6 +24,8 @@ struct ClothMeshData
Triangle(uint32_t _a, uint32_t _b, uint32_t _c) :
a(_a), b(_b), c(_c){}
uint32_t a, b, c;
+
+ Triangle operator+(uint32_t offset)const { return Triangle(a + offset, b + offset, c + offset); };
};
struct Quad
{
@@ -31,6 +33,8 @@ struct ClothMeshData
Quad(uint32_t _a, uint32_t _b, uint32_t _c, uint32_t _d) :
a(_a), b(_b), c(_c), d(_d){}
uint32_t a, b, c, d;
+
+ Quad operator+(uint32_t offset)const { return Quad(a + offset, b + offset, c + offset, d + offset); };
};
std::vector<physx::PxVec3> mVertices;
std::vector<physx::PxVec2> mUvs;
@@ -41,7 +45,7 @@ struct ClothMeshData
SimpleMesh mMesh;
void Clear();
- void GeneratePlaneCloth(float width, float height, int segmentsX, int segmentsY, bool createQuads = false, physx::PxMat44 transform = physx::PxIdentity, bool alternatingDiagonals = true);
+ void GeneratePlaneCloth(float width, float height, int segmentsX, int segmentsY, bool createQuads = false, physx::PxMat44 transform = physx::PxIdentity, bool alternatingDiagonals = true, int zigzag = 0);
void AttachClothPlaneByAngles(int segmentsX, int segmentsY, bool attachByWidth = true);
void AttachClothPlaneBySide(int segmentsX, int segmentsY, bool attachByWidth = true);
@@ -51,4 +55,6 @@ struct ClothMeshData
nv::cloth::ClothMeshDesc GetClothMeshDesc();
SimpleMesh GetRenderMesh();
+
+ void Merge(const ClothMeshData& other);
};
diff --git a/NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.cpp b/NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.cpp
new file mode 100644
index 0000000..72e60e8
--- /dev/null
+++ b/NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.cpp
@@ -0,0 +1,21 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "DebugLineRenderBuffer.h"
+
+void DebugLineRenderBuffer::addLine(physx::PxVec3 a, physx::PxVec3 b, unsigned int color)
+{
+ m_lines.push_back(PxDebugLine(a, b, color));
+}
+
+void DebugLineRenderBuffer::addLine(physx::PxMat44 t, physx::PxVec3 a, physx::PxVec3 b, unsigned int color)
+{
+ m_lines.push_back(PxDebugLine(t.transform(a), t.transform(b), color));
+} \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.h b/NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.h
new file mode 100644
index 0000000..ce800d5
--- /dev/null
+++ b/NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.h
@@ -0,0 +1,25 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#pragma once
+#include "DebugRenderBuffer.h"
+#include <foundation/PxVec3.h>
+#include <foundation/PxMat44.h>
+
+class DebugLineRenderBuffer : public DebugRenderBuffer
+{
+public:
+ void clear() { m_lines.clear(); }
+ void addLine(physx::PxVec3 a, physx::PxVec3 b, unsigned int color);
+ void addVector(physx::PxVec3 start, physx::PxVec3 vec, unsigned int color) { addLine(start, start + vec, color); }
+
+ void addLine(physx::PxMat44 t, physx::PxVec3 a, physx::PxVec3 b, unsigned int color);
+ void addVector(physx::PxMat44 t, physx::PxVec3 start, physx::PxVec3 vec, unsigned int color) { addLine(t, start, start + vec, color); }
+}; \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/utils/MeshGenerator.cpp b/NvCloth/samples/SampleBase/utils/MeshGenerator.cpp
new file mode 100644
index 0000000..857daed
--- /dev/null
+++ b/NvCloth/samples/SampleBase/utils/MeshGenerator.cpp
@@ -0,0 +1,545 @@
+
+
+#include "./MeshGenerator.h"
+#include <foundation/PxVec2.h>
+#include <utility>
+#include "utils/Utils.h"
+
+namespace MeshGenerator
+{
+
+void Polygon::triangulate(std::vector<Polygon>& out) const
+{
+ for(int i = 2; i < (int)mPoints.size(); i++)
+ {
+ out.push_back(Polygon(mPoints[0], mPoints[i - 1], mPoints[i]));
+ }
+}
+
+void Polygon::triangulate(std::vector<RenderVertex>& verts, std::vector<uint16_t>& indices) const
+{
+ physx::PxVec3 normal = calculateNormal();
+ for(int i = 2; i < (int)mPoints.size(); i++)
+ {
+ indices.push_back((uint16_t)verts.size());
+ verts.push_back(RenderVertex(mPoints[0].p,normal));
+ indices.push_back((uint16_t)verts.size());
+ verts.push_back(RenderVertex(mPoints[i - 1].p, normal));
+ indices.push_back((uint16_t)verts.size());
+ verts.push_back(RenderVertex(mPoints[i].p, normal));
+ }
+}
+
+void Polygon::triangulateWeld(std::vector<RenderVertex>& verts, std::vector<uint16_t>& indices) const
+{
+ auto addVertex = [&verts, &indices](RenderVertex v)
+ {
+ for(int i = 0; i < (int)verts.size(); i++)
+ {
+ if((verts[i].p - v.p).magnitudeSquared() < 0.001f)
+ {
+ return i;
+ }
+ }
+ verts.push_back(v);
+ return (uint16_t)verts.size()-1;
+ };
+
+ physx::PxVec3 weightedNormal = calculateNormal()*calculateArea();
+
+ for(int i = 2; i < (int)mPoints.size(); i++)
+ {
+ indices.push_back(addVertex(RenderVertex(mPoints[0].p, weightedNormal)));
+ indices.push_back(addVertex(RenderVertex(mPoints[i - 1].p, weightedNormal)));
+ indices.push_back(addVertex(RenderVertex(mPoints[i].p, weightedNormal)));
+ }
+}
+
+void Polygon::triangulateForCollision(std::vector<physx::PxVec3>& verts) const
+{
+ for(int i = 2; i < (int)mPoints.size(); i++)
+ {
+ verts.push_back(mPoints[0].p);
+ verts.push_back(mPoints[i - 1].p);
+ verts.push_back(mPoints[i].p);
+ }
+}
+
+physx::PxVec3 Polygon::calculateNormal() const
+{
+ physx::PxVec3 normal(0.0f, 0.0f, 0.0f);
+ for(int i = 2; i < (int)mPoints.size(); i++)
+ {
+ physx::PxVec3 p[3];
+ p[0] = mPoints[0].p;
+ p[1] = mPoints[i - 1].p;
+ p[2] = mPoints[i].p;
+ normal += (p[1] - p[0]).cross(p[2] - p[0]);
+ }
+ normal.normalize();
+ return normal;
+}
+
+float Polygon::calculateArea() const
+{
+ float doubleArea = 0.0f;
+ for(int i = 2; i < (int)mPoints.size(); i++)
+ {
+ physx::PxVec3 p[3];
+ p[0] = mPoints[0].p;
+ p[1] = mPoints[i - 1].p;
+ p[2] = mPoints[i].p;
+ doubleArea += (p[1] - p[0]).cross(p[2] - p[0]).magnitude();
+ }
+ return doubleArea*0.5f;
+}
+
+void Polygon::subdivideTriangle(std::vector<Polygon>& out) const
+{
+ if(!isTriangle())
+ return;
+
+ for(int i = 0; i < 3; i++)
+ {
+ out.push_back(Polygon(Point(mPoints[i].p), Point(0.5f*(mPoints[(i+1)%3].p + mPoints[i].p)), Point(0.5f*(mPoints[(i + 2) % 3].p + mPoints[i].p))));
+ }
+ out.push_back(Polygon(Point(0.5f*(mPoints[0].p + mPoints[1].p)), Point(0.5f*(mPoints[1].p + mPoints[2].p)), Point(0.5f*(mPoints[2].p + mPoints[0].p))));
+
+}
+
+float intersetcLinePlane(physx::PxVec3 a, physx::PxVec3 b, physx::PxVec4 plane)
+{
+ physx::PxVec3 planeNormal(plane.x, plane.y, plane.z);
+ float aprj = planeNormal.dot(a);
+ float bprj = planeNormal.dot(b);
+
+ return (-plane.w - aprj) / (bprj - aprj);
+}
+
+bool Polygon::pointPlaneSide(physx::PxVec3 p, physx::PxVec4 plane) const
+{
+ physx::PxVec3 planeNormal(plane.x, plane.y, plane.z);
+ return p.dot(planeNormal) + plane.w < 0;
+}
+
+void Polygon::clip(physx::PxVec4 plane, bool flip)
+{
+ if(mPoints.size() < 3)
+ return;
+
+ std::vector<Point> input = mPoints;
+ mPoints.clear();
+
+ Point S = input.back();
+ for(int pointIndex = 0; pointIndex < (int)input.size(); pointIndex++)
+ {
+ if(pointPlaneSide(input[pointIndex].p, plane) != flip)
+ {
+ if(pointPlaneSide(S.p, plane) == flip)
+ {
+ float w = intersetcLinePlane(S.p, input[pointIndex].p, plane);
+ mPoints.push_back(S * (1.0f - w) + input[pointIndex] * w);
+ }
+ mPoints.push_back(input[pointIndex]);
+ }
+ else if(pointPlaneSide(S.p, plane) != flip)
+ {
+ float w = intersetcLinePlane(S.p, input[pointIndex].p, plane);
+ mPoints.push_back(S * (1.0f - w) + input[pointIndex] * w);
+ }
+ S = input[pointIndex];
+ }
+}
+
+void Mesh::addConvexPolygon(physx::PxVec4 plane, physx::PxVec4* planes, uint32_t mask, bool flip)
+{
+ physx::PxVec3 t1, t2, normal;
+ normal.x = plane.x;
+ normal.y = plane.y;
+ normal.z = plane.z;
+ computeBasis(normal, &t1, &t2);
+ Polygon poly;
+ for(int i = 0; i < 4; i++)
+ {
+ float xTable[4] = {-1.0f, 1.0f, 1.0f, -1.0f};
+ float yTable[4] = {-1.0f, -1.0f, 1.0f, 1.0f};
+ poly.mPoints.push_back(normal*-plane.w + 200.0f*t1 * xTable[i] + 200.0f*t2 * yTable[i]);
+ //polyTexcoord.push_back(vec2(0.0f, 10.0f) * xTable[i] + vec2(10.0f, 0.0f) * yTable[i]);
+ }
+
+ for(int i = 0; i < 32; i++)
+ {
+ if((1 << i) & mask)
+ {
+ const physx::PxVec4 pl = planes[i];
+ poly.clip(pl, flip);
+ }
+ }
+
+ mPolygons.push_back(poly);
+}
+
+void Mesh::generateRenderBuffers(RenderVertex** vertices, uint16_t** indices, int* vertexCount, int* indexCount) const
+{
+ std::vector<RenderVertex> verts;
+ std::vector<uint16_t> inds;
+ verts.reserve(mPolygons.size()*3);
+ verts.reserve(inds.size()*3);
+
+ for(auto& p : mPolygons)
+ {
+ p.triangulate(verts, inds);
+ }
+
+ *vertices = new RenderVertex[verts.size()];
+ *indices = new uint16_t[inds.size()];
+
+ memcpy(*vertices, verts.data(), sizeof(RenderVertex)*verts.size());
+ memcpy(*indices, inds.data(), sizeof(uint16_t)*inds.size());
+ *vertexCount = (uint16_t)verts.size();
+ *indexCount = (uint16_t)inds.size();
+}
+
+void Mesh::generateSmoothRenderBuffers(RenderVertex** vertices, uint16_t** indices, int* vertexCount, int* indexCount) const
+{
+ std::vector<RenderVertex> verts;
+ std::vector<uint16_t> inds;
+ verts.reserve(mPolygons.size() * 3);
+ verts.reserve(inds.size() * 3);
+
+ for(auto& p : mPolygons)
+ {
+ p.triangulateWeld(verts, inds);
+ }
+
+ for(auto& v : verts)
+ {
+ v.n.normalize();
+ }
+
+ *vertices = new RenderVertex[verts.size()];
+ *indices = new uint16_t[inds.size()];
+
+ memcpy(*vertices, verts.data(), sizeof(RenderVertex)*verts.size());
+ memcpy(*indices, inds.data(), sizeof(uint16_t)*inds.size());
+ *vertexCount = (uint16_t)verts.size();
+ *indexCount = (uint16_t)inds.size();
+
+}
+
+int Mesh::generateTriangleList(physx::PxVec3** positions)
+{
+ std::vector<physx::PxVec3> verts;
+ verts.reserve(mPolygons.size() * 3);
+
+ for(auto& p : mPolygons)
+ {
+ p.triangulateForCollision(verts);
+ }
+
+ *positions = new physx::PxVec3[verts.size()];
+ memcpy(*positions, verts.data(), sizeof(physx::PxVec3)*verts.size());
+ return (int)verts.size();
+}
+
+void Mesh::applyTransfom(physx::PxMat44 transform)
+{
+ for(auto& trig : mPolygons)
+ for(auto& point : trig.mPoints)
+ {
+ point.p = transform.transform(point.p);
+ }
+}
+
+void Mesh::merge(const Mesh& mesh)
+{
+ mPolygons.insert(mPolygons.end(), mesh.mPolygons.begin(), mesh.mPolygons.end());
+}
+
+Mesh generateTetrahedron(float radius)
+{
+ Mesh mesh;
+ Point p[4];
+ for(int i = 0; i < 3; i++)
+ {
+ p[i] = Point(radius*physx::PxVec3(cosf((float)i / 3.0f*PxTwoPi), -sqrtf(2.0f / 3.0f)*0.5f*sqrtf(3), sinf((float)i / 3.0f*PxTwoPi)));
+ }
+ p[3] = Point(radius*physx::PxVec3(0, sqrtf(2.0f / 3.0f)*0.5f*sqrtf(3), 0));
+
+ mesh.mPolygons.push_back(Polygon(p[0], p[1], p[2]));
+ mesh.mPolygons.push_back(Polygon(p[3], p[1], p[0]));
+ mesh.mPolygons.push_back(Polygon(p[3], p[2], p[1]));
+ mesh.mPolygons.push_back(Polygon(p[3], p[0], p[2]));
+
+ return mesh;
+}
+
+Mesh generateIcosahedron(float radius, int subdivisions)
+{
+ Mesh mesh;
+ Point p[12];
+
+ //generate positions
+ float goldenRatio = (1.0f + sqrtf(5.0f)) * 0.5f;
+ float scale = radius / physx::PxVec2(goldenRatio, 1.0f).magnitude();
+ for(int j = 0; j < 3; j++)
+ for(int i = 0; i < 4; i++)
+ {
+ float signA = i & 1 ? 1.0f : -1.0f;
+ float signB = i & 2 ? -1.0f : 1.0f;
+ physx::PxVec3 point(signA, signB * goldenRatio, 0.0f);
+ p[i + 4 * j] = physx::PxVec3(point[j % 3], point[(j + 1) % 3], point[(j + 2) % 3]) * scale;
+ }
+
+ //generate triangles
+ uint16_t ti[20 * 3] =
+ {
+ 0, 7, 9,
+ 0, 9, 1,
+ 0, 1, 11,
+ 0, 11, 6,
+ 0, 6, 7,
+
+ 1, 9, 5,
+ 9, 7, 8,
+ 7, 6, 2,
+ 6, 11, 10,
+ 11, 1, 4,
+
+ 3, 5, 8,
+ 3, 8, 2,
+ 3, 2, 10,
+ 3, 10, 4,
+ 3, 4, 5,
+
+ 8, 5, 9,
+ 2, 8, 7,
+ 10, 2, 6,
+ 4, 10, 11,
+ 5, 4, 1
+ };
+
+ for(int i = 0; i < 20*3; i += 3)
+ {
+ mesh.mPolygons.push_back(Polygon(p[ti[i]], p[ti[i+1]], p[ti[i+2]]));
+ }
+
+ bool projectToSphere = subdivisions > 0;
+ while(subdivisions > 0)
+ {
+ subdivisions--;
+ Mesh sub;
+ for(auto& trig : mesh.mPolygons)
+ {
+ trig.subdivideTriangle(sub.mPolygons);
+ }
+ std::swap(sub.mPolygons, mesh.mPolygons);
+ }
+
+ if(projectToSphere)
+ {
+ for(auto& trig : mesh.mPolygons)
+ for(auto& point : trig.mPoints)
+ {
+ point.p = point.p.getNormalized() * radius;
+ }
+ }
+
+ return mesh;
+}
+
+Mesh generateCone(physx::PxVec4 a, physx::PxVec4 b, int segments, float grow, bool correctCone)
+{
+ Mesh mesh;
+
+ if(a.w < b.w)
+ std::swap(a, b);
+
+ physx::PxVec3 aCenter = a.getXYZ();
+ physx::PxVec3 bCenter = b.getXYZ();
+ float aRadius = a.w + grow;
+ float bRadius = b.w + grow;
+
+ physx::PxVec3 basis[3];
+ basis[2] = bCenter - aCenter;
+ basis[2].normalize();
+ computeBasis(basis[2], &basis[0], &basis[1]);
+
+ physx::PxVec3 pa = aCenter + aRadius*basis[0];
+ physx::PxVec3 pb = bCenter + bRadius*basis[0];
+ physx::PxVec3 dir = pb - pa;
+
+ physx::PxVec3 n = basis[2].cross(dir);
+ physx::PxVec3 n2 = dir.cross(n);
+ physx::PxVec3 focusPoint = aCenter + ((pa - aCenter).dot(n2)) / basis[2].dot(n2) * basis[2];
+
+ if(correctCone)
+ {
+ {
+ float focusDistance = (focusPoint - aCenter).magnitude();
+ physx::PxVec3 cCenter = (focusPoint + aCenter)*0.5f;
+ float cRadius = focusDistance*0.5f;
+ float d = (aCenter - cCenter).magnitude();
+ float a = (aRadius*aRadius - cRadius*cRadius + d*d) / (2.0f*d);
+ float h = sqrtf(aRadius*aRadius - a*a);
+ physx::PxVec3 P3 = aCenter + a * (cCenter - aCenter) / d;
+
+ aCenter = P3;
+ aRadius = h;
+ }
+
+ {
+ float focusDistance = (focusPoint - bCenter).magnitude();
+ physx::PxVec3 cCenter = (focusPoint + bCenter)*0.5f;
+ float cRadius = focusDistance*0.5f;
+ float d = (bCenter - cCenter).magnitude();
+ float a = (bRadius*bRadius - cRadius*cRadius + d*d) / (2.0f*d);
+ float h = sqrtf(bRadius*bRadius - a*a);
+ physx::PxVec3 P3 = bCenter + a * (cCenter - bCenter) / d;
+
+ bCenter = P3;
+ bRadius = h;
+ }
+ }
+
+
+ for(int i = 0; i < segments; i++)
+ {
+ float angle1 = (float)i / (float)segments*physx::PxTwoPi;
+ float angle2 = (float)(i+1) / (float)segments*physx::PxTwoPi;
+
+ Polygon p;
+ p.addPoints(Point(aCenter + (cosf(angle1)*basis[0] + sinf(angle1)*basis[1])*aRadius));
+ p.addPoints(Point(aCenter + (cosf(angle2)*basis[0] + sinf(angle2)*basis[1])*aRadius));
+ p.addPoints(Point(bCenter + (cosf(angle2)*basis[0] + sinf(angle2)*basis[1])*bRadius));
+ p.addPoints(Point(bCenter + (cosf(angle1)*basis[0] + sinf(angle1)*basis[1])*bRadius));
+
+ mesh.mPolygons.push_back(p);
+ }
+
+ return mesh;
+}
+
+Mesh generateCollisionConvex(physx::PxVec4* planes, uint32_t mask, float grow, bool flip)
+{
+ Mesh mesh;
+ if(grow != 0.0f)
+ {
+ physx::PxVec4* grownPlanes = new physx::PxVec4[32];
+ for(int i = 0; i < 32; i++)
+ {
+ if((1 << i) & mask)
+ {
+ grownPlanes[i] = planes[i];
+ grownPlanes[i].w -= grow;
+ }
+ }
+ planes = grownPlanes;
+ }
+
+ for(int i = 0; i < 32; i++)
+ {
+ if((1 << i) & mask)
+ mesh.addConvexPolygon(planes[i], planes, mask ^ (1 << i), flip);
+ }
+
+ if(grow != 0.0f)
+ delete[] planes;
+
+ return mesh;
+}
+
+Mesh generateCollisionCapsules(physx::PxVec4* spheres, int sphereCount, uint32_t* indices, int indexCount, float grow)
+{
+ Mesh finalMesh;
+ for(int i = 0; i < sphereCount; i++)
+ {
+ Mesh sphere = generateIcosahedron(spheres[i].w+ grow, 4);
+ sphere.applyTransfom(physx::PxTransform(spheres[i].getXYZ()));
+ finalMesh.merge(sphere);
+ }
+
+ for(int i = 0; i < indexCount; i += 2)
+ {
+ finalMesh.merge(generateCone(spheres[indices[i]], spheres[indices[i + 1]], 32, grow, true));
+ }
+
+ return finalMesh;
+}
+
+uint32_t generateConvexPolyhedronPlanes(int segmentsX, int segmentsY, physx::PxVec3 center, float radius, std::vector<physx::PxVec4>* planes)
+{
+ int offset = 0;
+ if(planes)
+ {
+ planes->reserve(planes->size() + segmentsX*segmentsY);
+ offset = (int)planes->size();
+ }
+
+ segmentsY += 1;
+ for(int i = 1; i < segmentsY; i++)
+ {
+ float angleY = (float)i / (float)segmentsY * physx::PxPi + physx::PxPiDivTwo;
+ for(int j = 0; j < segmentsX; j++)
+ {
+ float angleX = (float)j / (float)segmentsX * physx::PxTwoPi;
+
+ physx::PxVec3 nx(cosf(angleX), 0.0f, sinf(angleX));
+ physx::PxVec3 n = cosf(angleY) * nx + sinf(angleY)*physx::PxVec3(0.0f, 1.0f, 0.0f);
+
+ physx::PxVec3 p = n*radius + center;
+
+ if(planes) planes->push_back(constructPlaneFromPointNormal(p, n));
+ }
+ }
+ uint64_t shift = (segmentsX * (segmentsY - 1) + offset);
+ uint64_t excludeMask = (((uint64_t)1 << offset) - 1);
+ uint64_t mask = (((uint64_t)1 << shift) - 1) & ~excludeMask;
+ return static_cast<uint32_t>(mask);
+}
+
+MeshGeneratorRenderMesh::MeshGeneratorRenderMesh(const Mesh mesh)
+{
+ RenderVertex* vertices;
+ uint16_t* indices;
+ int vertexCount, indexCount;
+ mesh.generateRenderBuffers(&vertices, &indices, &vertexCount, &indexCount);
+
+ std::vector<D3D11_INPUT_ELEMENT_DESC> layout;
+ layout.push_back({"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0});
+ layout.push_back({"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0});
+
+ initialize(vertices, (uint32_t)vertexCount, sizeof(RenderVertex), layout, indices, indexCount);
+
+ delete vertices;
+ delete indices;
+}
+MeshGeneratorRenderMesh::~MeshGeneratorRenderMesh()
+{
+
+}
+
+MeshGeneratorRenderMeshSmooth::MeshGeneratorRenderMeshSmooth(const Mesh mesh)
+{
+ RenderVertex* vertices;
+ uint16_t* indices;
+ int vertexCount, indexCount;
+ mesh.generateSmoothRenderBuffers(&vertices, &indices, &vertexCount, &indexCount);
+
+ std::vector<D3D11_INPUT_ELEMENT_DESC> layout;
+ layout.push_back({"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0});
+ layout.push_back({"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0});
+
+ initialize(vertices, (uint32_t)vertexCount, sizeof(RenderVertex), layout, indices, indexCount);
+
+ delete vertices;
+ delete indices;
+}
+MeshGeneratorRenderMeshSmooth::~MeshGeneratorRenderMeshSmooth()
+{
+
+}
+
+
+
+} \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/utils/MeshGenerator.h b/NvCloth/samples/SampleBase/utils/MeshGenerator.h
new file mode 100644
index 0000000..4f4b0c9
--- /dev/null
+++ b/NvCloth/samples/SampleBase/utils/MeshGenerator.h
@@ -0,0 +1,114 @@
+/*
+* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef MESH_GENERATOR_H
+#define MESH_GENERATOR_H
+
+#include <vector>
+#include "renderer/CustomRenderMesh.h"
+#include <foundation/PxVec3.h>
+
+namespace MeshGenerator
+{
+
+struct Point
+{
+ Point(){}
+ Point(physx::PxVec3 _p):p(_p){}
+ physx::PxVec3 p;
+
+ Point operator*(float f) const { return Point(p*f); }
+ Point operator+(Point pt) const { return Point(p+pt.p); }
+};
+
+struct RenderVertex
+{
+ RenderVertex() {}
+ RenderVertex(physx::PxVec3 _p, physx::PxVec3 _n):p(_p),n(_n) {}
+ physx::PxVec3 p;
+ physx::PxVec3 n;
+};
+
+struct Polygon
+{
+ Polygon() {}
+ template<typename P, typename... Args> Polygon(P p1, P p2, P p3, Args... args)
+ {
+ addPoints(p1, p2, p3, args...);
+ }
+
+ std::vector<Point> mPoints;
+
+ bool isTriangle()const { return mPoints.size() == 3; }
+
+ template<typename P, typename... Args> void addPoints(P p, Args... args)
+ {
+ mPoints.push_back(p);
+ addPoints(args...);
+ }
+ template<typename P> void addPoints(P p)
+ {
+ mPoints.push_back(p);
+ }
+
+ void triangulate(std::vector<Polygon>& out) const;
+ void triangulate(std::vector<RenderVertex>& verts, std::vector<uint16_t>& indices) const;
+ void triangulateWeld(std::vector<RenderVertex>& verts, std::vector<uint16_t>& indices) const; //normalize normals afterwards
+ void triangulateForCollision(std::vector<physx::PxVec3>& verts) const;
+ physx::PxVec3 calculateNormal() const;
+ float calculateArea() const;
+ void subdivideTriangle(std::vector<Polygon>& out) const;
+ bool Polygon::pointPlaneSide(physx::PxVec3 p, physx::PxVec4 plane) const;
+ void clip(physx::PxVec4 plane, bool flip = false);
+};
+
+struct Mesh
+{
+ std::vector<Polygon> mPolygons;
+
+ bool isTriangleMesh()const { bool b = true; for(const auto& p : mPolygons) { b = b && p.isTriangle(); } return b; }
+
+ void addConvexPolygon(physx::PxVec4 plane, physx::PxVec4* planes, uint32_t mask, bool flip);
+
+ void generateRenderBuffers(RenderVertex** vertices, uint16_t** indices, int* vertexCount, int* indexCount) const;
+ void generateSmoothRenderBuffers(RenderVertex** vertices, uint16_t** indices, int* vertexCount, int* indexCount) const;
+ int generateTriangleList(physx::PxVec3** positions);
+
+ void applyTransfom(physx::PxMat44 transform);
+
+ void merge(const Mesh& mesh);
+};
+
+Mesh generateTetrahedron(float radius);
+Mesh generateIcosahedron(float radius, int subdivisions);
+Mesh generateCone(physx::PxVec4 a, physx::PxVec4 b, int segments, float grow, bool correctCone);
+Mesh generateCollisionConvex(physx::PxVec4* planes, uint32_t mask, float grow, bool flip);
+Mesh generateCollisionCapsules(physx::PxVec4* spheres, int sphereCount, uint32_t* indices, int indexCount, float grow);
+
+uint32_t generateConvexPolyhedronPlanes(int segmentsX, int segmentsY, physx::PxVec3 center, float radius, std::vector<physx::PxVec4>* planes);
+
+class MeshGeneratorRenderMesh : public CustomRenderMesh
+{
+public:
+ MeshGeneratorRenderMesh(const Mesh mesh);
+ virtual ~MeshGeneratorRenderMesh();
+};
+
+class MeshGeneratorRenderMeshSmooth : public CustomRenderMesh
+{
+public:
+ MeshGeneratorRenderMeshSmooth(const Mesh mesh);
+ virtual ~MeshGeneratorRenderMeshSmooth();
+};
+
+
+};
+
+#endif \ No newline at end of file
diff --git a/NvCloth/samples/SampleBase/utils/Utils.h b/NvCloth/samples/SampleBase/utils/Utils.h
index 5e84e8e..1a5d5ee 100644
--- a/NvCloth/samples/SampleBase/utils/Utils.h
+++ b/NvCloth/samples/SampleBase/utils/Utils.h
@@ -3,6 +3,8 @@
#include <DeviceManager.h>
#include <assert.h>
+#include <foundation/PxVec3.h>
+#include <foundation/PxVec4.h>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -80,8 +82,32 @@ static const char* strext(const char* str)
return ext;
}
+//Math utilities
static inline float lerp(float a, float b, float t) { return a + (b - a) * t; }
+/** returns a PxVec4 containing [x,y,z,d] for plane equation ax + by + cz + d = 0.
+* Where plane contains p and has normal n.
+*/
+inline physx::PxVec4 constructPlaneFromPointNormal(physx::PxVec3 p, physx::PxVec3 n)
+{
+ n.normalize();
+ return physx::PxVec4(n, -p.dot(n));
+}
+
+/** returns two vectors in b and c so that [a b c] form a basis.
+* a needs to be a unit vector.
+*/
+inline void computeBasis(const physx::PxVec3& a, physx::PxVec3* b, physx::PxVec3* c)
+{
+ if(fabsf(a.x) >= 0.57735f)
+ *b = physx::PxVec3(a.y, -a.x, 0.0f);
+ else
+ *b = physx::PxVec3(0.0f, a.z, -a.y);
+
+ *b = b->getNormalized();
+ *c = a.cross(*b);
+}
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////