diff options
| author | Marijn Tamis <[email protected]> | 2017-04-28 14:19:07 +0200 |
|---|---|---|
| committer | Marijn Tamis <[email protected]> | 2017-04-28 14:19:07 +0200 |
| commit | b350eb5f4d44e8448115796144375d79438d74ae (patch) | |
| tree | 8e102e8c28f45a1b87bd335ceee4f33c3d4ee7c2 /NvCloth/samples/SampleBase | |
| parent | Add visual samples. (diff) | |
| download | nvcloth-b350eb5f4d44e8448115796144375d79438d74ae.tar.xz nvcloth-b350eb5f4d44e8448115796144375d79438d74ae.zip | |
NvCloth 1.1.0 Release. (22041545)
Diffstat (limited to 'NvCloth/samples/SampleBase')
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); +} + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |