diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_ClothController.cpp | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_ClothController.cpp')
| -rw-r--r-- | PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_ClothController.cpp | 452 |
1 files changed, 452 insertions, 0 deletions
diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_ClothController.cpp b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_ClothController.cpp new file mode 100644 index 00000000..df86d5f9 --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_ClothController.cpp @@ -0,0 +1,452 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PxPhysXConfig.h" + +#if PX_USE_CLOTH_API + +#include "SampleCharacterCloth.h" + +#include "SampleCharacterClothCameraController.h" +#include "SampleCharacterClothFlag.h" + +#include "TestClothHelpers.h" +#include "SampleCharacterHelpers.h" +#include "characterkinematic/PxCapsuleController.h" +#include "cloth/PxClothParticleData.h" +#include "extensions/PxClothMeshQuadifier.h" + +using namespace PxToolkit; + +#if PX_SUPPORT_GPU_PHYSX +PxClothFlag::Enum gGpuFlag = PxClothFlag::eCUDA; +#elif PX_XBOXONE +PxClothFlag::Enum gGpuFlag = PxClothFlag::eDEFAULT; +#endif + +// size of spheres for stickman (total 30 bones + 1 root) +static const PxReal gSphereRadius[] = { + 2.0f, // root + + // left lower limb + 1.5f, // lhipjoint + 1.5f, // lfemur (upper leg) + 1.0f, // ltibia (lower leg) + 1.0f, // lfoot + 1.0f, // ltoes + + // right lower limb + 1.5f, // rhipjoint + 1.5f, // rfemur + 1.0f, // rtibia + 1.0f, // rfoot + 1.0f, // rtoes + + // spine + 2.5f, // lowerback + 2.5f, // upperback + 2.0f, // thorax + 1.0f, // lowerneck + 1.0f, // upperneck + + 2.0f, // head + + // left arm/hand + 1.5f, // lclavicle (shoulder) + 1.5f, // lhumerus (upper arm) + 1.3f, // lradius (lower arm) + 1.5f, // lwrist + 1.8f, // lhand + 0.5f, // lfingers + 0.5f, // lthumb + + // right arm/hand + 1.5f, // rclavicle + 1.5f, // rhumerus + 1.3f, // rradius + 1.5f, // rwrist + 1.8f, // rhand + 0.5f, // rfingers + 0.5f, // rthumb +}; + +static const PxReal gCharacterScale = 0.1; + +/////////////////////////////////////////////////////////////////////////////// +void +SampleCharacterCloth::createCharacter() +{ + const char* asfpath = getSampleMediaFilename("motion/stickman.asf"); + if (!mCharacter.create(asfpath, gCharacterScale)) + { + fatalError("ERROR - Cannot load motion/stickman.asf\n"); + } + + // add motion clips to the character + const char* amcpath = 0; + + amcpath = getSampleMediaFilename("motion/stickman_walking_01.amc"); + mMotionHandleWalk = mCharacter.addMotion(amcpath); + if (mMotionHandleWalk < 0) + fatalError("ERROR - Cannot load motion/stickman_walking_01.amc\n"); + + amcpath = getSampleMediaFilename("motion/stickman_jump_01.amc"); + mMotionHandleJump = mCharacter.addMotion(amcpath, 100,200); + if (mMotionHandleJump < 0) + fatalError("ERROR - Cannot load motion/stickman_jump_01.amc\n"); + + // initialize character position, scale, and orientation + resetCharacter(); +} + +/////////////////////////////////////////////////////////////////////////////// +void +SampleCharacterCloth::createCape() +{ + PxSceneWriteLock scopedLock(*mScene); + + // compute root transform and positions of all the bones + PxTransform rootPose; + SampleArray<PxVec3> positions; + SampleArray<PxU32> indexPairs; + mCharacter.getFramePose(rootPose, positions, indexPairs); + + // convert bones to collision capsules + SampleArray<PxClothCollisionSphere> spheres; + spheres.resize(positions.size()); + for (PxU32 i = 0; i < positions.size(); i++) + { + spheres[i].pos = positions[i]; + spheres[i].radius = gCharacterScale * gSphereRadius[i]; + } + + // create the cloth cape mesh from file + SampleArray<PxVec4> vertices; + SampleArray<PxU32> primitives; + SampleArray<PxVec2> uvs; + const char* capeFileName = getSampleMediaFilename("ctdm_cape_m.obj"); + PxClothMeshDesc meshDesc = Test::ClothHelpers::createMeshFromObj(capeFileName, + gCharacterScale * 0.3f, PxQuat(PxIdentity), PxVec3(0,-1.5,0), vertices, primitives, uvs); + + for (PxU32 i = 0; i < meshDesc.invMasses.count; i++) + { + ((float*)meshDesc.invMasses.data)[i*4] = 0.5f; + } + + if (!meshDesc.isValid()) fatalError("Could not load ctdm_cape_m.obj\n"); + + for (PxU32 i = 0; i < meshDesc.points.count; i++) + { + if(uvs[i].y > 0.85f) + vertices[i].w = 0.0f; + } + + // create the cloth + PxClothMeshQuadifier quadifier(meshDesc); + mCape = createClothFromMeshDesc(quadifier.getDescriptor(), rootPose, PxVec3(0,-1,0), + uvs.begin(), "dummy_cape_d.bmp", 0.8f); + PxCloth& cloth = *mCape; + + cloth.setCollisionSpheres(spheres.begin(), static_cast<PxU32>(positions.size())); + for(PxU32 i=0; i<indexPairs.size(); i+=2) + cloth.addCollisionCapsule(indexPairs[i], indexPairs[i+1]); + + // compute initial skin binding to the character + mSkin.bindToCharacter(mCharacter, vertices); + + // set solver settings + cloth.setSolverFrequency(240); + + cloth.setStiffnessFrequency(10.0f); + + // damp global particle velocity to 90% every 0.1 seconds + cloth.setDampingCoefficient(PxVec3(0.2f)); // damp local particle velocity + cloth.setLinearDragCoefficient(PxVec3(0.2f)); // transfer frame velocity + cloth.setAngularDragCoefficient(PxVec3(0.2f)); // transfer frame rotation + + // reduce impact of frame acceleration + // x, z: cloth swings out less when walking in a circle + // y: cloth responds less to jump acceleration + cloth.setLinearInertiaScale(PxVec3(0.8f, 0.6f, 0.8f)); + + // leave impact of frame torque at default + cloth.setAngularInertiaScale(PxVec3(1.0f)); + + // reduce centrifugal force of rotating frame + cloth.setCentrifugalInertiaScale(PxVec3(0.3f)); + + const bool useVirtualParticles = true; + const bool useSweptContact = true; + const bool useCustomConfig = true; + + // virtual particles + if (useVirtualParticles) + Test::ClothHelpers::createVirtualParticles(cloth, meshDesc, 4); + + // ccd + cloth.setClothFlag(PxClothFlag::eSWEPT_CONTACT, useSweptContact); + + // use GPU or not +#if PX_SUPPORT_GPU_PHYSX || PX_XBOXONE + cloth.setClothFlag(gGpuFlag, mUseGPU); +#endif + + // custom fiber configuration + if (useCustomConfig) + { + PxClothStretchConfig stretchConfig; + stretchConfig.stiffness = 1.0f; + + cloth.setStretchConfig(PxClothFabricPhaseType::eVERTICAL, PxClothStretchConfig(1.0f)); + cloth.setStretchConfig(PxClothFabricPhaseType::eVERTICAL, PxClothStretchConfig(1.0f)); + cloth.setStretchConfig(PxClothFabricPhaseType::eSHEARING, PxClothStretchConfig(0.75f)); + cloth.setStretchConfig(PxClothFabricPhaseType::eBENDING, PxClothStretchConfig(0.5f)); + cloth.setTetherConfig(PxClothTetherConfig(1.0f)); + } +} + +/////////////////////////////////////////////////////////////////////////////// +void +SampleCharacterCloth::createFlags() +{ + PxSceneWriteLock scopedLock(*mScene); + + PxQuat q = PxQuat(PxIdentity); + + PxU32 numFlagRow = 2; + PxU32 resX = 20, resY = 10; + if (mClothFlagCountIndex == 0) + { + numFlagRow = 2; + resX = 20; + resY = 10; + } + else if (mClothFlagCountIndex == 1) + { + numFlagRow = 4; + resX = 30; + resY = 15; + } + else if (mClothFlagCountIndex == 2) + { + numFlagRow = 8; + resX = 50; + resY = 25; + } + else if (mClothFlagCountIndex == 3) + { + numFlagRow = 15; + resX = 50; + resY = 25; + } + + for (PxU32 i = 0; i < numFlagRow; i++) + { + mFlags.pushBack(new SampleCharacterClothFlag(*this, PxTransform(PxVec3(-4,0,-10.0f -5.0f * i), q), resX, resY, 2.0f, 1.0f, 5.0f)); + mFlags.pushBack(new SampleCharacterClothFlag(*this, PxTransform(PxVec3(4,0,-10.0f -5.0f * i), q), resX, resY, 2.0f, 1.0f, 5.0f)); + } + +#if PX_SUPPORT_GPU_PHYSX || PX_XBOXONE + for (PxU32 i = 0; i < mFlags.size(); ++i) + mFlags[i]->getCloth()->setClothFlag(gGpuFlag, mUseGPU); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +void +SampleCharacterCloth::releaseFlags() +{ + PxSceneWriteLock scopedLock(*mScene); + + const size_t nbFlags = mFlags.size(); + for(PxU32 i = 0;i < nbFlags;i++) + mFlags[i]->release(); + mFlags.clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +void +SampleCharacterCloth::resetCape() +{ + PxSceneWriteLock scopedLock(*mScene); + + PxCloth& cloth = *mCape; + + // compute cloth pose and collider positions + PxTransform rootPose; + SampleArray<PxVec3> positions; + SampleArray<PxU32> indexPairs; + mCharacter.getFramePose(rootPose, positions, indexPairs); + + // set cloth pose and zero velocity/acceleration + cloth.setGlobalPose(rootPose); + + // set collision sphere positions + SampleArray<PxClothCollisionSphere> spheres(positions.size()); + cloth.getCollisionData(spheres.begin(), 0, 0, 0, 0); + for (PxU32 i = 0; i < positions.size(); i++) + spheres[i].pos = positions[i]; + cloth.setCollisionSpheres(spheres.begin(), spheres.size()); + + // set positions for constrained particles + SampleArray<PxVec3> particlePositions; + mSkin.computeNewPositions(mCharacter, particlePositions); + Test::ClothHelpers::setParticlePositions(cloth, particlePositions, false, false); + + cloth.setExternalAcceleration(PxVec3(0.0f)); + + // clear previous state of collision shapes etc. + cloth.clearInterpolation(); +} + +/////////////////////////////////////////////////////////////////////////////// +void +SampleCharacterCloth::resetCharacter() +{ + // compute global pose and local positions + PxExtendedVec3 posExt = mController->getPosition(); + PxVec3 pos = PxVec3(PxReal(posExt.x), PxReal(posExt.y), PxReal(posExt.z)) - PxVec3(0.0f, 1.5, 0.0f); + + PxTransform pose; + pose.p = pos; + pose.q = PxQuat(PxIdentity); + + mCharacter.resetMotion(37.0f); + mCharacter.setGlobalPose(pose); + mCharacter.setTargetPosition(PxVec3(pos.x, pos.y, pos.z)); + mCharacter.setMotion(mMotionHandleWalk, true); + mCharacter.move(1.0f, false, mCCTActive); + mCharacter.faceToward(PxVec3(0,0,-1)); + + mJump.reset(); + + mCCTDisplacementPrevStep = PxVec3(0.0f); +} + + +/////////////////////////////////////////////////////////////////////////////// +void +SampleCharacterCloth::updateCape(float dtime) +{ + PxSceneWriteLock scopedLock(*mScene); + + PxCloth& cloth = *mCape; + + // compute cloth pose and collider positions + PxTransform rootPose; + SampleArray<PxVec3> spherePositions; + SampleArray<PxU32> indexPairs; + mCharacter.getFramePose(rootPose, spherePositions, indexPairs); + + // set cloth pose + cloth.setTargetPose(rootPose); + + // set collision sphere positions + SampleArray<PxClothCollisionSphere> spheres(spherePositions.size()); + cloth.getCollisionData(spheres.begin(), 0, 0, 0, 0); + for (PxU32 i = 0; i < spherePositions.size(); i++) + spheres[i].pos = spherePositions[i]; + cloth.setCollisionSpheres(spheres.begin(), spheres.size()); + + // set positions for constrained particles + SampleArray<PxVec3> particlePositions; + mSkin.computeNewPositions(mCharacter, particlePositions); + + Test::ClothHelpers::setParticlePositions(cloth, particlePositions, true, true); + + // add wind while in freefall + if (mJump.isInFreefall()) + { + PxReal strength = 20.0f; + PxVec3 offset( PxReal(PxToolkit::Rand(-1,1)), 1.0f + PxReal(PxToolkit::Rand(-1,1)), PxReal(PxToolkit::Rand(-1,1))); + PxVec3 windAcceleration = strength * offset; + cloth.setExternalAcceleration(windAcceleration); + } +} + +/////////////////////////////////////////////////////////////////////////////// +void +SampleCharacterCloth::updateCharacter(float dtime) +{ + // compute global pose of the character from CCT + PxExtendedVec3 posExt = mController->getPosition(); + PxVec3 offset(0.0f, gCharacterScale * 15.0f, 0.0f); // offset from controller center to the foot + PxVec3 pos = PxVec3(PxReal(posExt.x), PxReal(posExt.y), PxReal(posExt.z)) - offset; + + // update character pose and motion + if (mJump.isJumping() == true) + { + mCharacter.setTargetPosition(pos); + mCharacter.setMotion(mMotionHandleJump); + mCharacter.move(0.25f, true); + } + else + { + bool cctActive = mCCTActive && (mJump.isInFreefall() == false); + + mCharacter.setTargetPosition(pos); + mCharacter.setMotion(mMotionHandleWalk); + mCharacter.move(1.0f, false, cctActive); + } +} + +/////////////////////////////////////////////////////////////////////////////// +void +SampleCharacterCloth::updateFlags(float dtime) +{ + PxSceneWriteLock scopedLock(*mScene); + + // apply wind force to flags + for (PxU32 i = 0 ; i < mFlags.size(); i++) + { + mFlags[i]->setWind(PxVec3(1,0.1,0), 40.0f, PxVec3(0.0f, 10.0f, 10.0f)); + mFlags[i]->update(dtime); + } +} + +#if PX_SUPPORT_GPU_PHYSX || PX_XBOXONE +/////////////////////////////////////////////////////////////////////////////// +void +SampleCharacterCloth::toggleGPU() +{ + PxSceneWriteLock scopedLock(*mScene); + + mUseGPU = !mUseGPU; + + if (mCape) + mCape->setClothFlag(gGpuFlag, mUseGPU); + + for (PxU32 i = 0 ; i < mFlags.size(); i++) + { + mFlags[i]->getCloth()->setClothFlag(gGpuFlag, mUseGPU); + } +} +#endif + +#endif // PX_USE_CLOTH_API |