aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Samples/SampleBridges/SampleBridges.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Samples/SampleBridges/SampleBridges.cpp
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'PhysX_3.4/Samples/SampleBridges/SampleBridges.cpp')
-rw-r--r--PhysX_3.4/Samples/SampleBridges/SampleBridges.cpp979
1 files changed, 979 insertions, 0 deletions
diff --git a/PhysX_3.4/Samples/SampleBridges/SampleBridges.cpp b/PhysX_3.4/Samples/SampleBridges/SampleBridges.cpp
new file mode 100644
index 00000000..7894458a
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleBridges/SampleBridges.cpp
@@ -0,0 +1,979 @@
+// 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 "SamplePreprocessor.h"
+#include "SampleBridges.h"
+#include "SampleUtils.h"
+#include "RendererMemoryMacros.h"
+#include "KinematicPlatform.h"
+#include "RenderMaterial.h"
+#include "RenderBaseActor.h"
+#include <SamplePlatform.h>
+#include <SampleUserInput.h>
+#include <SampleBaseInputEventIds.h>
+#include "SampleBridgesInputEventIds.h"
+
+#include "PxPhysicsAPI.h"
+#include "extensions/PxExtensionsAPI.h"
+#include "PsMathUtils.h"
+
+#ifdef CCT_ON_BRIDGES
+#include "characterkinematic/PxControllerManager.h"
+#include "SampleCCTActor.h"
+#include "SampleCCTCameraController.h"
+
+ #define CONTACT_OFFSET 0.01f
+// #define CONTACT_OFFSET 0.1f
+// #define STEP_OFFSET 0.01f
+ #define STEP_OFFSET 0.05f
+// #define STEP_OFFSET 0.1f
+// #define STEP_OFFSET 0.2f
+
+// #define SLOPE_LIMIT 0.8f
+ #define SLOPE_LIMIT 0.0f
+// #define INVISIBLE_WALLS_HEIGHT 6.0f
+ #define INVISIBLE_WALLS_HEIGHT 0.0f
+// #define MAX_JUMP_HEIGHT 4.0f
+ #define MAX_JUMP_HEIGHT 0.0f
+
+ static const float gScaleFactor = 1.5f;
+ static const float gStandingSize = 1.0f * gScaleFactor;
+ static const float gCrouchingSize = 0.25f * gScaleFactor;
+ static const float gControllerRadius = 0.3f * gScaleFactor;
+
+ const char* gPlankName = "Plank";
+ const char* gPlatformName = "Platform";
+
+#endif
+
+using namespace SampleRenderer;
+using namespace SampleFramework;
+
+REGISTER_SAMPLE(SampleBridges, "SampleBridges")
+
+//using namespace physx;
+
+static const bool gBreakableBridges = false;
+static const PxReal gBreakForce = 1.0f;
+//static const PxReal gPlatformSpeed = 100.0f;
+static const PxReal gPlatformSpeed = 10.0f;
+//static const PxReal gPlatformSpeed = 5.0f;
+static const PxReal gGlobalScale = 2.0f;
+
+static const PxReal gBoxUVs[] =
+{
+ 0.0f, 180.0f/256.0f,
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 1.0f, 180.0f/256.0f,
+
+ 0.0f, 180.0f/256.0f,
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 1.0f, 180.0f/256.0f,
+
+ 0.0f, 180.0f/256.0f,
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 1.0f, 180.0f/256.0f,
+
+ 0.0f, 180.0f/256.0f,
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 1.0f, 180.0f/256.0f,
+
+ 0.0f, 180.0f/256.0f,
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 1.0f, 180.0f/256.0f,
+
+ 0.0f, 180.0f/256.0f,
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 1.0f, 180.0f/256.0f,
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+// PT: TODO: use PhysXSampleApplication helper for this
+
+static PxRigidActor* createRigidActor( PxScene& scene, PxPhysics& physics,
+ const PxTransform& pose, const PxGeometry& geometry, PxMaterial& material,
+ const PxFilterData* fd, const PxReal* density, const PxReal* mass, PxU32 flags)
+{
+ const bool isDynamic = (density && *density) || (mass && *mass);
+
+ PxRigidActor* actor = isDynamic ? static_cast<PxRigidActor*>(physics.createRigidDynamic(pose))
+ : static_cast<PxRigidActor*>(physics.createRigidStatic(pose));
+ if(!actor)
+ return NULL;
+
+ PxShape* shape = PxRigidActorExt::createExclusiveShape(*actor, geometry, material);
+ if(!shape)
+ {
+ actor->release();
+ return NULL;
+ }
+
+ if(fd)
+ shape->setSimulationFilterData(*fd);
+
+ if(isDynamic)
+ {
+ PxRigidDynamic* body = static_cast<PxRigidDynamic*>(actor);
+ {
+ if(density)
+ PxRigidBodyExt::updateMassAndInertia(*body, *density);
+ else
+ PxRigidBodyExt::setMassAndUpdateInertia(*body, *mass);
+ }
+ }
+
+ scene.addActor(*actor);
+
+ return actor;
+}
+
+static PxRigidActor* createBox( PxScene& scene, PxPhysics& physics,
+ const PxTransform& pose, const PxVec3& dimensions, const PxReal density, PxMaterial& m, const PxFilterData* fd, PxU32 flags)
+{
+ return createRigidActor(scene, physics, pose, PxBoxGeometry(dimensions), m, fd, &density, NULL, flags);
+}
+
+enum BridgeJoint
+{
+ BRIDGE_REVOLUTE,
+ BRIDGE_SPHERICAL,
+ BRIDGE_FIXED,
+
+ BRIDGE_COUNT
+};
+
+// PT: TODO: share this function with original code in Visual Tests?
+static void buildBridge(PxScene& scene, PxPhysics& physics, PxMaterial& material, std::vector<PxRigidActor*>& actors, std::vector<PxJoint*>& joints, const PxTransform& tr, PxReal scale, BridgeJoint type)
+{
+ const PxVec3 offset(0,0,0);
+
+ const PxReal groundLength = 5.0f;
+ const PxReal groundHeight = 5.0f;
+
+ // create ground under character
+ if(1)
+ {
+ PxTransform boxPose = tr * PxTransform(PxVec3(0.0f, -groundHeight, -10.0f-groundLength)*scale, PxQuat(PxIdentity));
+ boxPose.p += offset;
+
+ const PxVec3 boxSize = PxVec3(1.0f, groundHeight, groundLength) * scale;
+ PxRigidActor* box = createBox(scene, physics, boxPose, boxSize, 0.0f, material, NULL, 0);
+ actors.push_back(box);
+ }
+
+ // create bridge...
+ if(1)
+ {
+ const PxReal plankWidth = 1.0f;
+ const PxReal plankHeight = 0.02f;
+ const PxReal plankDepth = 0.5f;
+ const PxReal plankDensity = 0.03f;
+// const PxReal plankDensity = 0.3f;
+ PxRigidDynamic* lastPlank = 0;
+
+ for(PxReal z = -10.0f+plankDepth; z<10.0f; z+= plankDepth*2)
+ {
+ const PxVec3 boxSize = PxVec3(plankWidth, plankHeight, plankDepth) * scale;
+
+ PxTransform boxPose = tr * PxTransform(PxVec3(0,-plankHeight,z)*scale);
+
+ PxRigidDynamic* plank = createBox(scene, physics, boxPose, boxSize, plankDensity, material, NULL, 0)->is<PxRigidDynamic>();
+ if(plank)
+ {
+#ifdef CCT_ON_BRIDGES
+ plank->setName(gPlankName);
+#endif
+ actors.push_back(plank);
+
+ //plank->setSolverIterationCounts(1, 1);
+// plank->setSolverIterationCounts(255, 255);
+// plank->setSolverIterationCounts(10, 10);
+ plank->setSolverIterationCounts(8, 8);
+ plank->setLinearDamping(1.0f);
+ plank->setAngularDamping(1.0f);
+// plank->putToSleep();
+
+ if(!lastPlank)
+ {
+ // plank = first plank...
+ plank->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
+ }
+ else
+ {
+ // joint together plank and lastPlank...
+ if(type==BRIDGE_REVOLUTE)
+ {
+ PxRevoluteJoint* j = PxRevoluteJointCreate(physics,
+ lastPlank, PxTransform(PxVec3(0,0, plankDepth)*scale),
+ plank, PxTransform(PxVec3(0,0,-plankDepth)*scale));
+ if(j)
+ {
+ j->setProjectionLinearTolerance(0.5f);
+ joints.push_back(j);
+ }
+ }
+ else if(type==BRIDGE_FIXED)
+ {
+ PxFixedJoint* j = PxFixedJointCreate(physics,
+ lastPlank, PxTransform(PxVec3(0,0, plankDepth)*scale),
+ plank, PxTransform(PxVec3(0,0,-plankDepth)*scale));
+ if(j)
+ {
+ j->setProjectionLinearTolerance(0.5f);
+ joints.push_back(j);
+ }
+ }
+ else if(type==BRIDGE_SPHERICAL)
+ {
+ const PxReal plankX = 0.1f;
+ PxSphericalJoint* j1 = PxSphericalJointCreate(physics,
+ lastPlank, PxTransform(PxVec3(plankX, 0.0f, plankDepth)*scale),
+ plank, PxTransform(PxVec3(plankX, 0.0f, -plankDepth)*scale));
+ if(j1)
+ {
+ j1->setProjectionLinearTolerance(0.5f);
+ joints.push_back(j1);
+ }
+
+ PxSphericalJoint* j2 = PxSphericalJointCreate(physics,
+ lastPlank, PxTransform(PxVec3(-plankX, 0.0f, plankDepth)*scale),
+ plank, PxTransform(PxVec3(-plankX, 0.0f, -plankDepth)*scale));
+ if(j2)
+ {
+ j2->setProjectionLinearTolerance(0.5f);
+ joints.push_back(j2);
+ }
+ }
+ else PX_ASSERT(0);
+ }
+ }
+
+ if(gBreakableBridges)
+ {
+ for(PxU32 i=0;i<joints.size();i++)
+ joints[i]->setBreakForce(gBreakForce * scale, gBreakForce * scale);
+ }
+
+ lastPlank = plank;
+ }
+ if(lastPlank)
+ {
+ lastPlank->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
+ }
+ }
+
+ // create ground after bridge
+ if(1)
+ {
+ PxTransform boxPose = tr * PxTransform(PxVec3(0.0f, -groundHeight, 10.0f+groundLength)*scale);
+ boxPose.p += offset;
+
+ const PxVec3 boxSize = PxVec3(1.0f, groundHeight, groundLength) * scale;
+ PxRigidActor* box = createBox(scene, physics, boxPose, boxSize, 0.0f, material, NULL, 0);
+ actors.push_back(box);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SampleBridges::SampleBridges(PhysXSampleApplication& app) :
+ PhysXSample (app),
+#ifdef CCT_ON_BRIDGES
+ mCCTCamera (NULL),
+ mActor (NULL),
+ mControllerManager (NULL),
+#endif
+#ifdef PLATFORMS_AS_OBSTACLES
+ mObstacleContext (NULL),
+ mBoxObstacles (NULL),
+#endif
+ mGlobalScale (gGlobalScale),
+ mCurrentPlatform (0xffffffff),
+ mElapsedRenderTime (0.0f),
+ mRockMaterial (NULL),
+ mWoodMaterial (NULL),
+ mPlatformMaterial (NULL),
+ mBomb (NULL),
+ mBombTimer (0.0f),
+ mWaterY (0.0f),
+ mMustResync (false),
+ mEnableCCTDebugRender (false)
+{
+#ifdef CCT_ON_BRIDGES
+ mControllerInitialPosition = PxExtendedVec3(18.0f, 2.0f, -64.0f);
+#endif
+ mCreateGroundPlane = false;
+ //mStepperType = FIXED_STEPPER;
+ mDefaultDensity = 0.1f;
+// mDefaultDensity = 1.0f;
+
+}
+
+SampleBridges::~SampleBridges()
+{
+#ifdef CCT_ON_BRIDGES
+ DELETESINGLE(mActor);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleBridges::customizeSample(SampleSetup& setup)
+{
+ setup.mName = "SampleBridges";
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// PT: this is called from the RAW-loader when loading a scene. The default behavior
+// in PhysXSampleApplication creates a physics and a graphics mesh for each exported object. We
+// intercept the call here to disable the physics mesh for the "water plane".
+void SampleBridges::newMesh(const RAWMesh& data)
+{
+ if(data.mName && (Ps::strcmp(data.mName, "WaterPlane")==0 || Ps::strcmp(data.mName, "skyshape")==0))
+ {
+ // PT: create render mesh only (not physics) for the waterplane & skyboxes
+ createRenderMeshFromRawMesh(data);
+ if(Ps::strcmp(data.mName, "WaterPlane")==0)
+ mWaterY = data.mTransform.p.y;
+ return;
+ }
+ PhysXSample::newMesh(data);
+}
+
+// PT: this is a callback from the RAW-loader, used to import a new shape. We use
+// simple segment shapes in the MAX scene to define where our bridges should be.
+void SampleBridges::newShape(const RAWShape& data)
+{
+ if(data.mName)
+ {
+ if(::strcmp(data.mName, "Bridge")==0)
+ {
+ PX_ASSERT(data.mNbVerts==2);
+ const PxVec3 p0 = data.mTransform.transform(data.mVerts[0]);
+ const PxVec3 p1 = data.mTransform.transform(data.mVerts[1]);
+ const PxVec3 center = (p0 + p1)*0.5f;
+
+ PxVec3 dir, right, up;
+ Ps::computeBasis(p0, p1, dir, right, up);
+
+ PxMat33 m(right, up, dir);
+ PxTransform tr;
+ tr.p = center;
+ tr.q = PxQuat(m);
+
+ const float l = (p1 - p0).magnitude();
+ const float coeff = l / 80.0f;
+
+ float scale = 2.0f * coeff;
+ // float scale = 4.0f * coeff;
+ // float scale = 1.0f;
+
+ BridgeJoint type = BRIDGE_REVOLUTE;
+ {
+ static int count=0;
+ if(count==0)
+ type = BRIDGE_REVOLUTE;
+ else if(count==1)
+ type = BRIDGE_SPHERICAL;
+ else if(count==2)
+ type = BRIDGE_FIXED;
+ else PX_ASSERT(0);
+
+ count++;
+ if(count==BRIDGE_COUNT)
+ count = 0;
+ }
+
+ std::vector<PxRigidActor*> bridgeActors;
+ buildBridge(getActiveScene(), getPhysics(), getDefaultMaterial(), bridgeActors, mJoints, tr, scale, type);
+
+ for(PxU32 i=0;i<bridgeActors.size();i++)
+ {
+ RenderMaterial* m = (i==0 || i==bridgeActors.size()-1) ? mRockMaterial : mWoodMaterial;
+
+ PX_ASSERT(bridgeActors[i]->getNbShapes()==1);
+ PxShape* boxShape;
+ PxU32 nb = bridgeActors[i]->getShapes(&boxShape, 1);
+ PX_ASSERT(nb==1);
+ PX_UNUSED(nb);
+ createRenderBoxFromShape(bridgeActors[i], boxShape, m, gBoxUVs);
+ }
+ }
+ else if(::strcmp(data.mName, "Platform")==0)
+ {
+ const PxTransform idt = PxTransform(PxIdentity);
+
+ PxRigidDynamic* platformActor = (PxRigidDynamic*)::createBox(getActiveScene(), getPhysics(), idt, gGlobalScale * PxVec3(1.0f, 5.0f, 5.0f), 1.0f, getDefaultMaterial(), NULL, 0);
+#ifdef CCT_ON_BRIDGES
+ platformActor->setName(gPlatformName);
+#endif
+ platformActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
+
+// createRenderObjectsFromActor(platformActor, mPlatformMaterial);
+ PxShape* platformShape = NULL;
+ platformActor->getShapes(&platformShape, 1);
+ PX_ASSERT(platformShape);
+ RenderBaseActor* renderActor = createRenderObjectFromShape(platformActor, platformShape, mPlatformMaterial);
+
+#ifdef PLATFORMS_AS_OBSTACLES
+// platformShape->userData = NULL;
+ renderActor->setPhysicsShape(NULL, NULL);
+ PxBounds3 maxBounds;
+ maxBounds.setMaximal();
+ renderActor->setWorldBounds(maxBounds);
+#else
+ PX_UNUSED(renderActor);
+#endif
+
+#ifdef ROTATING_PLATFORMS
+ const PxF32 rotationSpeed = 0.5f;
+#else
+ const PxF32 rotationSpeed = 0.0f;
+#endif
+ const PxVec3 up(0.0f, 1.0f, 0.0f);
+ const PxQuat q = PxShortestRotation(PxVec3(1.0f, 0.0f, 0.0f), up);
+
+ mPlatformManager.createPlatform(data.mNbVerts, data.mVerts, data.mTransform, q, platformActor, gPlatformSpeed, rotationSpeed);
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleBridges::onInit()
+{
+ PhysXSample::onInit();
+ PxSceneWriteLock scopedLock(*mScene);
+
+ mApplication.setMouseCursorHiding(true);
+ mApplication.setMouseCursorRecentering(true);
+
+ getRenderer()->setAmbientColor(RendererColor(170, 170, 170));
+// mScene->setGravity(PxVec3(0.0f, -98.1f, 0.0f));
+ getActiveScene().setGravity(PxVec3(0.0f, -9.81f, 0.0f));
+
+ {
+ {
+ RAWTexture data;
+ data.mName = "rock_distance_diffuse.tga";
+ RenderTexture* rockTexture = createRenderTextureFromRawTexture(data);
+
+ mRockMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(), PxVec3(1.0f, 1.0f, 1.0f), 1.0f, false, 0xffffffff, rockTexture);
+ mRenderMaterials.push_back(mRockMaterial);
+ }
+
+ {
+ RAWTexture data;
+ data.mName = "pier_diffuse.dds";
+ RenderTexture* woodTexture = createRenderTextureFromRawTexture(data);
+
+ mWoodMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(), PxVec3(1.0f, 1.0f, 1.0f), 1.0f, false, 0xffffffff, woodTexture);
+ mRenderMaterials.push_back(mWoodMaterial);
+ }
+
+ {
+ RAWTexture data;
+ data.mName = "divingBoardFloor_diffuse.dds";
+ RenderTexture* platformTexture = createRenderTextureFromRawTexture(data);
+
+ mPlatformMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(), PxVec3(1.0f, 1.0f, 1.0f), 1.0f, false, 0xffffffff, platformTexture);
+ mRenderMaterials.push_back(mPlatformMaterial);
+ }
+
+ importRAWFile("SampleBridges.raw", gGlobalScale);
+ importRAWFile("sky_mission_race1.raw", 1.0f);
+ }
+
+#ifdef CCT_ON_BRIDGES
+ mControllerManager = PxCreateControllerManager(getActiveScene());
+
+ ControlledActorDesc desc;
+ desc.mType = PxControllerShapeType::eCAPSULE;
+ desc.mPosition = mControllerInitialPosition;
+ desc.mSlopeLimit = SLOPE_LIMIT;
+ desc.mContactOffset = CONTACT_OFFSET;
+ desc.mStepOffset = STEP_OFFSET;
+ desc.mInvisibleWallHeight = INVISIBLE_WALLS_HEIGHT;
+ desc.mMaxJumpHeight = MAX_JUMP_HEIGHT;
+ desc.mRadius = gControllerRadius;
+ desc.mHeight = gStandingSize;
+ desc.mCrouchHeight = gCrouchingSize;
+ desc.mReportCallback = this;
+ desc.mBehaviorCallback = this;
+
+ {
+ mActor = SAMPLE_NEW(ControlledActor)(*this);
+ mActor->init(desc, mControllerManager);
+
+ RenderBaseActor* actor0 = mActor->getRenderActorStanding();
+ RenderBaseActor* actor1 = mActor->getRenderActorCrouching();
+ if(actor0)
+ mRenderActors.push_back(actor0);
+ if(actor1)
+ mRenderActors.push_back(actor1);
+ }
+
+ mCCTCamera = SAMPLE_NEW(SampleCCTCameraController)(*this);
+ mCCTCamera->setControlled(&mActor, 0, 1);
+// mCCTCamera->setFilterData();
+ mCCTCamera->setFilterCallback(this);
+ mCCTCamera->setGravity(-20.0f);
+
+ setCameraController(mCCTCamera);
+
+ mCCTCamera->setView(0,0);
+
+ #ifdef PLATFORMS_AS_OBSTACLES
+ mObstacleContext = mControllerManager->createObstacleContext();
+ mCCTCamera->setObstacleContext(mObstacleContext);
+
+ const PxVec3 up(0.0f, 1.0f, 0.0f);
+ const PxQuat q = PxShortestRotation(PxVec3(1.0f, 0.0f, 0.0f), up);
+
+ const PxU32 nbPlatforms = mPlatformManager.getNbPlatforms();
+ KinematicPlatform** platforms = mPlatformManager.getPlatforms();
+ mBoxObstacles = new PxBoxObstacle[nbPlatforms];
+ for(PxU32 i=0;i<nbPlatforms;i++)
+ {
+ mBoxObstacles[i].mPos.x = 0.0;
+ mBoxObstacles[i].mPos.y = 0.0;
+ mBoxObstacles[i].mPos.z = 0.0;
+ mBoxObstacles[i].mRot = q;
+ mBoxObstacles[i].mHalfExtents = gGlobalScale * PxVec3(1.0f, 5.0f, 5.0f);
+// mBoxObstacles[i].mHalfExtents = gGlobalScale * PxVec3(5.0f, 1.0f, 5.0f);
+ const ObstacleHandle handle = mObstacleContext->addObstacle(mBoxObstacles[i]);
+ platforms[i]->setBoxObstacle(handle, mBoxObstacles + i);
+ }
+ #endif
+
+// mCCTCamera->setCameraLinkToPhysics(true);
+#endif
+
+// mScene->setVisualizationParameter(PxVisualizationParameter::eCONTACT_NORMAL, 1.0f);
+// mScene->setVisualizationParameter(PxVisualizationParameter::eJOINT_LOCAL_FRAMES, 1.0f);
+
+// advanceSimulation(4.0f);
+}
+
+void SampleBridges::onShutdown()
+{
+ {
+ PxSceneWriteLock scopedLock(*mScene);
+#ifdef CCT_ON_BRIDGES
+ DELETESINGLE(mCCTCamera);
+ #ifdef PLATFORMS_AS_OBSTACLES
+ SAFE_RELEASE(mObstacleContext);
+ DELETEARRAY(mBoxObstacles);
+ #endif
+ mControllerManager->release();
+#endif
+ const size_t nbJoints = mJoints.size();
+ for(PxU32 i=0;i<nbJoints;i++)
+ if(mJoints[i])
+ mJoints[i]->release();
+ mJoints.clear();
+ }
+
+
+ mPlatformManager.release();
+
+ PhysXSample::onShutdown();
+}
+
+// PT: very crude attempt here, just to have something running
+static void applyBombForce(PxRigidActor* actor, const PxVec3& actorPos, const PxVec3& bombPos, PxReal bombRange)
+{
+ PxRigidDynamic* dyna = actor->is<PxRigidDynamic>();
+ if(dyna)
+ {
+ PxVec3 dir = (actorPos - bombPos);
+ const PxReal m = dir.magnitude();
+ if(m<bombRange)
+ {
+ const PxReal coeff = (1.0f - m/bombRange) * 50.0f;
+ dir /= m;
+// dyna->addForce(dir*coeff);
+
+ PxBounds3 worldBounds = dyna->getWorldBounds();
+
+ const PxVec3 center = worldBounds.getCenter();
+ const PxVec3 extents = worldBounds.getExtents();
+ const PxVec3 axis0(extents.x, 0.0f, 0.0f);
+ const PxVec3 axis1(0.0f, extents.y, 0.0f);
+ const PxVec3 axis2(0.0f, 0.0f, extents.z);
+
+ PxVec3 pts[8];
+ pts[0] = pts[3] = pts[4] = pts[7] = center - axis0;
+ pts[1] = pts[2] = pts[5] = pts[6] = center + axis0;
+
+ PxVec3 tmp = axis1 + axis2;
+ pts[0] -= tmp;
+ pts[1] -= tmp;
+ pts[6] += tmp;
+ pts[7] += tmp;
+
+ tmp = axis1 - axis2;
+ pts[2] += tmp;
+ pts[3] += tmp;
+ pts[4] -= tmp;
+ pts[5] -= tmp;
+
+ PxReal minDist = 1e+30f;
+ PxU32 index = 0;
+ for(PxU32 i=0;i<8;i++)
+ {
+ PxReal d2 = (pts[i] - bombPos).magnitudeSquared();
+ if(d2<minDist)
+ {
+ minDist = d2;
+ index = i;
+ }
+ }
+
+ PxRigidBodyExt::addForceAtPos(*dyna, dir*coeff, pts[index]);
+// PxRigidBodyExt::addForceAtPos(*dyna, dir*coeff, actorPos);
+ }
+ }
+}
+
+template<class T>
+bool findAndReplaceWithLast(std::vector<T*>& array, T* ptr)
+{
+ const size_t s = array.size();
+ for(PxU32 j=0; j<s; j++)
+ {
+ if(array[j]==ptr)
+ {
+ T* last = array[s-1];
+ array.pop_back();
+ if(j!=s-1)
+ array[j] = last;
+ return true;
+ }
+ }
+ return false;
+}
+
+void SampleBridges::onTickPreRender(float dtime)
+{
+// shdfnd::printFormatted("SampleBridges::onTickPreRender\n");
+
+ const bool paused = isPaused();
+
+ // PT: keep track of elapsed render time
+ if(!paused)
+ mElapsedRenderTime += dtime;
+
+#ifdef CCT_ON_BRIDGES
+// const bool postUpdate = mCCTCamera->getCameraLinkToPhysics();
+ const bool postUpdate = true;
+// const bool postUpdate = false;
+
+ if(!postUpdate && !mPause)
+ {
+// shdfnd::printFormatted("CCT sync\n");
+ mActor->sync();
+ }
+#endif
+
+ if(!paused)
+ {
+// mPlatformManager.updatePhysicsPlatforms(dtime);
+
+ if(mBomb)
+ {
+ mBombTimer -= dtime;
+ if(mBombTimer<0.0f)
+ {
+ PxSceneWriteLock scopedLock(*mScene);
+ mBombTimer = 0.0f;
+
+ {
+ const PxVec3 bombPos = mBomb->getGlobalPose().p;
+ const PxReal bombActorRange = 30.0f;
+ const PxReal bombJointRange = 10.0f;
+ size_t nbJoints = mJoints.size();
+ for(PxU32 i=0;i<nbJoints;i++)
+ {
+ PxJoint* j = mJoints[i];
+ if(!j)
+ continue;
+
+ PxRigidActor* actor0;
+ PxRigidActor* actor1;
+ j->getActors(actor0, actor1);
+ const PxVec3 actorPos0 = actor0->getGlobalPose().p;
+ const PxVec3 actorPos1 = actor1->getGlobalPose().p;
+
+ applyBombForce(actor0, actorPos0, bombPos, bombActorRange);
+ applyBombForce(actor1, actorPos1, bombPos, bombActorRange);
+
+ const PxVec3 jointPos = (actorPos0 + actorPos1)*0.5f;
+ const PxReal d2 = (bombPos - jointPos).magnitudeSquared();
+ if(d2<bombJointRange*bombJointRange)
+ {
+ j->release();
+ mJoints[i] = NULL;
+ }
+ }
+ }
+
+ {
+ PxU32 nbShapes = mBomb->getNbShapes();
+ PxShape** shapes = (PxShape**)SAMPLE_ALLOC(sizeof(PxShape*)*nbShapes);
+ PxU32 nb = mBomb->getShapes(shapes, nbShapes);
+ PX_ASSERT(nb==nbShapes);
+ PX_UNUSED(nb);
+ for(PxU32 i=0;i<nbShapes;i++)
+ {
+ PxShape* currentShape = shapes[i];
+
+ RenderBaseActor* renderActor = getRenderActor(mBomb, currentShape);
+ unlink(renderActor, currentShape, mBomb);
+
+ findAndReplaceWithLast(mRenderActors, renderActor);
+
+ renderActor->release();
+ }
+ SAMPLE_FREE(shapes);
+ }
+
+ findAndReplaceWithLast(mPhysicsActors, mBomb);
+
+ SAFE_RELEASE(mBomb);
+ }
+ }
+ }
+
+ PhysXSample::onTickPreRender(dtime);
+
+#ifdef PLATFORMS_AS_OBSTACLES
+ if(!paused)
+ updateRenderPlatforms(dtime);
+#endif
+
+#ifdef CCT_ON_BRIDGES
+ if(postUpdate && !mPause)
+ {
+// shdfnd::printFormatted("CCT sync\n");
+ mActor->sync();
+ }
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleBridges::onTickPostRender(float dtime)
+{
+ PhysXSample::onTickPostRender(dtime);
+
+ // PT: add CCT's internal debug rendering
+ if(mEnableCCTDebugRender)
+ {
+ mControllerManager->setDebugRenderingFlags(PxControllerDebugRenderFlag::eALL);
+ PxRenderBuffer& renderBuffer = mControllerManager->getRenderBuffer();
+ RenderPhysX3Debug* renderer = getDebugRenderer();
+ renderer->update(renderBuffer);
+ renderBuffer.clear();
+ }
+ else
+ {
+ mControllerManager->setDebugRenderingFlags(PxControllerDebugRenderFlag::eNONE);
+ }
+
+#ifdef CCT_ON_BRIDGES
+// mControllerManager->setDebugRenderingFlags(PxControllerDebugRenderFlag::eCACHED_BV|PxControllerDebugRenderFlag::eTEMPORAL_BV);
+ PxRenderBuffer& renderBuffer = mControllerManager->getRenderBuffer();
+ getDebugRenderer()->update(renderBuffer);
+ renderBuffer.clear();
+#endif
+
+ const float lag = fabsf(mPlatformManager.getElapsedTime() - mElapsedRenderTime);
+ mMustResync = lag > 1.0f/60.0f;
+
+ if(0)
+ {
+ shdfnd::printFormatted("Render time: %f\n", mElapsedRenderTime);
+ shdfnd::printFormatted("Platform time: %f\n", mPlatformManager.getElapsedTime());
+ shdfnd::printFormatted("Delta: %f\n", lag);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef PLATFORMS_AS_OBSTACLES
+void SampleBridges::updateRenderPlatforms(float dtime)
+{
+ // PT: compute new positions for (render) platforms, then move their corresponding obstacles to these positions.
+ const PxU32 nbPlatforms = mPlatformManager.getNbPlatforms();
+ KinematicPlatform** platforms = mPlatformManager.getPlatforms();
+
+ {
+ PxSceneReadLock scopedLock(*mScene);
+
+ for(PxU32 i=0;i<nbPlatforms;i++)
+ {
+ if(1)
+ {
+ PxRigidDynamic* actor = platforms[i]->getPhysicsActor();
+ PxShape* shape = NULL;
+ actor->getShapes(&shape, 1);
+ RenderBaseActor* renderActor = getRenderActor(actor, shape);
+ renderActor->setTransform(platforms[i]->getRenderPose());
+ }
+
+ platforms[i]->updateRender(dtime, mObstacleContext);
+ }
+ }
+
+ // PT: if render time & physics time varies too much, we must resync the physics to avoid large visual mismatchs
+ if(mMustResync)
+ {
+ PxSceneWriteLock scopedLock(*mScene);
+
+// mElapsedPlatformTime = mElapsedRenderTime;
+ mPlatformManager.syncElapsedTime(mElapsedRenderTime);
+// static int count=0; shdfnd::printFormatted("Resync %d\n", count++);
+ for(PxU32 i=0;i<nbPlatforms;i++)
+ {
+ PxRigidDynamic* actor = platforms[i]->getPhysicsActor();
+ actor->setKinematicTarget(platforms[i]->getRenderPose());
+ platforms[i]->resync();
+ }
+ }
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleBridges::onSubstep(float dtime)
+{
+// shdfnd::printFormatted("onSubstep\n");
+ mPlatformManager.updatePhysicsPlatforms(dtime);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleBridges::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 crouch", CAMERA_CROUCH,-1);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor); ;
+ msg = mApplication.inputInfoMsg("Press "," to throw an object", SPAWN_DEBUG_OBJECT, -1);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor); ;
+ msg = mApplication.inputInfoMsg("Press "," to reset CCT position", RETRY,-1);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
+ msg = mApplication.inputInfoMsg("Press "," to teleport from one platform to another", TELEPORT,-1);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
+}
+
+void SampleBridges::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 configuration and run-time control of the";
+ char line1[256]="PhysX kinematic character controller (cct). In particular, the";
+ char line2[256]="interaction between the cct and both kinematic and dynamic scene objects";
+ char line3[256]="is presented. Jointed bridges with a variety of configurations are also";
+ char line4[256]="added to the scene to illustrate the setup code and behavior of some of";
+ char line5[256]="the different joint types supported by the PhysX SDK.";
+
+ 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);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleBridges::customizeRender()
+{
+ // PT: add a simple screenquad when underwater
+ if(getCamera().getPos().y<mWaterY)
+ {
+ const RendererColor color(0, 90, 90);
+ ScreenQuad sq;
+ sq.mLeftUpColor = color;
+ sq.mRightUpColor = color;
+ sq.mLeftDownColor = color;
+ sq.mRightDownColor = color;
+ sq.mAlpha = 0.75;
+
+ getRenderer()->drawScreenQuad(sq);
+ }
+}
+