diff options
Diffstat (limited to 'PhysX_3.4/Samples/SampleCharacterCloth')
17 files changed, 2830 insertions, 0 deletions
diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth.h b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth.h new file mode 100644 index 00000000..95e33d41 --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth.h @@ -0,0 +1,189 @@ +// 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. + +#ifndef SAMPLE_CHARACTER_CLOTH_H +#define SAMPLE_CHARACTER_CLOTH_H + +#include "PhysXSample.h" +#include "PxSimulationEventCallback.h" +#include "characterkinematic/PxController.h" +#include "characterkinematic/PxControllerBehavior.h" +#include "PxShape.h" + +#include "SampleCharacterHelpers.h" +#include "SampleCharacterClothJump.h" +#include "SampleCharacterClothPlatform.h" + +namespace physx +{ + class PxCapsuleController; + class PxControllerManager; +} + + class SampleCharacterClothFlag; + class SampleCharacterClothCameraController; + class ControlledActor; + + class SampleCharacterCloth : public PhysXSample, public PxUserControllerHitReport, public PxControllerBehaviorCallback + { + public: + SampleCharacterCloth(PhysXSampleApplication& app); + virtual ~SampleCharacterCloth(); + + /////////////////////////////////////////////////////////////////////////////// + + // Implements SampleApplication + virtual void onInit(); + virtual void onInit(bool restart) { onInit(); } + virtual void onShutdown(); + virtual void onSubstep(float dtime); + virtual void onTickPreRender(float dtime); + virtual void onTickPostRender(float dtime); + virtual void onPointerInputEvent(const SampleFramework::InputEvent& ie, physx::PxU32 x, physx::PxU32 y, physx::PxReal dx, physx::PxReal dy, bool val); + virtual void onDigitalInputEvent(const SampleFramework::InputEvent& , bool val); + + /////////////////////////////////////////////////////////////////////////////// + + // Implements PhysXSampleApplication + virtual void helpRender(PxU32 x, PxU32 y, PxU8 textAlpha); + virtual void descriptionRender(PxU32 x, PxU32 y, PxU8 textAlpha); + virtual void customizeRender(); + virtual void customizeSample(SampleSetup&); + virtual void customizeSceneDesc(PxSceneDesc&); + virtual void collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents); + + /////////////////////////////////////////////////////////////////////////////// + + // Implements PxUserControllerHitReport + virtual void onShapeHit(const PxControllerShapeHit& hit); + virtual void onControllerHit(const PxControllersHit& hit); + virtual void onObstacleHit(const PxControllerObstacleHit& hit); + + // Implements PxControllerBehaviorCallback + virtual PxControllerBehaviorFlags getBehaviorFlags(const PxShape&, const PxActor&); + virtual PxControllerBehaviorFlags getBehaviorFlags(const PxController&); + virtual PxControllerBehaviorFlags getBehaviorFlags(const PxObstacle&); + + /////////////////////////////////////////////////////////////////////////////// + protected: + // non-dynamic environment + PxRigidStatic* buildHeightField(); + void createLandscape(PxReal* heightmap, PxU32 size, PxReal scale, PxReal* outVerts, PxReal* outNorms, PxU32* outTris); + PxRigidStatic* createHeightField(PxReal* heightmap, PxReal scale, PxU32 size); + SampleCharacterClothPlatform* createPlatform(const PxTransform &pose, const PxGeometry &geom, PxReal travelTime, const PxVec3 &offset, RenderMaterial *renderMaterial); + void createPlatforms(); + void updatePlatforms(float dtime); + + // cct control + void bufferCCTMotion(const PxVec3& disp, PxReal dtime); + void createCCTController(); + void updateCCT(float dtime); + + // cloth and character + void createCharacter(); + void createCape(); + void createFlags(); + void releaseFlags(); + + void resetCape(); + void resetCharacter(); + void resetScene(); + + void updateCape(float dtime); + void updateCharacter(float dtime); + void updateFlags(float dtime); + + void createRenderMaterials(); +#if PX_SUPPORT_GPU_PHYSX || PX_XBOXONE + void toggleGPU(); +#endif + + private: + /////////////////////////////////////////////////////////////////////////////// + // Landscape + PxTransform mHFPose; + PxU32 mNbVerts; + PxU32 mNbTris; + PxReal* mVerts; + PxU32* mTris; + + /////////////////////////////////////////////////////////////////////////////// + // Camera and Controller + SampleCharacterClothCameraController* mCCTCamera; + PxCapsuleController* mController; + PxControllerManager* mControllerManager; + PxVec3 mControllerInitialPosition; + bool mCCTActive; + PxVec3 mCCTDisplacement; + PxVec3 mCCTDisplacementPrevStep; + PxReal mCCTTimeStep; + SampleCharacterClothJump mJump; + + /////////////////////////////////////////////////////////////////////////////// + // rendering + RenderMaterial* mSnowMaterial; + RenderMaterial* mPlatformMaterial; + RenderMaterial* mRockMaterial; + RenderMaterial* mWoodMaterial; + RenderMaterial* mFlagMaterial; + + /////////////////////////////////////////////////////////////////////////////// + // cloth + PxCloth* mCape; + SampleArray<SampleCharacterClothFlag*> mFlags; +#if PX_SUPPORT_GPU_PHYSX || PX_XBOXONE + bool mUseGPU; +#endif + PxU32 mClothFlagCountIndex; + PxU32 mClothFlagCountIndexMax; + + /////////////////////////////////////////////////////////////////////////////// + // character motion + Character mCharacter; + Skin mSkin; + int mMotionHandleWalk; + int mMotionHandleRun; + int mMotionHandleJump; + + /////////////////////////////////////////////////////////////////////////////// + // simulation stats + shdfnd::Time mTimer; + PxReal mAccumulatedSimulationTime; + PxReal mAverageSimulationTime; + PxU32 mFrameCount; + + /////////////////////////////////////////////////////////////////////////////// + // platform levels + SampleArray<SampleCharacterClothPlatform*> mPlatforms; + + friend class SampleCharacterClothCameraController; + friend class SampleCharacterClothFlag; + }; + +#endif diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothCameraController.cpp b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothCameraController.cpp new file mode 100644 index 00000000..a30d150f --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothCameraController.cpp @@ -0,0 +1,259 @@ +// 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 "PhysXSample.h" + +#include "SampleCharacterClothCameraController.h" + +#include "SampleCharacterCloth.h" +#include "SampleCharacterClothInputEventIds.h" +#include "SampleUtils.h" + +#include "PxRigidDynamic.h" +#include "foundation/PxMath.h" +#include <SampleBaseInputEventIds.h> +#include <SamplePlatform.h> +#include <SampleUserInput.h> +#include <SampleUserInputIds.h> +#include <SampleUserInputDefines.h> + +using namespace physx; +using namespace SampleRenderer; +using namespace SampleFramework; + +/////////////////////////////////////////////////////////////////////////////// +SampleCharacterClothCameraController::SampleCharacterClothCameraController(PxController& controlled, SampleCharacterCloth& base) : + mCamera (NULL), + mController (controlled), + mSample (base), + mTargetYaw (0.0f-PxPi/2), + mTargetPitch (0.0f), + mPitchMin (-PxHalfPi), + mPitchMax (PxHalfPi), + mGamepadPitchInc (0.0f), + mGamepadYawInc (0.0f), + mGamepadForwardInc (0.0f), + mGamepadLateralInc (0.0f), + mSensibility (0.01f), + mFwd (false), + mBwd (false), + mLeft (false), + mRight (false), + mKeyShiftDown (false), + mRunningSpeed (8.0f), + mWalkingSpeed (4.0f) +{ +} + +////////////////////////////////////////////////////////////////////////// + +void SampleCharacterClothCameraController::collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents) +{ + //digital keyboard events + DIGITAL_INPUT_EVENT_DEF(CAMERA_MOVE_FORWARD, SCAN_CODE_FORWARD, XKEY_W, X1KEY_W, PS3KEY_W, PS4KEY_W, AKEY_UNKNOWN, SCAN_CODE_FORWARD, IKEY_UNKNOWN, SCAN_CODE_FORWARD, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(CAMERA_MOVE_BACKWARD, SCAN_CODE_BACKWARD, XKEY_S, X1KEY_S, PS3KEY_S, PS4KEY_S, AKEY_UNKNOWN, SCAN_CODE_BACKWARD, IKEY_UNKNOWN, SCAN_CODE_BACKWARD, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(CAMERA_MOVE_LEFT, SCAN_CODE_LEFT, XKEY_A, X1KEY_A, PS3KEY_A, PS4KEY_A, AKEY_UNKNOWN, SCAN_CODE_LEFT, IKEY_UNKNOWN, SCAN_CODE_LEFT, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(CAMERA_MOVE_RIGHT, SCAN_CODE_RIGHT, XKEY_D, X1KEY_D, PS3KEY_D, PS4KEY_D, AKEY_UNKNOWN, SCAN_CODE_RIGHT, IKEY_UNKNOWN, SCAN_CODE_RIGHT, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(CAMERA_SHIFT_SPEED, SCAN_CODE_LEFT_SHIFT, XKEY_SHIFT, X1KEY_SHIFT, PS3KEY_SHIFT, PS4KEY_SHIFT, AKEY_UNKNOWN, OSXKEY_SHIFT, IKEY_UNKNOWN, LINUXKEY_SHIFT, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(CAMERA_JUMP, SCAN_CODE_SPACE, XKEY_SPACE, X1KEY_SPACE, PS3KEY_SPACE, PS4KEY_SPACE, AKEY_UNKNOWN, OSXKEY_SPACE, IKEY_UNKNOWN, LINUXKEY_SPACE, WIIUKEY_UNKNOWN); + + //digital gamepad events + DIGITAL_INPUT_EVENT_DEF(CAMERA_JUMP, GAMEPAD_SOUTH, GAMEPAD_SOUTH, GAMEPAD_SOUTH, GAMEPAD_SOUTH, GAMEPAD_SOUTH, AKEY_UNKNOWN, GAMEPAD_SOUTH, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_SOUTH); + + //analog gamepad events + ANALOG_INPUT_EVENT_DEF(CAMERA_GAMEPAD_ROTATE_LEFT_RIGHT,GAMEPAD_ROTATE_SENSITIVITY, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, LINUXKEY_UNKNOWN, GAMEPAD_RIGHT_STICK_X); + ANALOG_INPUT_EVENT_DEF(CAMERA_GAMEPAD_ROTATE_UP_DOWN,GAMEPAD_ROTATE_SENSITIVITY, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, LINUXKEY_UNKNOWN, GAMEPAD_RIGHT_STICK_Y); + ANALOG_INPUT_EVENT_DEF(CAMERA_GAMEPAD_MOVE_LEFT_RIGHT,GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, LINUXKEY_UNKNOWN, GAMEPAD_LEFT_STICK_X); + ANALOG_INPUT_EVENT_DEF(CAMERA_GAMEPAD_MOVE_FORWARD_BACK,GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, LINUXKEY_UNKNOWN, GAMEPAD_LEFT_STICK_Y); + + //touch events + TOUCH_INPUT_EVENT_DEF(CAMERA_JUMP, "Jump", AQUICK_BUTTON_1, IQUICK_BUTTON_1); +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterClothCameraController::onDigitalInputEvent(const SampleFramework::InputEvent& ie, bool val) +{ + switch (ie.m_Id) + { + case CAMERA_MOVE_FORWARD: + { + mFwd = val; + } + break; + case CAMERA_MOVE_BACKWARD: + { + mBwd = val; + } + break; + case CAMERA_MOVE_LEFT: + { + mLeft = val; + } + break; + case CAMERA_MOVE_RIGHT: + { + mRight = val; + } + break; + case CAMERA_SHIFT_SPEED: + { + mKeyShiftDown = val; + } + break; + case CAMERA_JUMP: + { + if(val) + mSample.mJump.startJump(13.0f); + } + break; + } +} + +/////////////////////////////////////////////////////////////////////////////// +static PX_FORCE_INLINE PxReal remapAxisValue(PxReal absolutePosition) +{ + return absolutePosition * absolutePosition * absolutePosition * 5.0f; +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterClothCameraController::onAnalogInputEvent(const SampleFramework::InputEvent& ie, float val) +{ + if(ie.m_Id == CAMERA_GAMEPAD_ROTATE_LEFT_RIGHT) + { + mGamepadYawInc = - remapAxisValue(val); + } + else if(ie.m_Id == CAMERA_GAMEPAD_ROTATE_UP_DOWN) + { + mGamepadPitchInc = - remapAxisValue(val); + } + else if(ie.m_Id == CAMERA_GAMEPAD_MOVE_LEFT_RIGHT) + { + mGamepadLateralInc = -val; + } + else if(ie.m_Id == CAMERA_GAMEPAD_MOVE_FORWARD_BACK) + { + mGamepadForwardInc = val; + } +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterClothCameraController::onPointerInputEvent(const SampleFramework::InputEvent &ie, physx::PxU32, physx::PxU32, physx::PxReal dx, physx::PxReal dy, bool val) +{ + if (ie.m_Id == CAMERA_MOUSE_LOOK) + { + mTargetYaw -= dx * mSensibility; + mTargetPitch += dy * mSensibility; + } +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterClothCameraController::setView(PxReal pitch, PxReal yaw) +{ + mTargetPitch = pitch; + mTargetYaw = yaw; +} + +/////////////////////////////////////////////////////////////////////////////// +// This function gets called whenever camera needs to be updated +void SampleCharacterClothCameraController::update(Camera& camera, PxReal dtime) +{ + mCamera = &camera; + updateFromCCT(dtime); +} + +/////////////////////////////////////////////////////////////////////////////// +void +SampleCharacterClothCameraController::updateFromCCT(PxReal dtime) +{ + if(!mSample.isPaused()) + { + PxVec3 disp(0); + + if (mFwd || mBwd || mRight || mLeft || (fabsf(mGamepadForwardInc) > 0.1f) || (fabsf(mGamepadLateralInc) > 0.1f)) + { + PxVec3 targetKeyDisplacement(0); + PxVec3 targetPadDisplacement(0); + + // compute basis + PxVec3 forward = mCamera->getViewDir(); + forward.y = 0; + forward.normalize(); + PxVec3 up = PxVec3(0,1,0); + PxVec3 right = forward.cross(up); + Ps::computeBasis(forward, right, up); + + // increase target displacement due to key press + if (mFwd) targetKeyDisplacement += forward; + if (mBwd) targetKeyDisplacement -= forward; + if (mLeft) targetKeyDisplacement += right; + if (mRight) targetKeyDisplacement -= right; + + targetKeyDisplacement *= mKeyShiftDown ? mRunningSpeed : mWalkingSpeed; + targetKeyDisplacement *= dtime; + + // displacement due to game pad control + targetPadDisplacement += forward * mGamepadForwardInc * mRunningSpeed; + targetPadDisplacement += right * mGamepadLateralInc * mRunningSpeed; + targetPadDisplacement *= dtime; + + // compute total displacement due to user input + disp = targetKeyDisplacement + targetPadDisplacement; + + mSample.mCCTActive = true; + } + else + mSample.mCCTActive = false; + + mSample.bufferCCTMotion(disp, dtime); + } + else + mSample.bufferCCTMotion(PxVec3(0.0f), dtime); + + // Update camera + mTargetYaw += mGamepadYawInc * dtime; + mTargetPitch += mGamepadPitchInc * dtime; + + // Clamp pitch + if (mTargetPitch < mPitchMin) mTargetPitch = mPitchMin; + if (mTargetPitch > mPitchMax) mTargetPitch = mPitchMax; + + mCamera->setRot(PxVec3(-mTargetPitch,-mTargetYaw,0)); + + const PxExtendedVec3 camTarget = mController.getPosition(); + const PxVec3 target = PxVec3((PxReal)camTarget.x,(PxReal)camTarget.y,(PxReal)camTarget.z) + - mCamera->getViewDir()*7.0f; + mCamera->setPos(target); +} + +#endif // PX_USE_CLOTH_API + diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothCameraController.h b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothCameraController.h new file mode 100644 index 00000000..87be0cea --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothCameraController.h @@ -0,0 +1,78 @@ +// 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. + +#ifndef SAMPLE_CHARACTER_CAMERA_CONTROLLER_H +#define SAMPLE_CHARACTER_CAMERA_CONTROLLER_H + +#include "SampleCameraController.h" + +#include "characterkinematic/PxController.h" + +class SampleCharacterCloth; + +class SampleCharacterClothCameraController : public CameraController +{ +public: + SampleCharacterClothCameraController(PxController& controlled, SampleCharacterCloth& sample); + + // Implements CameraController + virtual void onDigitalInputEvent(const SampleFramework::InputEvent& , bool val); + virtual void onAnalogInputEvent(const SampleFramework::InputEvent& , float val); + virtual void onPointerInputEvent(const SampleFramework::InputEvent&, physx::PxU32, physx::PxU32, physx::PxReal, physx::PxReal, bool); + virtual void collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents); + + virtual void update(Camera& camera, PxReal dtime); + + void updateFromCCT(PxReal dtime); + void setView(PxReal pitch, PxReal yaw); + +protected: + + Camera* mCamera; + PxController& mController; + SampleCharacterCloth& mSample; + + PxReal mTargetYaw, mTargetPitch; + PxReal mPitchMin, mPitchMax; + + PxReal mGamepadPitchInc, mGamepadYawInc; + PxReal mGamepadForwardInc, mGamepadLateralInc; + PxReal mSensibility; + + bool mFwd,mBwd,mLeft,mRight,mKeyShiftDown; + + PxReal mRunningSpeed; + PxReal mWalkingSpeed; + +private: + SampleCharacterClothCameraController& operator=(const SampleCharacterClothCameraController&); + +}; + +#endif diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothFlag.cpp b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothFlag.cpp new file mode 100644 index 00000000..2499201f --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothFlag.cpp @@ -0,0 +1,201 @@ +// 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 "SampleCharacterClothFlag.h" +#include "SampleCharacterCloth.h" + +#include "TestClothHelpers.h" +#include "cloth/PxClothParticleData.h" + +using namespace PxToolkit; + +//////////////////////////////////////////////////////////////////////////////// +SampleCharacterClothFlag::SampleCharacterClothFlag(SampleCharacterCloth& sample, const PxTransform &pose, PxU32 resX, PxU32 resY, PxReal sizeX, PxReal sizeY, PxReal height) + : + mRenderActor(NULL), + mSample(sample), + mWindDir(1.0f, 0.0f, 0.0f), + mWindRange(1.0f), + mWindStrength(1.0f), + mTime(0.0f), + mCapsuleActor(NULL) +{ + PxScene& scene = mSample.getActiveScene(); + PxPhysics& physics = mSample.getPhysics(); + + // adjust placement position for the flag with ray casting so that we can put each flag properly on the terrain + PxVec3 pos = pose.p; + PxRaycastBuffer hit; + scene.raycast(PxVec3(pos.x,100,pos.z), PxVec3(0,-1,0), 500.0f, hit, PxHitFlags(0xffff)); + bool didHit = hit.hasBlock; + PX_ASSERT(didHit); PX_UNUSED(didHit); + pos = hit.block.position + PxVec3(0,0.2f,0.0); + + // settings to adjust flag and pole position on the ground + PxTransform clothPose(pos, pose.q); + + PxReal halfSizeX = sizeX * 0.5f; + PxReal halfSizeY = sizeY * 0.5f; + PxReal offset = sizeX * 0.1f; + PxReal halfHeight = height * 0.5f; + + PxReal clothHeight = height - halfSizeY; + clothPose.p.y += clothHeight; + + // create the cloth flag mesh + SampleArray<PxVec4> vertices; + SampleArray<PxU32> primitives; + PxClothMeshDesc meshDesc = Test::ClothHelpers::createMeshGrid( + PxVec3(sizeX,0,0), PxVec3(0,-sizeY,0), resX, resY, vertices, primitives, mUVs); + + // attach two corners on the left + for (PxU32 i = 0; i < meshDesc.points.count; i++) + { + PxReal u = mUVs[i].x, v = mUVs[i].y; + bool constrain = ( (u < 0.01) && (v < 0.01) ) || (( u < 0.01) && (v > 0.99)); + vertices[i].w = constrain ? 0.0f : 1.0f; + } + + // create cloth fabric + PxClothFabric* clothFabric = PxClothFabricCreate(physics, meshDesc, PxVec3(0,-1,0)); + PX_ASSERT(meshDesc.points.stride == sizeof(PxVec4)); + + // create the cloth actor + const PxClothParticle* particles = (const PxClothParticle*)meshDesc.points.data; + PxCloth* cloth = physics.createCloth( clothPose, *clothFabric, particles, PxClothFlags()); + PX_ASSERT(cloth); + + // add this cloth into the scene + scene.addActor(*cloth); + + // create collision capsule for the pole + SampleArray<PxClothCollisionSphere> spheres(2); + spheres[0].pos = PxVec3(-halfSizeX - offset, -clothHeight, 0); + spheres[1].pos = PxVec3(-halfSizeX - offset, halfSizeY, 0); + spheres[0].radius = 0.1f; + spheres[1].radius = 0.1f; + + SampleArray<PxU32> indexPairs; + indexPairs.pushBack(0); + indexPairs.pushBack(1); + cloth->setCollisionSpheres(spheres.begin(), 2); + cloth->addCollisionCapsule(indexPairs[0], indexPairs[1]); + + // create render material + RenderMaterial* clothMaterial = mSample.mFlagMaterial; + mRenderActor = SAMPLE_NEW (RenderClothActor)(*mSample.getRenderer(), *cloth, meshDesc, + mUVs.begin(), 0.5f); + mRenderActor->setRenderMaterial(clothMaterial); + mSample.mRenderClothActors.push_back(mRenderActor); + mSample.mRenderActors.push_back(mRenderActor); + + // set solver settings + cloth->setSolverFrequency(120); + cloth->setDampingCoefficient(PxVec3(0.0f)); + + cloth->setStretchConfig(PxClothFabricPhaseType::eBENDING, PxClothStretchConfig(0.1f)); + cloth->setTetherConfig(PxClothTetherConfig(1.0f, 1.0f)); + + mCloth = cloth; + + // we create an invisible kinematic capsule so that the CCT avoids colliding character against the pole of this flag + // note that cloth collision capsule above has no effect on rigid body scenes. + PxTransform capsulePose(pos, PxQuat(PxHalfPi, PxVec3(0,0,1))); + capsulePose.p.x -= halfSizeX + offset; + capsulePose.p.y += halfHeight; + PxCapsuleGeometry geom(0.2f,halfHeight); + + mCapsuleActor = sample.getPhysics().createRigidDynamic(capsulePose); + mCapsuleActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true); + PxRigidActorExt::createExclusiveShape(*mCapsuleActor, geom, sample.getDefaultMaterial()); + scene.addActor(*mCapsuleActor); +} + +//////////////////////////////////////////////////////////////////////////////// +void +SampleCharacterClothFlag::release() +{ + mSample.removeRenderClothActor(*mRenderActor); + delete mRenderActor; + + mCloth->release(); + mCapsuleActor->release(); + + delete this; +} + +//////////////////////////////////////////////////////////////////////////////// +void +SampleCharacterClothFlag::setWind(const PxVec3 &dir, PxReal strength, const PxVec3& range) +{ + mWindStrength = strength; + mWindDir = dir; + mWindRange = range; +} + +//////////////////////////////////////////////////////////////////////////////// +void +SampleCharacterClothFlag::update(PxReal dtime) +{ + PX_ASSERT(mCloth); + + // implementation of a simple wind force that varies its direction, strength over time + mTime += dtime * PxToolkit::Rand(0.0f, 1.0f); + + float st = 1.0f + (float)sin(mTime); + float windStrength = PxToolkit::Rand(1.0f, st) * mWindStrength; + float windRangeStrength = PxToolkit::Rand(0.0f, 2.0f); + + PxVec3 offset( PxReal(PxToolkit::Rand(-1,1)), PxReal(PxToolkit::Rand(-1,1)), PxReal(PxToolkit::Rand(-1,1))); + float ct = 1.0f + (float)cos(mTime + 0.1); + offset *= ct; + PxVec3 windAcceleration = windStrength * mWindDir + windRangeStrength * mWindRange.multiply(offset); + + mCloth->setExternalAcceleration(windAcceleration); + +#if 0 + PxU32 nbParticles = mCloth->getNbParticles(); + SampleArray<PxVec4> accel(nbParticles); + + for (PxU32 i = 0; i < nbParticles; i++) + { + accel[i].x = PxToolkit::Rand(-1,1) * mWindRange.x; + accel[i].y = PxToolkit::Rand(-1,1) * mWindRange.y; + accel[i].z = PxToolkit::Rand(-1,1) * mWindRange.z; + } + mCloth->setParticleAccelerations(accel.begin()); +#endif +} + +#endif // PX_USE_CLOTH_API + + diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothFlag.h b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothFlag.h new file mode 100644 index 00000000..5e91c325 --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothFlag.h @@ -0,0 +1,63 @@ +// 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. + +#ifndef SAMPLE_CHARACTER_CLOTH_FLAG_H +#define SAMPLE_CHARACTER_CLOTH_FLAG_H + +#include "cloth/PxCloth.h" +#include "PhysXSample.h" + +class SampleCharacterCloth; +class RenderClothActor; + +class SampleCharacterClothFlag +{ +public: + SampleCharacterClothFlag(SampleCharacterCloth& sample, const PxTransform &pose, PxU32 resX, PxU32 resY, PxReal sizeX, PxReal sizeY, PxReal height); + + void setWind(const PxVec3 &dir, PxReal strength, const PxVec3& range); + void update(PxReal dtime); + void release(); + PxCloth* getCloth() { return mCloth; } + +protected: + RenderClothActor* mRenderActor; + SampleCharacterCloth& mSample; + PxCloth* mCloth; + SampleArray<PxVec2> mUVs; + PxVec3 mWindDir; + PxVec3 mWindRange; + PxReal mWindStrength; + PxReal mTime; + PxRigidDynamic* mCapsuleActor; +private: + SampleCharacterClothFlag& operator=(const SampleCharacterClothFlag&); +}; + +#endif diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothInputEventIds.h b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothInputEventIds.h new file mode 100644 index 00000000..90f31f10 --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothInputEventIds.h @@ -0,0 +1,45 @@ +// 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. +#ifndef _SAMPLE_CCT_INPUT_EVENT_IDS_H +#define _SAMPLE_CCT_INPUT_EVENT_IDS_H + +#include <SampleBaseInputEventIds.h> + +// InputEvents used by SampleCharacterController +enum SampleCharacterControllerInputEventIds +{ + SAMPLE_CCT_FIRST = NUM_SAMPLE_BASE_INPUT_EVENT_IDS, + + CROUCH , + RESET_SCENE, + JUMP, + CHANGE_CLOTH_CONTENT, + + NUM_SAMPLE_CCT_INPUT_EVENT_IDS, +}; + +#endif diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothJump.cpp b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothJump.cpp new file mode 100644 index 00000000..8e96f1e9 --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothJump.cpp @@ -0,0 +1,83 @@ +// 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 "SampleCharacterClothJump.h" + +using namespace physx; + +static PxF32 gJumpGravity = -25.0f; + +SampleCharacterClothJump::SampleCharacterClothJump() : + mV (0.0f), + mTime (0.0f), + mJump (false), + mFreefall (false) +{ +} + +void SampleCharacterClothJump::startJump(PxF32 v0) +{ + if (mJump) return; + if (mFreefall) return; + mV = v0; + mJump = true; +} + +void SampleCharacterClothJump::reset() +{ + // reset jump state at most every half a second + // otherwise we might miss jump events + if (mTime < 0.5f) + return; + + mFreefall = false; + mJump = false; + mV = 0.0f; + mTime = 0.0f; +} + +void SampleCharacterClothJump::tick(PxF32 dtime) +{ + mTime += dtime; + mV += gJumpGravity * dtime; + const PxReal vlimit = -25.0f; + if (mV < vlimit) + { + // limit velocity in freefall so that character does not fall at rocket speed. + mV = vlimit; + mFreefall = true; + mJump = false; + } +} + +PxF32 SampleCharacterClothJump::getDisplacement(PxF32 dtime) +{ + return mV * dtime; +} + diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothJump.h b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothJump.h new file mode 100644 index 00000000..83e7d87e --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothJump.h @@ -0,0 +1,58 @@ +// 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. + +#ifndef SAMPLE_CCT_JUMP_H +#define SAMPLE_CCT_JUMP_H + +#include "common/PxPhysXCommonConfig.h" +#include "SampleAllocator.h" + +using namespace physx; + +class SampleCharacterClothJump : public SampleAllocateable +{ + public: + SampleCharacterClothJump(); + + bool isJumping() const { return mJump; } + bool isInFreefall() const { return mFreefall; } + PxF32 getDisplacement(PxF32 dtime); + void reset(); + void startJump(PxF32 v0); + void tick(PxF32 elapsedTime); + +protected: + PxF32 mV; + PxF32 mTime; + bool mJump; + bool mFreefall; + +}; + +#endif diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothPlatform.h b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothPlatform.h new file mode 100644 index 00000000..a9af7280 --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothPlatform.h @@ -0,0 +1,80 @@ +// 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. + +#ifndef SAMPLE_CHARACTER_CLOTH_PLATFORM_H +#define SAMPLE_CHARACTER_CLOTH_PLATFORM_H + +#include "PhysXSample.h" +#include "characterkinematic/PxController.h" +#include "SampleAllocator.h" +#include "SampleAllocatorSDKClasses.h" + +/////////////////////////////////////////////////////////////////////////////// +class SampleCharacterClothPlatform : public SampleAllocateable +{ +public: + + /////////////////////////////////////////////////////////////////////////////// + enum { + ePLATFORM_TYPE_STATIC, + ePLATFORM_TYPE_MOVING, + ePLATFORM_TYPE_TRIGGERED, + }; + + /////////////////////////////////////////////////////////////////////////////// + SampleCharacterClothPlatform(); + ~SampleCharacterClothPlatform() {} + + /////////////////////////////////////////////////////////////////////////////// + PX_FORCE_INLINE PxRigidDynamic* getPhysicsActor() { return mActor;} + PX_FORCE_INLINE PxReal getTravelTime() const { return mTravelTime; } + PX_FORCE_INLINE PxU32 getType() const { return mType; } + + PX_FORCE_INLINE void setActive(bool b) { mActive = b; } + PX_FORCE_INLINE void setTravelTime(PxReal t) { mTravelTime = t; } + PX_FORCE_INLINE void setType(PxU32 t) { mType = t; } + + /////////////////////////////////////////////////////////////////////////////// + void init(PxRigidDynamic* actor, PxReal travelTime, const PxVec3& offsetTarget = PxVec3(0,0,0) ); + void release(); + void reset(); + void update(PxReal dtime); + +protected: + PxRigidDynamic* mActor; + PxReal mCurrentTime; + PxReal mTravelTime; + PxVec3 mStart; + PxVec3 mTarget; + bool mFlip; + PxU32 mType; + bool mActive; +}; + +#endif diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothSettings.h b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothSettings.h new file mode 100644 index 00000000..b38cd963 --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterClothSettings.h @@ -0,0 +1,39 @@ +// 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. + +#ifndef SAMPLE_CHARACTER_CLOTH_SETTINGS_H +#define SAMPLE_CHARACTER_CLOTH_SETTINGS_H + + #define CONTACT_OFFSET 0.01f + #define STEP_OFFSET 0.1f + #define SLOPE_LIMIT 0.8f + #define INVISIBLE_WALLS_HEIGHT 6.0f + #define MAX_JUMP_HEIGHT 4.0f + +#endif diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_CCT.cpp b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_CCT.cpp new file mode 100644 index 00000000..fef32565 --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_CCT.cpp @@ -0,0 +1,201 @@ +// 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 "SampleAllocatorSDKClasses.h" + +#include "PxPhysicsAPI.h" +#include "extensions/PxExtensionsAPI.h" + +#include "characterkinematic/PxControllerManager.h" +#include "characterkinematic/PxBoxController.h" +#include "characterkinematic/PxCapsuleController.h" + + +#include "geometry/PxMeshQuery.h" +#include "geometry/PxTriangle.h" + +#include "RenderBaseActor.h" +#include "RenderBoxActor.h" +#include "RenderCapsuleActor.h" +#include <SampleUserInputIds.h> +#include <SamplePlatform.h> +#include <SampleUserInput.h> +#include <SampleUserInputDefines.h> + +using namespace SampleRenderer; +using namespace SampleFramework; + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::bufferCCTMotion(const PxVec3& targetDisp, PxReal dtime) +{ + PxVec3 disp = targetDisp; + + if(!isPaused()) + { + // advance jump controller + mJump.tick(dtime); + + // modify y component of displacement due to jump status + disp.y = mJump.getDisplacement(dtime); + + if (mJump.isInFreefall()) + { + disp.x = 0; + disp.z = 0; + mCCTActive = false; + } + } + + // buffer the displacement and timestep to feed in onSubstep function + mCCTDisplacement = disp; + mCCTTimeStep = dtime; +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::createCCTController() +{ + mControllerManager = PxCreateControllerManager(getActiveScene()); + + // use ray casting to position the CCT on the terrain + PxScene& scene = getActiveScene(); + PxRaycastBuffer hit; + bool didHit = scene.raycast(PxVec3(0,100,0), PxVec3(0,-1,0), 500.0f, hit, PxHitFlags(0xffff)); + PX_UNUSED(didHit); + PX_ASSERT(didHit); + mControllerInitialPosition = hit.block.position + PxVec3(0.0f, 1.6f, 0.0f); + + // create and fill in the descriptor for the capsule controller + PxCapsuleControllerDesc cDesc; + + cDesc.height = 2.0f; + cDesc.radius = 0.5f; + cDesc.material = &getDefaultMaterial(); + cDesc.position = PxExtendedVec3(mControllerInitialPosition.x, mControllerInitialPosition.y, mControllerInitialPosition.z); + cDesc.slopeLimit = 0.1f; + cDesc.contactOffset = 0.01f; + cDesc.stepOffset = 0.1f; + cDesc.scaleCoeff = 0.9f; + cDesc.climbingMode = PxCapsuleClimbingMode::eEASY; + cDesc.invisibleWallHeight = 0.0f; + cDesc.maxJumpHeight = 2.0f; + cDesc.reportCallback = this; + + mController = static_cast<PxCapsuleController*>(mControllerManager->createController(cDesc)); + + // create camera + mCCTCamera = SAMPLE_NEW(SampleCharacterClothCameraController)(*mController, *this); + + setCameraController(mCCTCamera); +} + + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::onShapeHit(const PxControllerShapeHit& hit) +{ + PxRigidDynamic* hitActor = hit.shape->getActor()->is<PxRigidDynamic>(); + + const size_t nbPlatforms = mPlatforms.size(); + for(PxU32 i = 0;i < nbPlatforms;i++) + { + if (mPlatforms[i]->getType() == SampleCharacterClothPlatform::ePLATFORM_TYPE_TRIGGERED) + { + PxRigidDynamic* actor = mPlatforms[i]->getPhysicsActor(); + if (hitActor == actor) + mPlatforms[i]->setActive(true); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::onControllerHit(const PxControllersHit& hit) +{ +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::onObstacleHit(const PxControllerObstacleHit& hit) +{ +} + +/////////////////////////////////////////////////////////////////////////////// +PxControllerBehaviorFlags SampleCharacterCloth::getBehaviorFlags(const PxShape&, const PxActor&) +{ + return PxControllerBehaviorFlags(0); +} + +/////////////////////////////////////////////////////////////////////////////// +PxControllerBehaviorFlags SampleCharacterCloth::getBehaviorFlags(const PxController&) +{ + return PxControllerBehaviorFlags(0); +} + +/////////////////////////////////////////////////////////////////////////////// +PxControllerBehaviorFlags SampleCharacterCloth::getBehaviorFlags(const PxObstacle& obstacle) +{ + return PxControllerBehaviorFlag::eCCT_CAN_RIDE_ON_OBJECT; +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::updateCCT(float dtime) +{ + // compute target cct displacment for this time step + PxVec3 dispCurStep = (mCCTTimeStep > 0.0f) ? mCCTDisplacement * (dtime / mCCTTimeStep) : PxVec3(0.0f); + + // limit horizontal acceleration so that character motion does not produce abrupt impulse + PxVec3 accel = dispCurStep - mCCTDisplacementPrevStep; + const PxReal accelLimit = 0.3f * dtime; + PxVec3 accelHorizontal(accel.x, 0, accel.z); + PxReal accelHorizontalMagnitude = accelHorizontal.magnitude(); + if (accelHorizontalMagnitude > accelLimit) + { + const PxReal accelScale = accelLimit / accelHorizontalMagnitude; + accel.x *= accelScale; + accel.z *= accelScale; + } + + dispCurStep = mCCTDisplacementPrevStep + accel; + mCCTDisplacementPrevStep = dispCurStep; + + // move the CCT and change jump status due to contact + const PxU32 flags = mController->move(dispCurStep, 0.01f, dtime, PxControllerFilters()); + if(flags & PxControllerCollisionFlag::eCOLLISION_DOWN) + mJump.reset(); + + // update camera controller + mCCTCamera->updateFromCCT(dtime); + +} + +#endif // PX_USE_CLOTH_API 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 diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_FilterShader.cpp b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_FilterShader.cpp new file mode 100644 index 00000000..ec6d68bb --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_FilterShader.cpp @@ -0,0 +1,52 @@ +// 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 "PxPhysicsAPI.h" +#include "SampleCharacterCloth.h" + +static PxFilterFlags filter(PxFilterObjectAttributes attributes0, + PxFilterData filterData0, + PxFilterObjectAttributes attributes1, + PxFilterData filterData1, + PxPairFlags& pairFlags, + const void* constantBlock, + PxU32 constantBlockSize) +{ + pairFlags |= PxPairFlag::eCONTACT_DEFAULT; + return PxFilterFlags(); +} + +void SampleCharacterCloth::customizeSceneDesc(PxSceneDesc& sceneDesc) +{ + sceneDesc.gravity = PxVec3(0,-9.81,0); + sceneDesc.filterShader = filter; + sceneDesc.flags |= PxSceneFlag::eREQUIRE_RW_LOCK; +} + diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_Main.cpp b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_Main.cpp new file mode 100644 index 00000000..cfe641e9 --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_Main.cpp @@ -0,0 +1,441 @@ +// 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 "SampleAllocatorSDKClasses.h" +#include "SampleCharacterClothCameraController.h" +#include "SampleCharacterClothInputEventIds.h" +#include "SampleCharacterClothSettings.h" +#include "SampleCharacterClothFlag.h" +#include "SamplePlatform.h" + +#include "RenderMaterial.h" +#include "RenderBaseActor.h" + +#include "characterkinematic/PxCapsuleController.h" +#include "characterkinematic/PxControllerManager.h" +#include "PxPhysicsAPI.h" + +#include "SampleCharacterClothInputEventIds.h" +#include <SampleUserInputIds.h> +#include <SampleUserInput.h> +#include <SampleUserInputDefines.h> + +REGISTER_SAMPLE(SampleCharacterCloth, "SampleCharacterCloth") + +using namespace SampleFramework; +using namespace SampleRenderer; +using namespace PxToolkit; + +/////////////////////////////////////////////////////////////////////////////// + +SampleCharacterCloth::SampleCharacterCloth(PhysXSampleApplication& app) + : PhysXSample (app, 2) + , mCCTCamera (NULL) + , mController (NULL) + , mControllerManager (NULL) + , mCCTDisplacement (0.0f) + , mCCTDisplacementPrevStep (0.0f) + , mCCTTimeStep (0.0f) + , mCape (NULL) +#if PX_SUPPORT_GPU_PHYSX || PX_XBOXONE + , mUseGPU (true) +#endif +{ + mCreateGroundPlane = false; + //mStepperType = FIXED_STEPPER; + mControllerInitialPosition = PxVec3(0.0, 3.0f, 0.0); + + mCCTActive = false; + + mNbVerts = 0; + mNbTris = 0; + mVerts = NULL; + mTris = NULL; +} + +/////////////////////////////////////////////////////////////////////////////// +SampleCharacterCloth::~SampleCharacterCloth() +{ + DELETESINGLE(mCCTCamera); + + SAMPLE_FREE(mTris); + SAMPLE_FREE(mVerts); + + const size_t nbPlatforms = mPlatforms.size(); + for(PxU32 i = 0;i < nbPlatforms;i++) + mPlatforms[i]->release(); + +// releaseFlags(); +} + +/////////////////////////////////////////////////////////////////////////////// +// create render materials used for render objects. +// The newly created materials are appended to PhysXSample::mRenderMaterials array +void SampleCharacterCloth::createRenderMaterials() +{ + getRenderer()->setAmbientColor(RendererColor(100, 100, 100)); + + // create render materials used in this sample + mSnowMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(), PxVec3(0.70f, 0.70f, 0.8f), 1.0f, false, 0, NULL); + mRenderMaterials.push_back(mSnowMaterial); + + mFlagMaterial = createRenderMaterialFromTextureFile("nvidia_flag_d.bmp"); +} + +/////////////////////////////////////////////////////////////////////////////// + +void SampleCharacterCloth::customizeSample(SampleSetup& setup) +{ + setup.mName = "SampleCharacterCloth"; +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::collectInputEvents(std::vector<const InputEvent*>& inputEvents) +{ + PhysXSample::collectInputEvents(inputEvents); + getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(SPAWN_DEBUG_OBJECT); + + //digital keyboard events + DIGITAL_INPUT_EVENT_DEF(RESET_SCENE, WKEY_R, XKEY_R, X1KEY_R, PS3KEY_R, PS4KEY_R, AKEY_UNKNOWN, OSXKEY_R, IKEY_UNKNOWN, LINUXKEY_R, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(CHANGE_CLOTH_CONTENT, WKEY_M, XKEY_M, X1KEY_M, PS3KEY_M, PS4KEY_M, AKEY_UNKNOWN, OSXKEY_M, IKEY_UNKNOWN, LINUXKEY_M, WIIUKEY_UNKNOWN); + + //digital mouse events + + //touch events + TOUCH_INPUT_EVENT_DEF(RESET_SCENE, "Reset", ABUTTON_5, IBUTTON_5); +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::onDigitalInputEvent(const InputEvent& ie, bool val) +{ + if(val) + { + switch (ie.m_Id) + { + case RESET_SCENE: + { + resetScene(); + } + break; + case CHANGE_CLOTH_CONTENT: + mClothFlagCountIndex = (mClothFlagCountIndex+1)% (mClothFlagCountIndexMax+1); + releaseFlags(); + createFlags(); + break; + +#if PX_SUPPORT_GPU_PHYSX || PX_XBOXONE + case TOGGLE_CPU_GPU: + toggleGPU(); + return; + break; +#endif + } + } + + PhysXSample::onDigitalInputEvent(ie,val); +} + +/////////////////////////////////////////////////////////////////////////////// + +void SampleCharacterCloth::helpRender(PxU32 x, PxU32 y, PxU8 textAlpha) +{ + Renderer* renderer = getRenderer(); + const PxU32 yInc = 18; + const PxReal scale = 0.5f; + const PxReal shadowOffset = 6.0f; + const RendererColor textColor(255, 255, 255, textAlpha); + const bool isMouseSupported = getApplication().getPlatform()->getSampleUserInput()->mouseSupported(); + const bool isPadSupported = getApplication().getPlatform()->getSampleUserInput()->gamepadSupported(); + const char* msg; + + if (isMouseSupported && isPadSupported) + renderer->print(x, y += yInc, "Use mouse or right stick to rotate the camera", scale, shadowOffset, textColor); + else if (isMouseSupported) + renderer->print(x, y += yInc, "Use mouse to rotate the camera", scale, shadowOffset, textColor); + else if (isPadSupported) + renderer->print(x, y += yInc, "Use right stick to rotate the camera", scale, shadowOffset, textColor); + if (isPadSupported) + renderer->print(x, y += yInc, "Use left stick to move",scale, shadowOffset, textColor); + msg = mApplication.inputMoveInfoMsg("Press "," to move", CAMERA_MOVE_FORWARD,CAMERA_MOVE_BACKWARD, CAMERA_MOVE_LEFT, CAMERA_MOVE_RIGHT); + if(msg) + renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor); + msg = mApplication.inputInfoMsg("Press "," to move fast", CAMERA_SHIFT_SPEED, -1); + if(msg) + renderer->print(x, y += yInc, msg, scale, shadowOffset, textColor); + msg = mApplication.inputInfoMsg("Press "," to jump", CAMERA_JUMP, -1); + if(msg) + renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor); + + msg = mApplication.inputInfoMsg("Press "," to toggle visualization", TOGGLE_VISUALIZATION, -1); + if(msg) + renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor); + + msg = mApplication.inputInfoMsg("Press "," to reset scene", RESET_SCENE, -1); + if(msg) + renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor); + + msg = mApplication.inputInfoMsg("Press "," to change flag count", CHANGE_CLOTH_CONTENT,-1); + if(msg) + renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor); + +#if PX_SUPPORT_GPU_PHYSX || PX_XBOXONE + msg = mApplication.inputInfoMsg("Press "," to toggle CPU/GPU", TOGGLE_CPU_GPU, -1); + if(msg) + renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor); +#endif +} + +void SampleCharacterCloth::descriptionRender(PxU32 x, PxU32 y, PxU8 textAlpha) +{ + bool print=(textAlpha!=0.0f); + + if(print) + { + Renderer* renderer = getRenderer(); + const PxU32 yInc = 24; + const PxReal scale = 0.5f; + const PxReal shadowOffset = 6.0f; + const RendererColor textColor(255, 255, 255, textAlpha); + + char line0[256]="This sample demonstrates the PhysX cloth feature. In particular, the "; + char line1[256]="setup and simulation of a cape attached to an animated character is"; + char line2[256]="presented. This involves generating an approximate description of the"; + char line3[256]="character's geometry, cloth instantiation, the binding of the cloth to a"; + char line4[256]="skinned character, and the setup of simulation parameters and values"; + char line5[256]="controlling the different phases of the cloth solver. To clarify the"; + char line6[256]="process, and to offer some variety, a flag is also created and simulated."; +#if PX_WINDOWS + char line7[256]="Finally, the sample illustrates the steps required to enable GPU"; + char line8[256]="acceleration of PhysX cloth."; +#endif + + renderer->print(x, y+=yInc, line0, scale, shadowOffset, textColor); + renderer->print(x, y+=yInc, line1, scale, shadowOffset, textColor); + renderer->print(x, y+=yInc, line2, scale, shadowOffset, textColor); + renderer->print(x, y+=yInc, line3, scale, shadowOffset, textColor); + renderer->print(x, y+=yInc, line4, scale, shadowOffset, textColor); + renderer->print(x, y+=yInc, line5, scale, shadowOffset, textColor); + renderer->print(x, y+=yInc, line6, scale, shadowOffset, textColor); +#if PX_WINDOWS + renderer->print(x, y+=yInc, line7, scale, shadowOffset, textColor); + renderer->print(x, y+=yInc, line8, scale, shadowOffset, textColor); +#endif + } +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::customizeRender() +{ +#if PX_SUPPORT_GPU_PHYSX || PX_XBOXONE + SampleRenderer::Renderer* renderer = getRenderer(); + + const PxU32 yInc = 20; + const PxReal scale = 0.5f; + const PxReal shadowOffset = 6.0f; + PxU32 width, height; + renderer->getWindowSize(width, height); + + PxU32 y = height-2*yInc; + PxU32 x = width - 360; + + { + const RendererColor textColor(255, 0, 0, 255); + const char* message[4] = { "Flag count: Moderate", "Flag count: Medium", "Flag count: High", "Flag count: Very High" }; + renderer->print(x, y, message[mClothFlagCountIndex], scale, shadowOffset, textColor); + } + + { + y -= yInc; + const RendererColor textColor(255, 0, 0, 255); + + char buf[2048]; + sprintf(buf, mUseGPU ? "Running on GPU" : "Running on CPU"); + + if(PX_SUPPORT_GPU_PHYSX && mUseGPU) + sprintf(buf + strlen(buf), " (%s)", getActiveScene().getTaskManager()->getGpuDispatcher()->getCudaContextManager()->getDeviceName()); + + renderer->print(x, y, buf, scale, shadowOffset, textColor); + } + + { + y -= yInc; + + char fpsText[512]; + sprintf(fpsText, "Average PhysX time: %3.3f ms", 1000.0f * mAverageSimulationTime); + + const RendererColor textColor(255, 255, 255, 255); + renderer->print(x, y, fpsText, scale, shadowOffset, textColor); + } + +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::onInit() +{ + mNbThreads = PxMax(PxI32(shdfnd::Thread::getNbPhysicalCores())-1, 0); + + // try to get gpu support + mCreateCudaCtxManager = true; + + PhysXSample::onInit(); + + PxSceneWriteLock scopedLock(*mScene); + + mApplication.setMouseCursorHiding(true); + mApplication.setMouseCursorRecentering(true); + + mClothFlagCountIndex = 0; + mClothFlagCountIndexMax = 3; + + // create materials and render setup + createRenderMaterials(); + + // build static heightfield landscape + buildHeightField(); + + // create CCT controller + createCCTController(); + + // create the stickman character + createCharacter(); + + // create a cape for the stickman + createCape(); + + // create flags + createFlags(); + + // reset scene + resetScene(); + + // apply global physx settings + getActiveScene().setGravity(PxVec3(0,-10.0f,0)); +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::resetScene() +{ + PxSceneWriteLock scopedLock(*mScene); + + // reset cct + PxVec3 pos = mControllerInitialPosition; + mController->setPosition(PxExtendedVec3(pos.x, pos.y, pos.z)); + + // compute global pose and local positions + PxExtendedVec3 posExt = mController->getPosition(); + PxTransform pose = mController->getActor()->getGlobalPose(); + pose.p = PxVec3(PxReal(posExt.x), PxReal(posExt.y), PxReal(posExt.z)) - PxVec3(0.0f, 1.5, 0.0f); + + mCharacter.setGlobalPose(pose); + + resetCharacter(); + resetCape(); + + // reset platforms + const size_t nbPlatforms = mPlatforms.size(); + for(PxU32 i = 0;i < nbPlatforms;i++) + mPlatforms[i]->reset(); + + // reset camera + mCCTCamera->setView(0.0f, 0.0f); + + // reset stats + mFrameCount = 0; + mAccumulatedSimulationTime = 0.0f; + mAverageSimulationTime = 0.0f; +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::onShutdown() +{ + { + PxSceneWriteLock scopedLock(*mScene); + DELETESINGLE(mCCTCamera); + SAFE_RELEASE(mControllerManager); + } + PhysXSample::onShutdown(); +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::onTickPreRender(float dtime) +{ + PhysXSample::onTickPreRender(dtime); +} + +/////////////////////////////////////////////////////////////////////////////// +// called after each substep is done (can be called more than once per frame) +void SampleCharacterCloth::onSubstep(float dtime) +{ + PxSceneWriteLock scopedLock(*mScene); + + updatePlatforms(dtime); + updateCCT(dtime); + updateCharacter(dtime); + updateCape(dtime); + updateFlags(dtime); + +#if PX_SUPPORT_GPU_PHYSX || PX_XBOXONE + // update the GPU flag (may have been disabled if CUDA error, not enough shared memory, etc) + mUseGPU = mCape->getClothFlags() & (PxClothFlag::eCUDA); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::onTickPostRender(float dtime) +{ + PhysXSample::onTickPostRender(dtime); + + mFrameCount++; + mAccumulatedSimulationTime += getSimulationTime(); + PxReal delta = PxReal(mTimer.peekElapsedSeconds()); + if (delta > 1.0f) + { + mAverageSimulationTime = mAccumulatedSimulationTime / PxReal(mFrameCount); + mFrameCount = 0; + mAccumulatedSimulationTime = 0.0f; + mTimer.getElapsedSeconds(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::onPointerInputEvent(const SampleFramework::InputEvent& ie, physx::PxU32 x, physx::PxU32 y, physx::PxReal dx, physx::PxReal dy, bool val) +{ + PhysXSample::onPointerInputEvent(ie,x,y,dx,dy,val); +} + +#endif // PX_USE_CLOTH_API + + diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_Platform.cpp b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_Platform.cpp new file mode 100644 index 00000000..641e477a --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_Platform.cpp @@ -0,0 +1,120 @@ +// 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 "SampleCharacterCloth.h" + +#include "SampleCharacterClothPlatform.h" + + +/////////////////////////////////////////////////////////////////////////////// +SampleCharacterClothPlatform::SampleCharacterClothPlatform() : + mActor(NULL), + mCurrentTime(0.0f), + mTravelTime(0.0f), + mStart(0.0f), + mTarget(0.0f), + mFlip(false), + mType(ePLATFORM_TYPE_MOVING), + mActive(true) + { + } + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterClothPlatform::init(PxRigidDynamic* actor, PxReal travelTime, const PxVec3& offsetTarget) +{ + mActor = actor; + mCurrentTime = 0.0f; + mTravelTime = travelTime; + + mStart = mActor->getGlobalPose().p; + mTarget = mStart + offsetTarget; + + reset(); +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterClothPlatform::release() +{ + delete this; +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterClothPlatform::reset() +{ + mCurrentTime = 0.0f; + mFlip = false; + + switch (mType) + { + case ePLATFORM_TYPE_MOVING: + mActive = true; + break; + default: + mActive = false; + } + + update(0.0f); +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterClothPlatform::update(PxReal dtime) +{ + PxReal t = mCurrentTime / mTravelTime; + + PxTransform pose = mActor->getGlobalPose(); + if (!mFlip) + { + pose.p = (1 - t) * mStart + t * mTarget; + } + else + pose.p = t * mStart + (1-t) * mTarget; + + mActor->setKinematicTarget(pose); + + if (mActive == false) + return; + + mCurrentTime += dtime; + + if (mCurrentTime > mTravelTime) + { + mCurrentTime -= mTravelTime; + mFlip = !mFlip; + } +} + +/////////////////////////////////////////////////////////////////////////////// +void SampleCharacterCloth::updatePlatforms(float dtime) +{ + const size_t nbPlatforms = mPlatforms.size(); + for(PxU32 i = 0;i < nbPlatforms;i++) + { + mPlatforms[i]->update(dtime); + } +}
\ No newline at end of file diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_PlatformBuilder.cpp b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_PlatformBuilder.cpp new file mode 100644 index 00000000..a1919d60 --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_PlatformBuilder.cpp @@ -0,0 +1,201 @@ +// 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 "SampleCharacterCloth.h" + +#include "SampleCharacterClothPlatform.h" + +////////////////////////////////////////////////////////////////////////////// +// create a kinematic capsule +SampleCharacterClothPlatform* +SampleCharacterCloth::createPlatform(const PxTransform &pose, const PxGeometry &geom, PxReal travelTime, const PxVec3 &offset, RenderMaterial *renderMaterial) +{ + PxRigidDynamic* actor = getPhysics().createRigidDynamic(pose); + actor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true); + + PxShape* shape = PxRigidActorExt::createExclusiveShape(*actor, geom, getDefaultMaterial()); + + PxScene& scene = getActiveScene(); + scene.addActor(*actor); + + createRenderObjectFromShape(actor, shape, renderMaterial); + + SampleCharacterClothPlatform* platform = SAMPLE_NEW(SampleCharacterClothPlatform); + platform->init(actor, travelTime, offset); + + mPlatforms.pushBack(platform); + + return platform; +} + +////////////////////////////////////////////////////////////////////////////// +// create moving platforms +void SampleCharacterCloth::createPlatforms() +{ + SampleCharacterClothPlatform* platform = 0; + + // initial deck + PxVec3 p0(0,0,-4); + platform = createPlatform(PxTransform(p0, PxQuat(PxIdentity)), + PxBoxGeometry(PxVec3(2,1,8)), 2.0f, PxVec3(0,0,0), mPlatformMaterial); + + // moving platform (moving in x) + PxVec3 p1 = p0 + PxVec3(-4, 0, -6); + PxVec3 p1offset(-10,0,0); + platform = createPlatform(PxTransform(p1, PxQuat(PxIdentity)), + PxBoxGeometry(PxVec3(2,1,2)), 4.0f, p1offset, mPlatformMaterial); + + // moving platform triggered by contact + PxVec3 p2 = p1 + p1offset + PxVec3(-4,2,0); + PxVec3 p2offset(0,0,-10); + platform = createPlatform(PxTransform(p2, PxQuat(PxIdentity)), + PxBoxGeometry(PxVec3(2,1,2)), 5.0f, p2offset, mPlatformMaterial); + platform->setType(SampleCharacterClothPlatform::ePLATFORM_TYPE_TRIGGERED); + + // trampoline-like platform + PxVec3 p3 = p2 + p2offset + PxVec3(-4,-3,0); + PxVec3 p3offset(0,10, 0); + platform = createPlatform(PxTransform(p3, PxQuat(PxIdentity)), + PxBoxGeometry(PxVec3(1,1,1)), 5.0f, p3offset, mRockMaterial); + platform->setType(SampleCharacterClothPlatform::ePLATFORM_TYPE_TRIGGERED); + + // a wide deck with a hole + PxVec3 p4 = p3 + PxVec3(-10, 5, -4); + PxVec3 p4offset(0.0f); + + platform = createPlatform(PxTransform(p4+PxVec3(0,0,-4), PxQuat(PxIdentity)), + PxBoxGeometry(PxVec3(6,0.5,2)), 5.0f, p4offset, mWoodMaterial); + platform = createPlatform(PxTransform(p4+PxVec3(0,0,4), PxQuat(PxIdentity)), + PxBoxGeometry(PxVec3(6,0.5,2)), 5.0f, p4offset, mWoodMaterial); + + platform = createPlatform(PxTransform(p4+PxVec3(-4,0,0), PxQuat(PxIdentity)), + PxBoxGeometry(PxVec3(2,0.5,2)), 5.0f, p4offset, mWoodMaterial); + platform = createPlatform(PxTransform(p4+PxVec3(4,0,0), PxQuat(PxIdentity)), + PxBoxGeometry(PxVec3(2,0.5,2)), 5.0f, p4offset, mWoodMaterial); + + // walls + platform = createPlatform(PxTransform(p4+PxVec3(0,5.5,-6), PxQuat(PxIdentity)), + PxBoxGeometry(PxVec3(6,6,0.5)), 1.0f, p4offset, mRockMaterial); + platform = createPlatform(PxTransform(p4+PxVec3(-6,5.5,0), PxQuat(PxIdentity)), + PxBoxGeometry(PxVec3(0.5,6,6)), 1.0f, p4offset, mRockMaterial); + + // moving platform under the deck + PxVec3 p5 = p4 + PxVec3(0,-6,0); + PxVec3 p5offset(15,0,-15); + platform = createPlatform(PxTransform(p5, PxQuat(PxIdentity)), + PxBoxGeometry(PxVec3(3,1,3)), 5.0f, p5offset, mPlatformMaterial); + + // steps made of spheres + PxVec3 sphere0 = p5 + p5offset + PxVec3(4,1,-4); + platform = createPlatform(PxTransform(sphere0, PxQuat(PxIdentity)), + PxSphereGeometry(1.5f), 3.0f, PxVec3(0), mRockMaterial); + + PxVec3 sphere1 = sphere0 + PxVec3(4,1,-3); + platform = createPlatform(PxTransform(sphere1, PxQuat(PxIdentity)), + PxSphereGeometry(1.5f), 3.0f, PxVec3(0), mRockMaterial); + + PxVec3 sphere2 = sphere1 + PxVec3(-2,1,-4); + platform = createPlatform(PxTransform(sphere2, PxQuat(PxIdentity)), + PxSphereGeometry(1.5f), 3.0f, PxVec3(0), mRockMaterial); + + PxVec3 sphere3 = sphere2 + PxVec3(-5,1,1); + platform = createPlatform(PxTransform(sphere3, PxQuat(PxIdentity)), + PxSphereGeometry(1.5f), 3.0f, PxVec3(0), mRockMaterial); + + PxVec3 sphere4 = sphere3 + PxVec3(-2,1,4); + platform = createPlatform(PxTransform(sphere4, PxQuat(PxIdentity)), + PxSphereGeometry(1.5f), 3.0f, PxVec3(0), mRockMaterial); + + PxVec3 sphere5 = sphere4 + PxVec3(3,1,1); + platform = createPlatform(PxTransform(sphere5, PxQuat(PxIdentity)), + PxSphereGeometry(1.5f), 3.0f, PxVec3(0), mRockMaterial); + + PxVec3 sphere6 = sphere5 + PxVec3(3,1,-3); + platform = createPlatform(PxTransform(sphere6, PxQuat(PxIdentity)), + PxSphereGeometry(1.5f), 3.0f, PxVec3(0), mRockMaterial); + + + // capsule platform + PxVec3 capsule0 = sphere6 + PxVec3(12, 1, -12); + platform = createPlatform(PxTransform(capsule0, PxQuat(PxPi / 4.0f, PxVec3(0,1.0f, 0.0f))), + PxCapsuleGeometry(1.5f,12.0f), 2.0f, PxVec3(0.0f), mSnowMaterial); + + // second capsule base + PxVec3 capsule1 = capsule0 + PxVec3(12, 0, -22); + platform = createPlatform(PxTransform(capsule1, PxQuat(PxPi / 2.0f, PxVec3(0,1.0f, 0.0f))), + PxCapsuleGeometry(1.5f,10.0f), 2.0f, PxVec3(0.0f), mPlatformMaterial); + + PxVec3 csphere0 = capsule1 + PxVec3(3,0.5,10); + platform = createPlatform(PxTransform(csphere0, PxQuat(PxIdentity)), + PxSphereGeometry(1.5f), 1.0f, PxVec3(-6,0,0), mPlatformMaterial); + + PxVec3 csphere1 = capsule1 + PxVec3(-3,0.5,6); + platform = createPlatform(PxTransform(csphere1, PxQuat(PxIdentity)), + PxSphereGeometry(1.5f), 1.0f, PxVec3(6,0,0), mPlatformMaterial); + + PxVec3 csphere2 = capsule1 + PxVec3(-3,0.5,2); + platform = createPlatform(PxTransform(csphere2, PxQuat(PxIdentity)), + PxSphereGeometry(1.5f), 1.0f, PxVec3(6,0,0), mPlatformMaterial); + + PxVec3 csphere3 = capsule1 + PxVec3(3,0.5,-2); + platform = createPlatform(PxTransform(csphere3, PxQuat(PxIdentity)), + PxSphereGeometry(1.5f), 1.0f, PxVec3(-6,0,0), mPlatformMaterial); + + PxVec3 csphere4 = capsule1 + PxVec3(3,0.5,-6); + platform = createPlatform(PxTransform(csphere4, PxQuat(PxIdentity)), + PxSphereGeometry(1.5f), 1.0f, PxVec3(-6,0,0), mPlatformMaterial); + + PxVec3 csphere5 = capsule1 + PxVec3(-3,0.5,-10); + platform = createPlatform(PxTransform(csphere5, PxQuat(PxIdentity)), + PxSphereGeometry(1.5f), 1.0f, PxVec3(6,0,0), mPlatformMaterial); + + // jump deck + PxVec3 jumpDeck = capsule1 + PxVec3(0,1, 0) + PxVec3(-10,0,-10); + platform = createPlatform(PxTransform(jumpDeck, PxQuat(-PxPi / 4.0f, PxVec3(0,1.0f, 0.0f))), + PxBoxGeometry(PxVec3(6,1,2)), 5.0f, PxVec3(0.0f), mWoodMaterial); + + // wind tunnel + PxVec3 windTunnel = jumpDeck + PxVec3(0,0,0) + PxVec3(-6,0,-6); + platform = createPlatform(PxTransform(windTunnel, PxQuat(-PxPi / 4.0f, PxVec3(0,1.0f, 0.0f))), + PxBoxGeometry(PxVec3(2,0.5,2)), 5.0f, PxVec3(0.0f), mPlatformMaterial); + + // landing deck + PxVec3 landingDeck = jumpDeck + PxVec3(0,2, 0) + PxVec3(-15,0,-15); + platform = createPlatform(PxTransform(landingDeck, PxQuat(-PxPi / 4.0f, PxVec3(0,1.0f, 0.0f))), + PxBoxGeometry(PxVec3(4,1,2)), 5.0f, PxVec3(0.0f), mRockMaterial); + + // reset platforms + const size_t nbPlatforms = mPlatforms.size(); + for(PxU32 i = 0;i < nbPlatforms;i++) + mPlatforms[i]->reset(); + + // debugging cheat to start from later levels +// mControllerInitialPosition = jumpDeck + PxVec3(0,5,0); + +} diff --git a/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_TerrainBuilder.cpp b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_TerrainBuilder.cpp new file mode 100644 index 00000000..c3443a10 --- /dev/null +++ b/PhysX_3.4/Samples/SampleCharacterCloth/SampleCharacterCloth_TerrainBuilder.cpp @@ -0,0 +1,268 @@ +// 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 "PxPhysicsAPI.h" +#include "PxTkStream.h" +#include "SampleCharacterCloth.h" + +using namespace PxToolkit; + +//#define USE_MESH + +static PxToolkit::BasicRandom gClothRandom; + +static PxReal randomScaled(PxReal value) +{ + PxReal val = value*(gClothRandom.randomFloat()); + return val; +} + +static void computeTerrain(bool* done, PxReal* pVB, PxU32 x0, PxU32 y0, PxU32 currentSize, PxReal value, PxU32 initSize) +{ + // Compute new size + currentSize>>=1; + if (currentSize > 0) { + PxU32 x1 = (x0+currentSize) % initSize; + PxU32 x2 = (x0+currentSize+currentSize) % initSize; + PxU32 y1 = (y0+currentSize) % initSize; + PxU32 y2 = (y0+currentSize+currentSize) % initSize; + + if(!done[x1 + y0*initSize]) pVB[(x1 + y0*initSize)] = randomScaled(value) + 0.5f * (pVB[(x0 + y0*initSize)] + pVB[(x2 + y0*initSize)]); + if(!done[x0 + y1*initSize]) pVB[(x0 + y1*initSize)] = randomScaled(value) + 0.5f * (pVB[(x0 + y0*initSize)] + pVB[(x0 + y2*initSize)]); + if(!done[x2 + y1*initSize]) pVB[(x2 + y1*initSize)] = randomScaled(value) + 0.5f * (pVB[(x2 + y0*initSize)] + pVB[(x2 + y2*initSize)]); + if(!done[x1 + y2*initSize]) pVB[(x1 + y2*initSize)] = randomScaled(value) + 0.5f * (pVB[(x0 + y2*initSize)] + pVB[(x2 + y2*initSize)]); + if(!done[x1 + y1*initSize]) pVB[(x1 + y1*initSize)] = randomScaled(value) + 0.5f * (pVB[(x0 + y1*initSize)] + pVB[(x2 + y1*initSize)]); + + done[x1 + y0*initSize] = true; + done[x0 + y1*initSize] = true; + done[x2 + y1*initSize] = true; + done[x1 + y2*initSize] = true; + done[x1 + y1*initSize] = true; + + // Recurse through 4 corners + value *= 0.5f; + computeTerrain(done, pVB, x0, y0, currentSize, value, initSize); + computeTerrain(done, pVB, x0, y1, currentSize, value, initSize); + computeTerrain(done, pVB, x1, y0, currentSize, value, initSize); + computeTerrain(done, pVB, x1, y1, currentSize, value, initSize); + } +} + +static void fractalize(PxReal* heights, const PxU32 size, const PxReal roughness) +{ + PxU32 num = size*size; + bool* done = (bool*)SAMPLE_ALLOC(sizeof(bool)*num); + for(PxU32 i=0; i<num; i++) + done[i]=false; + computeTerrain(done,heights,0,0,size,roughness,size); + SAMPLE_FREE(done); +} + +PxRigidStatic* SampleCharacterCloth::buildHeightField() +{ + // create a height map + gClothRandom.setSeed(42); + + const PxU32 hfSize = 32; // some power of 2 + const PxU32 hfNumVerts = hfSize*hfSize; + + const PxReal hfScale = 8.0f; // this is how wide one heightfield square is + + PxReal* heightmap = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal)*hfNumVerts); +// memset(heightmap,0,hfNumVerts*sizeof(PxReal)); + for(PxU32 i = 0; i < hfNumVerts; i++) + heightmap[i] = -9.0f; + + fractalize(heightmap,hfSize,16); + + for(PxU32 i = 0; i < hfNumVerts; i++) + heightmap[i] -= 5.0f; + + { // make render terrain + PxReal* hfVerts = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal)*hfNumVerts*3); + PxReal* hfNorms = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal)*hfNumVerts*3); + const PxU32 hfNumTris = (hfSize-1)*(hfSize-1)*2; + PxU32* hfTris = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*hfNumTris*3); + + createLandscape(heightmap,hfSize,hfScale,hfVerts,hfNorms,hfTris); + + RAWMesh data; + data.mName = "terrain"; + data.mTransform = PxTransform(PxIdentity); + data.mTransform.p = PxVec3(-(hfSize/2*hfScale),0,-(hfSize/2*hfScale)); + data.mNbVerts = hfNumVerts; + data.mVerts = (PxVec3*)hfVerts; + data.mVertexNormals = (PxVec3*)hfNorms; + data.mUVs = 0; + data.mMaterialID = 0; + data.mNbFaces = hfNumTris; + data.mIndices = hfTris; + + createRenderMeshFromRawMesh(data); + + mNbVerts = hfNumVerts; + mNbTris = hfNumTris; + mVerts = hfVerts; + mTris = hfTris; + + SAMPLE_FREE(hfNorms); + } + + // eventually create the physics heightfield + PxRigidStatic* hfActor = createHeightField(heightmap,hfScale,hfSize); + + SAMPLE_FREE(heightmap); + + return hfActor; +} + +void SampleCharacterCloth::createLandscape(PxReal* heightmap, PxU32 width, PxReal hfScale, PxReal* outVerts, PxReal* outNorms, PxU32* outTris) +{ + for(PxU32 y=0; y<width; y++) + { + for(PxU32 x=0; x<width; x++) + { + PxU32 index=(x+y*width)*3; + + outVerts[index+0]=(PxReal(x))* hfScale; + outVerts[index+1]=heightmap[x+y*width]; + outVerts[index+2]=(PxReal(y))*hfScale; + + outNorms[index+0]=0; + outNorms[index+1]=1; + outNorms[index+2]=0; + } + } + + // Sobel filter + for (PxU32 y=1;y<width-1;y++) { + for (PxU32 x=1;x<width-1;x++) { + + // 1 0 -1 + // 2 0 -2 + // 1 0 -1 + PxReal dx; + dx = outVerts[((x-1)+(y-1)*width)*3+1]; + dx -= outVerts[((x+1)+(y-1)*width)*3+1]; + dx += 2.0f*outVerts[((x-1)+(y+0)*width)*3+1]; + dx -= 2.0f*outVerts[((x+1)+(y+0)*width)*3+1]; + dx += outVerts[((x-1)+(y+1)*width)*3+1]; + dx -= outVerts[((x+1)+(y+1)*width)*3+1]; + + // 1 2 1 + // 0 0 0 + // -1 -2 -1 + PxReal dy; + dy = outVerts[((x-1)+(y-1)*width)*3+1]; + dy += 2.0f*outVerts[((x+0)+(y-1)*width)*3+1]; + dy += outVerts[((x+1)+(y-1)*width)*3+1]; + dy -= outVerts[((x-1)+(y+1)*width)*3+1]; + dy -= 2.0f*outVerts[((x+0)+(y+1)*width)*3+1]; + dy -= outVerts[((x+1)+(y+1)*width)*3+1]; + + PxReal nx = dx/hfScale*0.15f; + PxReal ny = 1.0f; + PxReal nz = dy/hfScale*0.15f; + + PxReal len = sqrtf(nx*nx+ny*ny+nz*nz); + + outNorms[(x+y*width)*3+0] = nx/len; + outNorms[(x+y*width)*3+1] = ny/len; + outNorms[(x+y*width)*3+2] = nz/len; + } + } + + PxU32 numTris = 0; + for(PxU32 j=0; j<width-1; j++) + { + for(PxU32 i=0; i<width-1; i++) + { + outTris[3*numTris+0]= i + j *(width); + outTris[3*numTris+1]= i + (j+1)*(width); + outTris[3*numTris+2]= i+1 + j *(width); + outTris[3*numTris+3]= i + (j+1)*(width); + outTris[3*numTris+4]= i+1 + (j+1)*(width); + outTris[3*numTris+5]= i+1 + j *(width); + numTris+=2; + } + } +} + +PxRigidStatic* SampleCharacterCloth::createHeightField(PxReal* heightmap, PxReal hfScale, PxU32 hfSize) +{ + const PxReal heightScale = 0.01f; + + PxU32 hfNumVerts = hfSize*hfSize; + + PxHeightFieldSample* samples = (PxHeightFieldSample*)SAMPLE_ALLOC(sizeof(PxHeightFieldSample)*hfNumVerts); + memset(samples,0,hfNumVerts*sizeof(PxHeightFieldSample)); + + for(PxU32 x = 0; x < hfSize; x++) + for(PxU32 y = 0; y < hfSize; y++) + { + PxI32 h = PxI32(heightmap[y+x*hfSize]/heightScale); + PX_ASSERT(h<=0xffff); + samples[x+y*hfSize].height = (PxI16)(h); + samples[x+y*hfSize].setTessFlag(); + samples[x+y*hfSize].materialIndex0=1; + samples[x+y*hfSize].materialIndex1=1; + } + + PxHeightFieldDesc hfDesc; + hfDesc.format = PxHeightFieldFormat::eS16_TM; + hfDesc.nbColumns = hfSize; + hfDesc.nbRows = hfSize; + hfDesc.samples.data = samples; + hfDesc.samples.stride = sizeof(PxHeightFieldSample); + + PxHeightField* heightField = getCooking().createHeightField(hfDesc, getPhysics().getPhysicsInsertionCallback()); + if(!heightField) + fatalError("creating the heightfield failed"); + + PxTransform pose = PxTransform(PxIdentity); + pose.p = PxVec3(-(hfSize/2*hfScale),0,-(hfSize/2*hfScale)); + mHFPose = pose; + + PxRigidStatic* hfActor = getPhysics().createRigidStatic(pose); + if(!hfActor) + fatalError("creating heightfield actor failed"); + + PxHeightFieldGeometry hfGeom(heightField, PxMeshGeometryFlags(), heightScale, hfScale, hfScale); + PxShape* hfShape = PxRigidActorExt::createExclusiveShape(*hfActor, hfGeom, getDefaultMaterial()); + if(!hfShape) + fatalError("creating heightfield shape failed"); + + getActiveScene().addActor(*hfActor); + + SAMPLE_FREE(samples); + + return hfActor; +} + |