aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Samples/SampleLargeWorld/SampleLargeWorld.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/SampleLargeWorld/SampleLargeWorld.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/SampleLargeWorld/SampleLargeWorld.cpp')
-rw-r--r--PhysX_3.4/Samples/SampleLargeWorld/SampleLargeWorld.cpp1039
1 files changed, 1039 insertions, 0 deletions
diff --git a/PhysX_3.4/Samples/SampleLargeWorld/SampleLargeWorld.cpp b/PhysX_3.4/Samples/SampleLargeWorld/SampleLargeWorld.cpp
new file mode 100644
index 00000000..22db15c9
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleLargeWorld/SampleLargeWorld.cpp
@@ -0,0 +1,1039 @@
+// 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 "foundation/PxMemory.h"
+#include <PsString.h>
+#include "SampleLargeWorld.h"
+#include "RenderMeshActor.h"
+#include "RenderMaterial.h"
+
+#include <SampleBaseInputEventIds.h>
+#include <SamplePlatform.h>
+#include <SampleUserInput.h>
+#include <SampleUserInputIds.h>
+#include <SampleUserInputDefines.h>
+#include "SampleLargeWorldInputEventIds.h"
+
+using namespace SampleRenderer;
+using namespace SampleFramework;
+
+#include "ChunkLoader.h"
+#include "wavefront.h"
+#include "characterkinematic/PxControllerManager.h"
+#include "SampleCCTActor.h"
+#include "SampleCCTCameraController.h"
+
+#include "extensions/PxDefaultSimulationFilterShader.h"
+
+static const PxF32 gContactOffset = 0.01f;
+static const PxF32 gStepOffset = 0.05f;
+static const PxF32 gSlopeLimit = 0.0f;
+static const PxF32 gInvisibleWallsHeight = 0.0f;
+static const PxF32 gMaxJumpHeight = 0.0f;
+
+static const PxF32 gScaleFactor = 1.5f;
+static const PxF32 gStandingSize = 1.0f * gScaleFactor;
+static const PxF32 gCrouchingSize = 0.25f * gScaleFactor;
+static const PxF32 gControllerRadius = 0.3f * gScaleFactor;
+
+static const PxF32 CAMERA_MAX_SPEED = 120.0f;
+
+const char* gDynamic = "Dynamic";
+
+REGISTER_SAMPLE(SampleLargeWorld, "SampleLargeWorld")
+
+///////////////////////////////////////////////////////////////////////////////
+SampleLargeWorld::SampleLargeWorld(PhysXSampleApplication& app)
+ : PhysXSample(app)
+ , mCCTCamera(NULL)
+ , mActor(NULL)
+ , mControllerManager(NULL)
+ , mDiskIOTime(0)
+ , mPhysxStreaming(0)
+ , mGraphicStreaming(0)
+ , mReadyToSyncCCT(false)
+ , mAddRenderActor(false)
+ , mPick(false)
+ , mKeyShiftDown(false)
+ , mStringTable(NULL)
+{
+ mCreateGroundPlane = false;
+ mControllerInitialPosition = PxExtendedVec3(1035.0f, 49.0f, 989.0f);
+ mLastCCTPosition = mControllerInitialPosition;
+ mDefaultCameraSpeed = mCameraController.getCameraSpeed();
+
+ PxMemZero(mSkybox, sizeof(mSkybox));
+}
+
+SampleLargeWorld::~SampleLargeWorld()
+{
+ DELETESINGLE(mActor);
+ for(ObjMeshMap::Iterator iter = mRenderMeshCache.getIterator(); !iter.done(); ++iter)
+ {
+ RAWMesh& mesh = iter->second;
+
+ PxVec3 *verts = const_cast<PxVec3*>(mesh.mVerts);
+ SAMPLE_FREE(verts);
+ mesh.mVerts = NULL;
+
+ PxVec3 *normals = const_cast<PxVec3*>(mesh.mVertexNormals);
+ SAMPLE_FREE(normals);
+ mesh.mVertexNormals = NULL;
+
+ PxVec3 *colors = const_cast<PxVec3*>(mesh.mVertexColors);
+ SAMPLE_FREE(colors);
+ mesh.mVertexColors = NULL;
+
+ PxReal *uvs = const_cast<PxReal*>(mesh.mUVs);
+ SAMPLE_FREE(uvs);
+ mesh.mUVs = NULL;
+
+ PxU32 *indices = const_cast<PxU32*>(mesh.mIndices);
+ SAMPLE_FREE(indices);
+ mesh.mIndices = NULL;
+ }
+}
+
+void SampleLargeWorld::setCCDActive(PxShape& shape)
+{
+ PxFilterData fd = shape.getSimulationFilterData();
+ fd.word3 |= CCD_FLAG;
+ shape.setSimulationFilterData(fd);
+}
+
+bool SampleLargeWorld::isCCDActive(PxFilterData& filterData)
+{
+ return filterData.word3 & CCD_FLAG ? true : false;
+}
+
+PxFilterFlags SampleLargeWorld::filter( PxFilterObjectAttributes attributes0,
+ PxFilterData filterData0,
+ PxFilterObjectAttributes attributes1,
+ PxFilterData filterData1,
+ PxPairFlags& pairFlags,
+ const void* constantBlock,
+ PxU32 constantBlockSize)
+{
+ PxFilterFlags filterFlags = PxDefaultSimulationFilterShader(attributes0,
+ filterData0, attributes1, filterData1, pairFlags, constantBlock, constantBlockSize);
+
+ if (isCCDActive(filterData0) && isCCDActive(filterData1))
+ {
+ pairFlags |= PxPairFlag::eSOLVE_CONTACT;
+ pairFlags |= PxPairFlag::eDETECT_CCD_CONTACT;
+ }
+
+ return filterFlags;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if PX_INTEL_FAMILY
+static const bool gFlip = false;
+#elif PX_PPC
+static const bool gFlip = true;
+#elif PX_ARM_FAMILY
+static const bool gFlip = false;
+#else
+#error Unknown platform!
+#endif
+
+static PX_INLINE void Flip(PxU32& v)
+{
+ PxU8* b = (PxU8*)&v;
+
+ PxU8 temp = b[0];
+ b[0] = b[3];
+ b[3] = temp;
+ temp = b[1];
+ b[1] = b[2];
+ b[2] = temp;
+}
+
+static PX_INLINE void Flip(PxF32& v)
+{
+ Flip((PxU32&)v);
+}
+
+class PxBinFile: public PxDefaultFileInputData
+{
+public:
+ PxBinFile(const char* name):PxDefaultFileInputData(name){}
+ ~PxBinFile(){}
+
+ PX_FORCE_INLINE PxU32 LoadDword(){ PxU32 t; read(&t, sizeof(PxU32)); if(gFlip) Flip(t); return t;}
+ PX_FORCE_INLINE PxF32 LoadFloat(){ PxF32 t; read(&t, sizeof(PxF32)); if(gFlip) Flip(t); return t;}
+};
+
+void SampleLargeWorld::BinData::serialize( SampleLargeWorld* parent, const char* terrainFile)
+{
+ PxBinFile binFile(terrainFile);
+
+ if( !binFile.isValid())
+ {
+ char errMsg[256];
+ Ps::snprintf(errMsg, 256, "Couldn't load %s\n", terrainFile);
+ parent->fatalError(errMsg);
+
+ return;
+ }
+
+ PxU32 nbMeshes = binFile.LoadDword();
+
+ //Suppose the terrain is N*N
+ mDim = (CoordType)PxSqrt((PxF32)nbMeshes);
+
+ PxU32 totalNbTris = 0;
+ PxU32 totalNbVerts = 0;
+
+ mTerrainVertices.resize( nbMeshes );
+ mTerrainIndices.resize( nbMeshes );
+
+ for(PxU32 i = 0; i < nbMeshes; ++i)
+ {
+ binFile.LoadDword();
+ binFile.LoadDword();
+
+ const PxU32 nbVerts = binFile.LoadDword();
+ const PxU32 nbFaces = binFile.LoadDword();
+
+ totalNbTris += nbFaces;
+ totalNbVerts += nbVerts;
+
+ SampleArray<PxVec3>& vertices = mTerrainVertices[i];
+ vertices.resize(nbVerts);
+
+ for(PxU32 j = 0; j < nbVerts; ++j)
+ {
+ vertices[j].x = binFile.LoadFloat();
+ vertices[j].y = binFile.LoadFloat();
+ vertices[j].z = binFile.LoadFloat();
+ }
+
+ SampleArray<PxU32>& indices = mTerrainIndices[i];
+ indices.resize(nbFaces * 3);
+
+ for(PxU32 j = 0; j < nbFaces * 3; ++j)
+ {
+ indices[j] = binFile.LoadDword();
+ }
+ }
+}
+
+//Hardcoded terrain.bin terrain.
+void SampleLargeWorld::onInit()
+{
+ PhysXSample::onInit();
+ mCameraController.setCameraSpeed( 2.0f );
+
+ mStringTable = &PxStringTableExt::createStringTable( Ps::getAllocator() );
+
+ mApplication.setMouseCursorHiding(true);
+ mApplication.setMouseCursorRecentering(true);
+
+ //Disable collision between differnt groups
+ PxSetGroupCollisionFlag(DEFAULT_COLLISION_GROUP,FAN_COLLISION_GROUP,false);
+ PxSetGroupCollisionFlag(DEFAULT_COLLISION_GROUP,PICKING_COLLISION_GROUP,false);
+ PxSetGroupCollisionFlag(FAN_COLLISION_GROUP,PICKING_COLLISION_GROUP,false);
+
+ mBGLoader = SAMPLE_NEW(BackgroundLoader)(*this, N1, N2-1, CHUNK_WIDTH);
+
+ const char* terrainFile = getSampleMediaFilename("Terrain.bin");
+ binData.serialize(this, terrainFile);
+
+ //Load the skydome.
+ importRAWFile("sky_mission_race1.raw", 2.0f);
+
+ //Load the terrain material
+ {
+ RAWTexture data;
+ data.mName = "grass_diffuse.dds";
+ RenderTexture* grassTexture = createRenderTextureFromRawTexture(data);
+ RenderMaterial* roadGravelMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(),
+ PxVec3(1.0f, 1.0f, 1.0f), 1.0f, false, MATERIAL_ROAD_GRASS, grassTexture);
+ mRenderMaterials.push_back(roadGravelMaterial);
+ }
+
+ {
+ RAWTexture data;
+ data.mName = "DiffuseMap.bmp";
+ RenderTexture* bricksTexture = createRenderTextureFromRawTexture(data);
+ RenderMaterial* bricksMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(),
+ PxVec3(1.0f, 1.0f, 1.0f), 1.0f, false, MATERIAL_BUILDING, bricksTexture);
+ mRenderMaterials.push_back(bricksMaterial);
+ }
+ {
+ RAWTexture data;
+ data.mName = "Fencing.tga";
+ RenderTexture* fencingTexture = createRenderTextureFromRawTexture(data);
+ RenderMaterial* fencingMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(),
+ PxVec3(1.0f, 1.0f, 1.0f), 1.0f, false, MATERIAL_FARM, fencingTexture);
+ mRenderMaterials.push_back(fencingMaterial);
+ }
+ {
+ RAWTexture data;
+ data.mName = "Yellow_0.bmp";
+ RenderTexture* treeTexture = createRenderTextureFromRawTexture(data);
+ RenderMaterial* treeMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(),
+ PxVec3(1.0f, 1.0f, 1.0f), 1.0f, false, MATERIAL_TREE, treeTexture);
+ mRenderMaterials.push_back(treeMaterial);
+ }
+ //Set up the fog.
+ getRenderer()->setFog(SampleRenderer::RendererColor(40,40,40), 225.0f);
+
+ mControllerManager = PxCreateControllerManager(getActiveScene());
+ mControllerManager->setOverlapRecoveryModule(false);
+
+ ControlledActorDesc desc;
+ desc.mType = PxControllerShapeType::eCAPSULE;
+ desc.mPosition = mControllerInitialPosition;
+ desc.mSlopeLimit = gSlopeLimit;
+ desc.mContactOffset = gContactOffset;
+ desc.mStepOffset = gStepOffset;
+ desc.mInvisibleWallHeight = gInvisibleWallsHeight;
+ desc.mMaxJumpHeight = gMaxJumpHeight;
+ desc.mRadius = gControllerRadius;
+ desc.mHeight = gStandingSize;
+ desc.mCrouchHeight = gCrouchingSize;
+ desc.mReportCallback = this;
+ desc.mBehaviorCallback = this;
+ {
+ mActor = SAMPLE_NEW(ControlledActor)(*this);
+
+ {
+ PxSceneWriteLock scopedLock(*mScene);
+ mActor->init(desc, mControllerManager);
+ }
+
+ mCCTCamera = SAMPLE_NEW(SampleCCTCameraController)(*this);
+ mCCTCamera->setControlled(&mActor, 0, 1);
+ mCCTCamera->setFilterCallback(this);
+ mCCTCamera->setGravity(-20.0f);
+
+ setCameraController(mCCTCamera);
+
+ mCCTCamera->setView(0,0);
+ mCCTCamera->setCameraMaxSpeed( CAMERA_MAX_SPEED );
+ mCCTCamera->enableCCT(false);
+ }
+
+ mWorldBound.minimum = PxVec3(-128.0f,-256.0f, -128.0f);
+ mWorldBound.maximum = PxVec3(-128.0f + 256.0f*N2,256.0f, -128.0f + 256.0f*N2);
+}
+
+void SampleLargeWorld::onShutdown()
+{
+ mCameraController.setCameraSpeed(mDefaultCameraSpeed);
+
+ if(isPaused())
+ {
+ togglePause();
+ }
+
+ mScene->fetchResults(true);
+ DELETESINGLE(mBGLoader);
+
+ {
+ PxSceneWriteLock scopedLock(*mScene);
+
+ if( !mAddRenderActor )
+ {
+ RenderBaseActor* actor = mActor->getRenderActorStanding();
+ DELETESINGLE( actor );
+
+ actor = mActor->getRenderActorCrouching();
+ DELETESINGLE( actor );
+ }
+
+ DELETESINGLE(mCCTCamera);
+ mControllerManager->release();
+
+ releaseJoints();
+ }
+
+ if(mStringTable)
+ {
+ mStringTable->release();
+ mStringTable = NULL;
+ }
+
+ PhysXSample::onShutdown();
+}
+
+void SampleLargeWorld::onTickPreRender(PxF32 dtime)
+{
+ if(!mPause)
+ {
+ mBGLoader->onTick();
+
+ //add render actor here, otherwise it has issues on render
+ if(!mReadyToSyncCCT)
+ {
+ mReadyToSyncCCT = readyToSyncCCT();
+ }
+
+ if( !mAddRenderActor && mReadyToSyncCCT )
+ {
+ RenderBaseActor* actor0 = mActor->getRenderActorStanding();
+ RenderBaseActor* actor1 = mActor->getRenderActorCrouching();
+
+ if(actor0)
+ {
+ mRenderActors.push_back(actor0);
+ }
+
+ if(actor1)
+ {
+ mRenderActors.push_back(actor1);
+ }
+
+ mAddRenderActor = true;
+ }
+
+ if( mReadyToSyncCCT && !mCCTCamera->getCCTState() )
+ {
+ mCCTCamera->enableCCT(true);
+ }
+ }
+
+ for( PxU32 i = 0; i < 2; i++)
+ {
+ if(mSkybox[i])
+ mSkybox[i]->setTransform(PxTransform(getCamera().getPos()));
+ }
+
+ PhysXSample::onTickPreRender(dtime);
+
+ if(mIsFlyCamera)
+ {
+ getDebugRenderer()->addAABB(mWorldBound, RendererColor(0,255,0), RENDER_DEBUG_WIREFRAME);
+ }
+
+#if ENABLE_PROGRESS_BAR
+ mBGLoader->mLoaderStatusLock.lockReader();
+ mProgressBarRatio = mBGLoader->mQueryProgress;
+ mDiskIOTime = mBGLoader->mDiskIOTime;
+ mPhysxStreaming = mBGLoader->mPhyXStreamTime;
+ mGraphicStreaming = mBGLoader->mGraphicStreamTime;
+ mBGLoader->mLoaderStatusLock.unlockReader();
+#endif
+
+ mProgressBarRatio = PxClamp( mProgressBarRatio, 0.0f, 1.0f);
+
+ if(!mPause && mReadyToSyncCCT)
+ {
+ mActor->sync();
+ }
+}
+
+void SampleLargeWorld::onDigitalInputEvent(const SampleFramework::InputEvent& ie, bool val)
+{
+ if(val)
+ {
+ switch(ie.m_Id)
+ {
+ case RETRY:
+ {
+ PxSceneWriteLock scopedLock(*mScene);
+ mActor->reset();
+ mCCTCamera->setView(0,0);
+ }
+ break;
+
+ case FLY_CAMERA:
+ {
+ toggleFlyCamera();
+ mReadyToSyncCCT = false;
+ mPause = !mPause;
+ if( mPause )
+ {
+ mCCTCamera->enableCCT(false);
+ }
+
+ }
+ break;
+ case THROW_IMPORTANTOBJECT:
+ case THROW_UNIMPORTANCTOBJECT:
+ {
+ const PxVec3 pos = getCamera().getPos();
+ const PxVec3 vel = getCamera().getViewDir() * getDebugObjectsVelocity();
+
+ bool isImportant = ie.m_Id == THROW_IMPORTANTOBJECT;
+
+ PxSceneWriteLock scopedLock(*mScene);
+
+ PxRigidDynamic* actor = createBox(pos, getDebugBoxObjectExtents(), &vel,
+ isImportant ? mManagedMaterials[MATERIAL_RED] : mManagedMaterials[MATERIAL_GREEN], mDefaultDensity);
+
+ actor->setName(gDynamic);
+
+ mBGLoader->addDynamicObject(actor, isImportant);
+ }
+ break;
+
+ case PICK_NEARSETOBJECT:
+ {
+ mPick = !mPick;
+ if(mPick)
+ {
+ attachNearestObjectsToCCT();
+ }
+ else
+ {
+ releaseJoints();
+ }
+ }
+ break;
+ case CAMERA_SHIFT_SPEED:
+ {
+ mKeyShiftDown = true;
+ break;
+ }
+ case CAMERA_SPEED_INCREASE:
+ {
+ PxReal speed = getCurrentCameraController()->getCameraSpeed();
+ if(speed * 2 >= CAMERA_MAX_SPEED)
+ {
+ if(mKeyShiftDown)
+ shdfnd::printFormatted("running speed exceeds the maximum speed\n");
+ else
+ shdfnd::printFormatted("walking speed exceeds the maximum speed\n");
+ return;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ if(ie.m_Id == CAMERA_SHIFT_SPEED) mKeyShiftDown = false;
+ }
+
+ PhysXSample::onDigitalInputEvent(ie,val);
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+void SampleLargeWorld::customizeSceneDesc(PxSceneDesc& desc)
+{
+ desc.flags |= PxSceneFlag::eENABLE_CCD;
+ desc.flags |= PxSceneFlag::eREQUIRE_RW_LOCK;
+ desc.filterShader = filter;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleLargeWorld::customizeSample(SampleSetup& setup)
+{
+ setup.mName = "SampleLargeWorld";
+}
+
+void SampleLargeWorld::onSubstep(PxF32 dtime)
+{
+ PhysXSample::onSubstep(dtime);
+
+ mBGLoader->updateChunk(getCamera().getPos());
+
+ PxExtendedVec3 curCCTPosition = mActor->getController()->getPosition();
+ if(mWorldBound.contains(toVec3(curCCTPosition)))
+ {
+ mLastCCTPosition = curCCTPosition;
+ }
+ else
+ {
+ PxSceneWriteLock scopedLock(*mScene);
+ mActor->getController()->setPosition(mLastCCTPosition);
+ }
+}
+
+void SampleLargeWorld::collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents)
+{
+ PhysXSample::collectInputEvents(inputEvents);
+
+ getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(STEP_ONE_FRAME);
+ getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(PAUSE_SAMPLE);
+ getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(SPAWN_DEBUG_OBJECT);
+ getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(CAMERA_JUMP);
+ getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(CAMERA_CONTROLLER_INCREASE);
+
+ DIGITAL_INPUT_EVENT_DEF(CAMERA_SPEED_INCREASE, WKEY_ADD, XKEY_ADD, X1KEY_ADD, PS3KEY_ADD, PS4KEY_ADD, AKEY_UNKNOWN, OSXKEY_ADD, IKEY_UNKNOWN, LINUXKEY_ADD, WIIUKEY_UNKNOWN);
+ DIGITAL_INPUT_EVENT_DEF(CAMERA_SPEED_DECREASE, WKEY_SUBTRACT, XKEY_SUBTRACT, X1KEY_SUBTRACT, PS3KEY_SUBTRACT, PS4KEY_SUBTRACT, AKEY_UNKNOWN, OSXKEY_SUBTRACT, IKEY_UNKNOWN, LINUXKEY_SUBTRACT, WIIUKEY_UNKNOWN);
+
+ DIGITAL_INPUT_EVENT_DEF(THROW_IMPORTANTOBJECT, WKEY_I, XKEY_I, X1KEY_I, PS3KEY_I, PS4KEY_I, AKEY_UNKNOWN, OSXKEY_I, IKEY_UNKNOWN, LINUXKEY_I, WIIUKEY_UNKNOWN);
+ DIGITAL_INPUT_EVENT_DEF(THROW_UNIMPORTANCTOBJECT, WKEY_U, XKEY_U, X1KEY_U, PS3KEY_U, PS4KEY_U, AKEY_UNKNOWN, OSXKEY_U, IKEY_UNKNOWN, LINUXKEY_U, WIIUKEY_UNKNOWN);
+ DIGITAL_INPUT_EVENT_DEF(PICK_NEARSETOBJECT, WKEY_E, XKEY_E, X1KEY_E, PS3KEY_E, PS4KEY_E, AKEY_UNKNOWN, OSXKEY_E, IKEY_UNKNOWN, LINUXKEY_E, WIIUKEY_UNKNOWN);
+
+ DIGITAL_INPUT_EVENT_DEF(FLY_CAMERA, WKEY_M, XKEY_M, X1KEY_M, PS3KEY_M, PS4KEY_M, AKEY_UNKNOWN, OSXKEY_M, IKEY_UNKNOWN, LINUXKEY_M, WIIUKEY_UNKNOWN);
+ DIGITAL_INPUT_EVENT_DEF(FLY_CAMERA, GAMEPAD_WEST, GAMEPAD_WEST, GAMEPAD_WEST, GAMEPAD_WEST, GAMEPAD_WEST, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_WEST);
+
+ DIGITAL_INPUT_EVENT_DEF(RETRY, WKEY_R, XKEY_R, X1KEY_R, PS3KEY_R, PS4KEY_R, AKEY_UNKNOWN, OSXKEY_R, IKEY_UNKNOWN, LINUXKEY_R, WIIUKEY_UNKNOWN);
+ TOUCH_INPUT_EVENT_DEF(RETRY, "Retry", ABUTTON_1, IBUTTON_1);
+ TOUCH_INPUT_EVENT_DEF(FLY_CAMERA, "Fly Mode", ABUTTON_3, IBUTTON_3);
+
+ DIGITAL_INPUT_EVENT_DEF(CAMERA_SPEED_INCREASE, GAMEPAD_RIGHT_SHOULDER_TOP, GAMEPAD_RIGHT_SHOULDER_TOP, GAMEPAD_RIGHT_SHOULDER_TOP, GAMEPAD_RIGHT_SHOULDER_TOP, GAMEPAD_RIGHT_SHOULDER_TOP, AKEY_UNKNOWN, GAMEPAD_RIGHT_SHOULDER_TOP, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_RIGHT_SHOULDER_TOP);
+ DIGITAL_INPUT_EVENT_DEF(CAMERA_SPEED_DECREASE, GAMEPAD_LEFT_SHOULDER_TOP, GAMEPAD_LEFT_SHOULDER_TOP, GAMEPAD_LEFT_SHOULDER_TOP, GAMEPAD_LEFT_SHOULDER_TOP, GAMEPAD_LEFT_SHOULDER_TOP, AKEY_UNKNOWN, GAMEPAD_LEFT_SHOULDER_TOP, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_LEFT_SHOULDER_TOP);
+}
+
+void SampleLargeWorld::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", scale, shadowOffset, textColor);
+ else if (isMouseSupported)
+ renderer->print(x, y += yInc, "Use mouse to rotate", scale, shadowOffset, textColor);
+ else if (isPadSupported)
+ renderer->print(x, y += yInc, "Use right stick to rotate", 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 throw an object", SPAWN_DEBUG_OBJECT, -1);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
+
+ msg = mApplication.inputInfoMsg("Press "," to toggle fly camera", FLY_CAMERA, -1);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
+
+ msg = mApplication.inputInfoMsg("Press "," to increase fly camera speed", CAMERA_SPEED_INCREASE, -1);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
+
+ msg = mApplication.inputInfoMsg("Press "," to decrease fly camera speed", CAMERA_SPEED_DECREASE, -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 throw an important object", THROW_IMPORTANTOBJECT, -1);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
+
+ msg = mApplication.inputInfoMsg("Press "," to throw an unimportant object", THROW_UNIMPORTANCTOBJECT, -1);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
+
+ msg = mApplication.inputInfoMsg("Press "," to pick up the nearest objects maximum=5, or release objects", PICK_NEARSETOBJECT, -1);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
+}
+
+void SampleLargeWorld::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 streaming feature. It can load";
+ char line1[256]="and unload parts of map procedurally, treats it as an infinite map.";
+ char line2[256]="We serialize/deserialize files in the background thread, to avoid";
+ char line3[256]="spikes in the framerate when your HD is lagging or something. We add";
+ char line4[256]="one farm, one city, some trees and one fortress for gameplay activity.";
+
+ 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);
+ }
+}
+
+void SampleLargeWorld::customizeRender()
+{
+ PhysXSample::customizeRender();
+
+ renderProgressBar( mProgressBarRatio, false );
+ Renderer* renderer = getRenderer();
+ if(!renderer) return;
+
+ //ScopedRender renderSection(*renderer);
+ //if(renderSection)
+ {
+ const PxU32 yInc = 18;
+ char textBuf[256];
+
+ Camera& camera = getCamera();
+
+ Ps::snprintf(textBuf, 256, "Disk IO\t\t\t%0.1f ms", mDiskIOTime*1000.0f);
+ renderer->print(10, camera.getScreenHeight() - yInc*6, textBuf);
+
+ Ps::snprintf(textBuf, 256, "PhysX Streaming %0.1f ms", mPhysxStreaming*1000.0f);
+ renderer->print(10, camera.getScreenHeight() - yInc*5, textBuf);
+
+ Ps::snprintf(textBuf, 256, "Graphic Streaming %0.1f ms", mGraphicStreaming*1000.0f);
+ renderer->print(10, camera.getScreenHeight() - yInc*4, textBuf);
+
+ PxVec3 cameraPos = camera.getPos();
+ Ps::snprintf(textBuf, 256, "Position x=%0.1f,z=%0.1f", cameraPos.x, cameraPos.z);
+ renderer->print(camera.getScreenWidth() - 300, 10, textBuf);
+ }
+}
+
+//Sky box should not be culled
+void SampleLargeWorld::newMesh(const RAWMesh& data)
+{
+ static PxU32 submeshCount = 0;
+ if(submeshCount + 1<= (sizeof(mSkybox)/sizeof(mSkybox[0])))
+ {
+ mSkybox[submeshCount] = createRenderMeshFromRawMesh(data);
+ submeshCount++;
+ }
+}
+
+RAWMesh* SampleLargeWorld::createRawMeshFromMeshGeom(const PxTriangleMeshGeometry& mesh, RAWMesh &rawMesh)
+{
+ // Get physics geometry
+ PxTriangleMesh* tm = mesh.triangleMesh;
+
+ const PxU32 nbVerts = tm->getNbVertices();
+ const PxU32 nbTris = tm->getNbTriangles();
+ const void* tris = tm->getTriangles();
+ const bool has16BitTriangleIndices = tm->getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES ? true : false;
+ PX_ASSERT(has16BitTriangleIndices);
+
+ PxVec3* verts = (PxVec3*)SAMPLE_ALLOC(sizeof(PxVec3)*nbVerts);
+ PxMemCopy( verts, tm->getVertices(), sizeof(PxVec3)*nbVerts);
+
+ PxReal* normals = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal)*nbVerts*3);
+ PxU32* indices32 = NULL;
+
+ if(has16BitTriangleIndices)
+ {
+ PxU16* indices16 = (PxU16*)tris;
+ indices32 = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*nbTris*3);
+ for( PxU32 i = 0; i < nbTris; i++)
+ {
+ indices32[i*3+0] = indices16[i*3+0];
+ indices32[i*3+1] = indices16[i*3+1];
+ indices32[i*3+2] = indices16[i*3+2];
+ }
+
+ PxBuildSmoothNormals(nbTris, nbVerts, verts, NULL, indices16, (PxVec3*)normals, true);
+ }
+ else
+ {
+ indices32 = (PxU32*)tris;
+ PxBuildSmoothNormals(nbTris, nbVerts, verts, indices32, NULL, (PxVec3*)normals, true);
+ }
+
+ PxBounds3 bound = mesh.triangleMesh->getLocalBounds();
+
+ PxF32* uv =(PxF32*)SAMPLE_ALLOC(sizeof(PxF32)*nbVerts*2);
+ for(PxU32 i = 0; i < nbVerts; i++)
+ {
+ uv[i*2+0] = (verts[i].x - bound.minimum.x)/(bound.maximum.x - bound.minimum.x);
+ uv[i*2+1] = (verts[i].z - bound.minimum.z)/(bound.maximum.z - bound.minimum.z);
+ }
+
+ rawMesh.mNbVerts = nbVerts;
+ rawMesh.mVerts = verts;
+ rawMesh.mNbFaces = nbTris;
+ rawMesh.mIndices = indices32;
+ rawMesh.mVertexNormals = (PxVec3*)normals;
+ rawMesh.mUVs = uv;
+ rawMesh.mMaterialID = MATERIAL_ROAD_GRASS;
+
+ return &rawMesh;
+}
+
+RAWMesh* SampleLargeWorld::createRAWMeshFromObjMesh( const char* inObjFileName, const PxTransform& inPos, PxU32 inMaterialID, RAWMesh &outRawMesh )
+{
+ const ObjMeshMap::Entry* entry = mRenderMeshCache.find(inObjFileName);
+ if( entry != NULL )
+ {
+ cloneMesh( entry->second, outRawMesh );
+ }
+ else
+ {
+ WavefrontObj wfo;
+ if (!wfo.loadObj(getSampleMediaFilename(inObjFileName), true))
+ return NULL;
+
+ PxU32 nbTris = wfo.mTriCount;
+ PxU32 nbVerts = wfo.mVertexCount;
+
+ PxVec3* verts = (PxVec3*)SAMPLE_ALLOC(sizeof(PxVec3)*nbVerts);
+ PxMemCopy( verts, wfo.mVertices, sizeof(PxVec3)*nbVerts );
+
+ PxU32* indices = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*nbTris*3);
+ PxMemCopy( indices, wfo.mIndices, sizeof(PxU32)*nbTris*3 );
+
+ PxReal* uvs = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal)*nbVerts*2);
+ PxMemCopy( uvs, wfo.mTexCoords, sizeof(PxReal)*nbVerts*2 );
+
+ PxVec3* normals = (PxVec3*)SAMPLE_ALLOC(sizeof(PxVec3)*nbVerts);
+ PxBuildSmoothNormals(
+ nbTris,
+ nbVerts,
+ verts,
+ indices,
+ NULL,
+ normals,
+ true
+ );
+
+ outRawMesh.mNbVerts = nbVerts;
+ outRawMesh.mVerts = verts;
+ outRawMesh.mNbFaces = nbTris;
+ outRawMesh.mIndices = indices;
+ outRawMesh.mUVs = uvs;
+ outRawMesh.mVertexNormals = normals;
+ outRawMesh.mMaterialID = inMaterialID;
+ outRawMesh.mTransform = inPos;
+
+ RAWMesh cacheMesh;
+ cloneMesh( outRawMesh, cacheMesh );
+ mRenderMeshCache.insert( inObjFileName, cacheMesh );
+ }
+
+ return &outRawMesh;
+}
+
+void SampleLargeWorld::cloneMesh(const RAWMesh& inSrc, RAWMesh& outDst)
+{
+ PxVec3* verts = NULL;
+ PxU32* indices = NULL;
+ PxReal* uvs = NULL;
+ PxVec3* normals = NULL;
+ PxVec3* colors = NULL;
+
+ if( inSrc.mVerts )
+ {
+ verts = (PxVec3*)SAMPLE_ALLOC(sizeof(PxVec3)*inSrc.mNbVerts);
+ PxMemCopy( verts, inSrc.mVerts, sizeof(PxVec3)*inSrc.mNbVerts );
+ }
+
+ if( inSrc.mVertexNormals )
+ {
+ normals = (PxVec3*)SAMPLE_ALLOC(sizeof(PxVec3)*inSrc.mNbVerts);
+ PxMemCopy( normals, inSrc.mVertexNormals, sizeof(PxVec3)*inSrc.mNbVerts );
+ }
+
+ if( inSrc.mVertexColors )
+ {
+ colors = (PxVec3*)SAMPLE_ALLOC(sizeof(PxVec3)*inSrc.mNbVerts);
+ PxMemCopy( colors, inSrc.mVertexColors, sizeof(PxVec3)*inSrc.mNbVerts );
+ }
+
+ if( inSrc.mUVs )
+ {
+ uvs = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal)*inSrc.mNbVerts*2);
+ PxMemCopy( uvs, inSrc.mUVs, sizeof(PxReal)*inSrc.mNbVerts*2 );
+ }
+
+ if( inSrc.mIndices )
+ {
+ indices = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*inSrc.mNbFaces*3);
+ PxMemCopy( indices, inSrc.mIndices, sizeof(PxU32)*inSrc.mNbFaces*3 );
+ }
+
+ outDst.mName = inSrc.mName;
+ outDst.mTransform = inSrc.mTransform;
+ outDst.mNbVerts = inSrc.mNbVerts;
+ outDst.mNbFaces = inSrc.mNbFaces;
+ outDst.mMaterialID = inSrc.mMaterialID;
+ outDst.mVerts = verts;
+ outDst.mVertexNormals = normals;
+ outDst.mVertexColors = colors;
+ outDst.mUVs = uvs;
+ outDst.mIndices = indices;
+}
+
+void SampleLargeWorld::renderProgressBar( PxF32 ratio, bool needFlush )
+{
+ const RendererColor backColor(0, 255, 39);
+
+ ScreenQuad sq;
+ sq.mX0 = 0.0f;
+ sq.mY0 = 0.8f;
+ sq.mX1 = ratio;
+ sq.mY1 = 0.85f;
+ sq.mLeftUpColor = backColor;
+ sq.mRightUpColor = backColor;
+ sq.mLeftDownColor = backColor;
+ sq.mRightDownColor = backColor;
+ sq.mAlpha = 1.0f;
+
+ if(needFlush)
+ getRenderer()->clearBuffers();
+
+ getRenderer()->drawScreenQuad(sq);
+
+ if(needFlush)
+ getRenderer()->swapBuffers();
+}
+
+void SampleLargeWorld::releaseJoints()
+{
+ PxSceneWriteLock scopedLock(*mScene);
+
+ const size_t nbJoints = mFixedJoints.size();
+
+ PxRigidActor* actor0 = NULL;
+ PxRigidActor* actor1 = NULL;
+
+ for(PxU32 i=0;i<nbJoints;i++)
+ {
+ mFixedJoints[i]->getActors(actor0, actor1);
+ setCollisionGroup( actor1, DEFAULT_COLLISION_GROUP );
+
+ mFixedJoints[i]->release();
+ }
+ mFixedJoints.clear();
+}
+
+bool SampleLargeWorld::readyToSyncCCT()
+{
+ PxSceneReadLock scopedLock(*mScene);
+ PxVec3 pos = toVec3(mActor->getController()->getPosition());
+
+ PxRigidDynamic* actor = mActor->getController()->getActor();
+ PxShape* capsuleShape = getShape( *actor );
+
+ PxCapsuleGeometry capGeom(capsuleShape->getGeometry().capsule());
+
+ PxQueryFilterData objType = PxQueryFilterData(PxQueryFlag::eSTATIC);
+ PxHitFlags hitFlag = PxHitFlag::ePOSITION|PxHitFlag::eNORMAL;
+ PxSweepBuffer hit;
+ return getActiveScene().sweep(capGeom, PxTransform(pos), PxVec3(0.0f, -1.0f,0.0f), 1000.f, hit, hitFlag, objType);
+}
+
+void SampleLargeWorld::attachNearestObjectsToCCT()
+{
+ PxSceneWriteLock scopedLock(*mScene);
+
+ PxRigidDynamic* actor = mActor->getController()->getActor();
+ PxSphereGeometry sg(3.f);
+
+ PxI32 attachNum = 5;
+ PxVec3 footPos = toVec3(mActor->getController()->getFootPosition());
+
+ PxShape* capsuleShape = getShape( *actor );
+
+ const PxCapsuleGeometry& capGeom = capsuleShape->getGeometry().capsule();
+
+ PxF32 boxExtent = getDebugBoxObjectExtents().y + 0.1f;
+
+ PxOverlapHit hitBuffer[5];
+ PxMemZero(&hitBuffer, sizeof(hitBuffer));
+ PxFilterData fd(PICKING_COLLISION_GROUP,0,0,0);
+ PxOverlapBuffer buf(hitBuffer, 5);
+
+ getActiveScene().overlap(sg, PxTransform(footPos), buf, PxQueryFilterData(fd, PxQueryFlag::eDYNAMIC));
+ PxU32 hitNum = buf.getNbAnyHits();
+ if( hitNum == 0 )
+ return;
+
+ attachNum = hitNum == (PxU32)-1 ? attachNum : hitNum;
+
+ PxTransform lastTransform = PxTransform(actor->getGlobalPose().q);
+ PxVec3 hookPos = PxVec3( 0.0f, capGeom.halfHeight + capGeom.radius +boxExtent*2, capGeom.radius*2.0f);
+
+ for( PxI32 i = 0; i < attachNum; ++i)
+ {
+ PxRigidDynamic* attachedActor = hitBuffer[i].actor->is<PxRigidDynamic>();
+ setCollisionGroup( attachedActor, PICKING_COLLISION_GROUP );
+
+ PxFixedJoint *joint = PxFixedJointCreate(getPhysics(), actor,lastTransform, attachedActor, PxTransform(hookPos));
+ joint->setConstraintFlag( PxConstraintFlag::eCOLLISION_ENABLED, false );
+ mFixedJoints.push_back( joint );
+
+ hookPos.y += (boxExtent*1.5f);
+ }
+}
+
+PxRigidDynamic* SampleLargeWorld::createBox(const PxVec3& pos, const PxVec3& dims, const PxVec3* linVel, RenderMaterial* material, PxReal density)
+{
+ PxSceneWriteLock scopedLock(*mScene);
+
+ PxRigidDynamic* box = PxCreateDynamic(*mPhysics, PxTransform(pos), PxBoxGeometry(dims), *mMaterial, density);
+ PX_ASSERT(box);
+
+ box->setActorFlag(PxActorFlag::eVISUALIZATION, true);
+ box->setAngularDamping(0.5f);
+
+ //Enable ccd of dynamic generated box
+ PxShape* boxShape = getShape(*box);
+ setCCDActive(*boxShape);
+
+ boxShape->setQueryFilterData(PxFilterData(PICKING_COLLISION_GROUP,0,0,0));
+
+ getActiveScene().addActor(*box);
+
+ if(linVel)
+ box->setLinearVelocity(*linVel);
+
+ createRenderObjectsFromActor(box, material);
+
+ return box;
+}
+
+void SampleLargeWorld::setCollisionGroup(PxRigidActor* actor, PxU32 group)
+{
+ PxSceneWriteLock scopedLock(*mScene);
+
+ PxU32 nbShapes = actor->getNbShapes();
+ if( nbShapes )
+ {
+ SampleArray<PxShape*> shapes(nbShapes);
+ actor->getShapes( &shapes[0], nbShapes);
+ for( PxU32 j = 0; j < nbShapes; j++)
+ {
+ PxFilterData fd = shapes[j]->getSimulationFilterData();
+ fd.word0 = group;
+ shapes[j]->setSimulationFilterData(fd);
+ }
+ }
+}
+///////////////////////////////////////////////////////////////////////////////
+