diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Samples/SampleLargeWorld/SampleLargeWorld.cpp | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'PhysX_3.4/Samples/SampleLargeWorld/SampleLargeWorld.cpp')
| -rw-r--r-- | PhysX_3.4/Samples/SampleLargeWorld/SampleLargeWorld.cpp | 1039 |
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); + } + } +} +/////////////////////////////////////////////////////////////////////////////// + |