aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Samples/SampleSubmarine/SampleSubmarine.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/SampleSubmarine/SampleSubmarine.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/SampleSubmarine/SampleSubmarine.cpp')
-rw-r--r--PhysX_3.4/Samples/SampleSubmarine/SampleSubmarine.cpp1278
1 files changed, 1278 insertions, 0 deletions
diff --git a/PhysX_3.4/Samples/SampleSubmarine/SampleSubmarine.cpp b/PhysX_3.4/Samples/SampleSubmarine/SampleSubmarine.cpp
new file mode 100644
index 00000000..4eaac18b
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleSubmarine/SampleSubmarine.cpp
@@ -0,0 +1,1278 @@
+// 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 "SampleSubmarine.h"
+#include "SampleUtils.h"
+#include "SampleAllocatorSDKClasses.h"
+#include "RenderBaseActor.h"
+#include "RendererMemoryMacros.h"
+#include "RenderMaterial.h"
+
+#include "PxTkFile.h"
+#include "PxPhysicsAPI.h"
+#include "extensions/PxExtensionsAPI.h"
+
+#include <SamplePlatform.h>
+#include <SampleUserInput.h>
+#include <SampleUserInputIds.h>
+#include "SampleSubmarineInputEventIds.h"
+#include <SampleUserInputDefines.h>
+
+#include "Crab.h"
+
+#include "SubmarineCameraController.h"
+
+// for loading the HeightField
+#include "RenderMeshActor.h"
+#include "PxTkBmpLoader.h"
+//////////////////////////////
+
+#include <algorithm>
+
+using namespace PxToolkit;
+using namespace SampleRenderer;
+using namespace SampleFramework;
+
+REGISTER_SAMPLE(SampleSubmarine, "SampleSubmarine")
+
+static PxVec3 gBuoyancy = PxVec3(0, 1.0f, 0);
+static PxRigidDynamic* gTreasureActor = NULL;
+static PxVec3 gForce = PxVec3(0, 0, 0);
+static PxVec3 gTorque = PxVec3(0, 0, 0);
+static const PxReal gLinPower = 200.0f;
+static const PxReal gAngPower = 5000.0f;
+static const PxReal gSubMarineDensity = 3.0f;
+static PxI32 gSubmarineHealth = 100;
+static PxU32 gKeyFlags = 0;
+static bool gTreasureFound = false;
+static bool gResetScene = false;
+
+static Crab* gCrab = NULL;
+
+void setupFiltering(PxRigidActor* actor, PxU32 filterGroup, PxU32 filterMask);
+
+struct Movement
+{
+ enum Enum
+ {
+ eCRAB_FWD = (1 << 0),
+ eCRAB_BCKWD = (1 << 1),
+ eCRAB_ROTATE_LEFT = (1 << 2),
+ eCRAB_ROTATE_RIGHT = (1 << 3),
+ eSUBMAINE_FWD = (1 << 4),
+ eSUBMAINE_BCKWD = (1 << 5),
+ eSUBMAINE_UP = (1 << 6),
+ eSUBMAINE_DOWN = (1 << 7),
+ };
+};
+
+
+enum MaterialID
+{
+ MATERIAL_TERRAIN_MUD = 1000,
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+SampleSubmarine::SampleSubmarine(PhysXSampleApplication& app)
+ : PhysXSample(app)
+ , mSubmarineActor(NULL)
+ , mCameraAttachedToActor(NULL)
+ , mSubmarineCameraController(NULL)
+{
+ mCreateGroundPlane = false;
+ //mStepperType = FIXED_STEPPER;
+}
+
+SampleSubmarine::~SampleSubmarine()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::customizeSample(SampleSetup& setup)
+{
+ setup.mName = "SampleSubmarine";
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::onInit()
+{
+ mNbThreads = PxMax(PxI32(shdfnd::Thread::getNbPhysicalCores())-1, 0);
+
+ mCreateCudaCtxManager = true;
+
+ PhysXSample::onInit();
+
+ PxSceneWriteLock scopedLock(*mScene);
+
+ mSubmarineCameraController = SAMPLE_NEW(SubmarineCameraController)();
+ setCameraController(mSubmarineCameraController);
+
+ mApplication.setMouseCursorHiding(true);
+ mApplication.setMouseCursorRecentering(true);
+ mSubmarineCameraController->init(PxTransform(PxIdentity));
+ mSubmarineCameraController->setMouseSensitivity(0.5f);
+ mSubmarineCameraController->setMouseLookOnMouseButton(false);
+
+ getRenderer()->setAmbientColor(RendererColor(60, 60, 60));
+
+ PxMaterial& material = getDefaultMaterial();
+ material.setRestitution(0);
+ material.setDynamicFriction(50.0f);
+ material.setStaticFriction(50.0f);
+
+ // set gravity
+ getActiveScene().setGravity(PxVec3(0, -10.0f, 0));
+
+ createMaterials();
+
+ getRenderer()->setFog(SampleRenderer::RendererColor(16,16,40), 125.0f);
+
+ PxRigidActor* heightField = loadTerrain("submarine_heightmap.bmp", 0.4f, 3.0f, 3.0f);
+ if (!heightField) fatalError("Sample can not load file submarine_heightmap.bmp\n");
+
+ setupFiltering(heightField, FilterGroup::eHEIGHTFIELD, FilterGroup::eCRAB);
+
+ // create ceiling plane
+ PxReal d = 60.0f;
+ PxTransform pose = PxTransform(PxVec3(0.0f, d, 0.0f), PxQuat(PxHalfPi, PxVec3(0.0f, 0.0f, -1.0f)));
+ PxRigidStatic* plane = getPhysics().createRigidStatic(pose);
+ if(!plane) fatalError("createRigidStatic failed!");
+ PxShape* shape = PxRigidActorExt::createExclusiveShape(*plane, PxPlaneGeometry(), material);
+ if(!shape) fatalError("createShape failed!");
+ getActiveScene().addActor(*plane);
+
+ resetScene();
+}
+
+void SampleSubmarine::createMaterials()
+{
+ RAWTexture data;
+ data.mName = "rock_diffuse2.dds";
+ RenderTexture* gravelTexture = createRenderTextureFromRawTexture(data);
+
+ RenderMaterial* terrainMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(), PxVec3(0.5f, 0.25f, 0.125f), 1.0f, false, MATERIAL_TERRAIN_MUD, gravelTexture);
+ mRenderMaterials.push_back(terrainMaterial);
+
+ mSeamineMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(), PxVec3(0.50f, 0.50f, 0.5f), 1.0f, false, 0xffffffff, NULL);
+ mRenderMaterials.push_back(mSeamineMaterial);
+}
+
+
+PxRigidActor* SampleSubmarine::loadTerrain(const char* name, const PxReal heightScale, const PxReal rowScale, const PxReal columnScale)
+{
+ PxRigidActor* heightFieldActor = NULL;
+ BmpLoader loader;
+ if(loader.loadBmp(getSampleMediaFilename(name)))
+ {
+ PxU16 nbColumns = PxU16(loader.mWidth), nbRows = PxU16(loader.mHeight);
+ PxHeightFieldDesc heightFieldDesc;
+ heightFieldDesc.nbColumns = nbColumns;
+ heightFieldDesc.nbRows = nbRows;
+ PxU32* samplesData = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*nbColumns * nbRows);
+ heightFieldDesc.samples.data = samplesData;
+ heightFieldDesc.samples.stride = sizeof(PxU32);
+ PxU8* currentByte = (PxU8*)heightFieldDesc.samples.data;
+ PxU8* loader_ptr = loader.mRGB;
+ PxVec3Alloc* vertexesA = SAMPLE_NEW(PxVec3Alloc)[nbRows * nbColumns];
+ PxF32* uvs = (PxF32*)SAMPLE_ALLOC(sizeof(PxF32) * nbRows * nbColumns * 2);
+ PxVec3* vertexes = vertexesA;
+ for (PxU32 row = 0; row < nbRows; row++)
+ {
+ for (PxU32 column = 0; column < nbColumns; column++)
+ {
+ PxHeightFieldSample* currentSample = (PxHeightFieldSample*)currentByte;
+ currentSample->height = *loader_ptr;
+ vertexes[row * nbColumns + column] = PxVec3(PxReal(row)*rowScale,
+ PxReal(currentSample->height * heightScale),
+ PxReal(column)*columnScale);
+
+ uvs[(row * nbColumns + column)*2 + 0] = (float)column/7.0f;
+ uvs[(row * nbColumns + column)*2 + 1] = (float)row/7.0f;
+
+ currentSample->materialIndex0 = 0;
+ currentSample->materialIndex1 = 0;
+ currentSample->clearTessFlag();
+ currentByte += heightFieldDesc.samples.stride;
+ loader_ptr += 3 * sizeof(PxU8);
+ }
+ }
+ PxHeightField* heightField = getCooking().createHeightField(heightFieldDesc, getPhysics().getPhysicsInsertionCallback());
+ if(!heightField) fatalError("createHeightField failed!");
+ // create shape for heightfield
+ PxTransform pose(PxVec3(-((PxReal)nbRows*rowScale) / 2.0f,
+ 0.0f,
+ -((PxReal)nbColumns*columnScale) / 2.0f),
+ PxQuat(PxIdentity));
+ heightFieldActor = getPhysics().createRigidStatic(pose);
+ if(!heightFieldActor) fatalError("createRigidStatic failed!");
+ PxShape* shape = PxRigidActorExt::createExclusiveShape(*heightFieldActor, PxHeightFieldGeometry(heightField, PxMeshGeometryFlags(), heightScale, rowScale, columnScale), getDefaultMaterial());
+ if(!shape) fatalError("createShape failed!");
+ // add actor to the scene
+ getActiveScene().addActor(*heightFieldActor);
+ // create indices
+ PxU32* indices = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*((nbColumns - 1) * (nbRows - 1) * 3 * 2));
+ for(int i = 0; i < (nbColumns - 1); ++i)
+ {
+ for(int j = 0; j < (nbRows - 1); ++j)
+ {
+ // first triangle
+ indices[6 * (i * (nbRows - 1) + j) + 0] = (i + 1) * nbRows + j;
+ indices[6 * (i * (nbRows - 1) + j) + 1] = i * nbRows + j;
+ indices[6 * (i * (nbRows - 1) + j) + 2] = i * nbRows + j + 1;
+ // second triangle
+ indices[6 * (i * (nbRows - 1) + j) + 3] = (i + 1) * nbRows + j + 1;
+ indices[6 * (i * (nbRows - 1) + j) + 4] = (i + 1) * nbRows + j;
+ indices[6 * (i * (nbRows - 1) + j) + 5] = i * nbRows + j + 1;
+ }
+ }
+ // add mesh to renderer
+ RAWMesh data;
+ data.mName = name;
+ data.mTransform = PxTransform(PxIdentity);
+ data.mNbVerts = nbColumns * nbRows;
+ data.mVerts = vertexes;
+ data.mVertexNormals = NULL;
+ data.mUVs = uvs;
+ data.mMaterialID = MATERIAL_TERRAIN_MUD;
+ data.mNbFaces = (nbColumns - 1) * (nbRows - 1) * 2;
+ data.mIndices = indices;
+
+ RenderMeshActor* hf_mesh = createRenderMeshFromRawMesh(data);
+ if(!hf_mesh) fatalError("createRenderMeshFromRawMesh failed!");
+ hf_mesh->setPhysicsShape(shape, heightFieldActor);
+ shape->setFlag(PxShapeFlag::eVISUALIZATION, false);
+ SAMPLE_FREE(indices);
+ SAMPLE_FREE(uvs);
+ DELETEARRAY(vertexesA);
+ SAMPLE_FREE(samplesData);
+ }
+
+ return heightFieldActor;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void setupFiltering(PxRigidActor* actor, PxU32 filterGroup, PxU32 filterMask)
+{
+ PxFilterData filterData;
+ filterData.word0 = filterGroup; // word0 = own ID
+ filterData.word1 = filterMask; // word1 = ID mask to filter pairs that trigger a contact callback;
+ const PxU32 numShapes = actor->getNbShapes();
+ PxShape** shapes = (PxShape**)SAMPLE_ALLOC(sizeof(PxShape*)*numShapes);
+ actor->getShapes(shapes, numShapes);
+ for(PxU32 i = 0; i < numShapes; i++)
+ {
+ PxShape* shape = shapes[i];
+ shape->setSimulationFilterData(filterData);
+ }
+ SAMPLE_FREE(shapes);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+PxRigidDynamic* SampleSubmarine::createSubmarine(const PxVec3& inPosition, const PxReal yRot)
+{
+ PX_ASSERT(mSubmarineActor == NULL);
+
+ std::vector<PxTransform> localPoses;
+ std::vector<const PxGeometry*> geometries;
+
+ // cabin
+ PxSphereGeometry cabinGeom(1.5f);
+ PxTransform cabinPose = PxTransform(PxIdentity);
+ cabinPose.p.x = -0.5f;
+
+ // engine
+ PxBoxGeometry engineGeom(0.25f, 1.0f, 1.0f);
+ PxTransform enginePose = PxTransform(PxIdentity);
+ enginePose.p.x = cabinPose.p.x + cabinGeom.radius + engineGeom.halfExtents.x;
+
+ // tanks
+ PxCapsuleGeometry tankGeom(0.5f, 1.8f);
+ PxTransform tank1Pose = PxTransform(PxIdentity);
+ tank1Pose.p = PxVec3(0,-cabinGeom.radius, cabinGeom.radius);
+ PxTransform tank2Pose = PxTransform(PxIdentity);
+ tank2Pose.p = PxVec3(0,-cabinGeom.radius, -cabinGeom.radius);
+
+ localPoses.push_back(cabinPose);
+ geometries.push_back(&cabinGeom);
+ localPoses.push_back(enginePose);
+ geometries.push_back(&engineGeom);
+ localPoses.push_back(tank1Pose);
+ geometries.push_back(&tankGeom);
+ localPoses.push_back(tank2Pose);
+ geometries.push_back(&tankGeom);
+
+ // put the shapes together into one actor
+ mSubmarineActor = PhysXSample::createCompound(inPosition, localPoses, geometries, 0, mManagedMaterials[MATERIAL_YELLOW], gSubMarineDensity)->is<PxRigidDynamic>();
+
+ if(!mSubmarineActor) fatalError("createCompound failed!");
+
+ //disable the current and buoyancy effect for the sub.
+ mSubmarineActor->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
+
+ // set the filtering group for the submarine
+ setupFiltering(mSubmarineActor, FilterGroup::eSUBMARINE, FilterGroup::eMINE_HEAD | FilterGroup::eMINE_LINK);
+
+ mSubmarineActor->setLinearDamping(0.15f);
+ mSubmarineActor->setAngularDamping(15.0f);
+
+ PxTransform globalPose;
+ globalPose.p = inPosition;
+ globalPose.q = PxQuat(yRot, PxVec3(0,1,0));
+ mSubmarineActor->setGlobalPose(globalPose);
+
+ mSubmarineActor->setCMassLocalPose(PxTransform(PxIdentity));
+
+ return mSubmarineActor;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Seamine* SampleSubmarine::createSeamine(const PxVec3& inPosition, PxReal inHeight)
+{
+ static const PxReal chainLinkLength = 2.0f;
+ static const PxReal linkSpacing = 0.05f;
+ static const PxReal mineHeadRadius = 1.5f;
+ const PxVec3 mineStartPos = inPosition;
+ static const PxVec3 linkOffset = PxVec3(0, chainLinkLength + linkSpacing, 0);
+ static const PxVec3 halfLinkOffset = linkOffset * 0.5f;
+ static const PxVec3 linkDim = PxVec3(chainLinkLength*0.125f, chainLinkLength*0.5f, chainLinkLength*0.125f);
+ PxU32 numLinks = PxU32((inHeight - 2.0f*mineHeadRadius) / (chainLinkLength + linkSpacing));
+ numLinks = numLinks ? numLinks : 1;
+
+ Seamine* seamine = SAMPLE_NEW(Seamine);
+ mSeamines.push_back(seamine);
+
+ // create links from floor
+ PxVec3 linkPos = mineStartPos + halfLinkOffset;
+ PxRigidActor* prevActor = NULL;
+ for(PxU32 i = 0; i < numLinks; i++)
+ {
+ // create the link actor
+ PxRigidDynamic* link = createBox(linkPos, linkDim, NULL, mSeamineMaterial, 1.0f)->is<PxRigidDynamic>();
+ if(!link) fatalError("createBox failed!");
+ // back reference to mineHead
+ link->userData = seamine;
+ seamine->mLinks.push_back(link);
+
+ setupFiltering(link, FilterGroup::eMINE_LINK, FilterGroup::eSUBMARINE);
+ link->setLinearDamping(0.5f);
+ link->setAngularDamping(0.5f);
+ link->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
+
+ // create distance joint between link and prevActor
+ PxTransform linkFrameA = prevActor ? PxTransform(halfLinkOffset, PxQuat(PxIdentity)) : PxTransform(mineStartPos, PxQuat(PxIdentity));
+ PxTransform linkFrameB = PxTransform(-halfLinkOffset, PxQuat(PxIdentity));
+ PxDistanceJoint *joint = PxDistanceJointCreate(getPhysics(), prevActor, linkFrameA, link, linkFrameB);
+ if(!joint) fatalError("PxDistanceJointCreate failed!");
+
+ // set min & max distance to 0
+ joint->setMaxDistance(0.0f);
+ joint->setMinDistance(0.0f);
+ // setup damping & spring
+ joint->setDamping(1.0f * link->getMass());
+ joint->setStiffness(400.0f * link->getMass());
+ joint->setDistanceJointFlags(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED | PxDistanceJointFlag::eMIN_DISTANCE_ENABLED | PxDistanceJointFlag::eSPRING_ENABLED);
+
+ // add to joints array for cleanup
+ mJoints.push_back(joint);
+
+ prevActor = link;
+ linkPos += linkOffset;
+ }
+
+ // create mine head
+ linkPos.y += mineHeadRadius - (chainLinkLength*0.5f);
+ PxRigidDynamic* mineHead = createSphere(linkPos, mineHeadRadius, NULL, mSeamineMaterial, 1.0f)->is<PxRigidDynamic>();
+ mineHead->userData = seamine;
+ seamine->mMineHead = mineHead;
+
+ mineHead->setLinearDamping(0.5f);
+ mineHead->setAngularDamping(0.5f);
+ mineHead->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
+
+ // setup filtering to trigger contact reports when submarine touches the minehead
+ setupFiltering(mineHead, FilterGroup::eMINE_HEAD, FilterGroup::eSUBMARINE);
+
+
+ // create distance joint between mine head and prevActor
+ PxTransform linkFrameA = PxTransform(halfLinkOffset, PxQuat(PxIdentity));
+ PxTransform linkFrameB = PxTransform(PxVec3(0, -mineHeadRadius - linkSpacing*0.5f, 0), PxQuat(PxIdentity));
+ PxDistanceJoint *joint = PxDistanceJointCreate(getPhysics(), prevActor, linkFrameA, mineHead, linkFrameB);
+ if(!joint) fatalError("PxDistanceJointCreate failed!");
+
+ // set min & max distance to 0
+ joint->setMaxDistance(0.0f);
+ joint->setMinDistance(0.0f);
+ // setup damping & spring
+ joint->setDamping(1.0f * mineHead->getMass());
+ joint->setStiffness(400.0f * mineHead->getMass());
+ joint->setDistanceJointFlags(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED | PxDistanceJointFlag::eMIN_DISTANCE_ENABLED | PxDistanceJointFlag::eSPRING_ENABLED);
+
+ // add to joints array for cleanup
+ mJoints.push_back(joint);
+
+ return seamine;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static const char* getPlatformName()
+{
+#if PX_X86
+ return "PC32";
+#elif PX_X64
+ return "PC64";
+#elif PX_ARM_FAMILY
+ return "ARM";
+#else
+ return "";
+#endif
+}
+
+void SampleSubmarine::createDynamicActors()
+{
+ // create mines
+ static const PxU32 numMines = 20;
+ static const PxVec3 mineFieldCenter = PxVec3(0, 64, 0);
+ static const PxReal minMineDistance = 3.0f;
+ static const PxI32 mineFieldRadius = 30;
+ for(PxU32 i = 0; i < numMines; i++)
+ {
+ // raycast against floor (height field) to find the height to attach the mine
+ PxRaycastBuffer rayHit;
+ bool hit = false;
+ do
+ {
+ PxVec3 offset = PxVec3(PxReal(getSampleRandom().rand(-mineFieldRadius, mineFieldRadius)), 0, PxReal(getSampleRandom().rand(-mineFieldRadius, mineFieldRadius)));
+ PxVec3 raycastStart = mineFieldCenter + offset*minMineDistance;
+ hit = getActiveScene().raycast(raycastStart, PxVec3(0,-1,0), 100.0f, rayHit);
+ } while(!hit || (rayHit.block.position.y > 25.0f) || rayHit.block.actor->is<PxRigidDynamic>());
+ createSeamine(rayHit.block.position, getSampleRandom().rand(10.0f, 25.0f));
+ }
+
+ // create treasure
+ {
+ static const PxVec3 treasureDim = PxVec3(5, 3, 4)*0.5f;
+
+ PxRaycastBuffer rayHit;
+ PxVec3 raycastStart = PxVec3(-19, 64, -24);
+ getActiveScene().raycast(raycastStart, PxVec3(0,-1,0), 100.0f, rayHit);
+
+ gTreasureActor = createBox(rayHit.block.position+treasureDim, treasureDim, NULL, mManagedMaterials[MATERIAL_BLUE], 1)->is<PxRigidDynamic>();
+
+ if(!gTreasureActor) fatalError("createBox failed!");
+ gTreasureActor->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
+ PxShape* treasureShape;
+ gTreasureActor->getShapes(&treasureShape, 1);
+ treasureShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
+ treasureShape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);
+ }
+
+ // create submarine
+ createSubmarine(PxVec3(-110, 50, 110), 2.1f);
+
+ char theCrabName[256];
+ sprintf(theCrabName, "crab_%s.bin", getPlatformName());
+ // If we have already had crab copy, just load it, or will create crab and export it
+ char thePathBuffer[1024];
+ const char* theCrabPath = getSampleOutputDirManager().getFilePath( theCrabName, thePathBuffer, false );
+ SampleFramework::File* fp = NULL;
+ PxToolkit::fopen_s(&fp, theCrabPath, "r" );
+ if( fp )
+ {
+ shdfnd::printFormatted("loading the crab from file status: \n");
+ gCrab = SAMPLE_NEW(Crab)(*this, theCrabPath, mManagedMaterials[MATERIAL_RED]);
+ if (gCrab && !gCrab->getCrabBody())
+ {
+ delete gCrab;
+ gCrab = NULL;
+ }
+ shdfnd::printFormatted(gCrab ? "successful\n":"failed\n");
+ fclose (fp);
+ }
+
+ if( !gCrab )
+ {
+ gCrab = SAMPLE_NEW(Crab)(*this, PxVec3(0, 50, 0), mManagedMaterials[MATERIAL_RED]);
+ shdfnd::printFormatted("crab file not found ... exporting crab file\n");
+ gCrab->save(theCrabPath);
+ }
+
+ PX_ASSERT( gCrab );
+ mCrabs.push_back(gCrab);
+
+ static const PxU32 numCrabs = 3;
+ for(PxU32 i = 0; i < numCrabs; i++)
+ {
+ Crab* crab = SAMPLE_NEW(Crab)(*this, PxVec3(getSampleRandom().rand(-20.0f,20.0f), 50, getSampleRandom().rand(-20.0f,20.0f)), mManagedMaterials[MATERIAL_RED]);
+ mCrabs.push_back(crab);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::resetScene()
+{
+ gResetScene = false;
+ const size_t nbCrabs = mCrabs.size();
+ for(PxU32 i=0;i<nbCrabs;i++)
+ {
+ delete mCrabs[i];
+ }
+ mCrabs.clear();
+
+ const size_t nbJoints = mJoints.size();
+ for(PxU32 i=0;i<nbJoints;i++)
+ mJoints[i]->release();
+ mJoints.clear();
+
+ const size_t nbSeamines = mSeamines.size();
+ for(PxU32 i=0;i<nbSeamines;i++)
+ {
+ const size_t nbLink = mSeamines[i]->mLinks.size();
+ for(PxU32 j=0;j<nbLink;j++)
+ removeActor(mSeamines[i]->mLinks[j]);
+ removeActor(mSeamines[i]->mMineHead);
+ delete mSeamines[i];
+ }
+ mSeamines.clear();
+
+ if(mSubmarineActor)
+ {
+ removeActor(mSubmarineActor);
+ mSubmarineActor = NULL;
+ }
+ gSubmarineHealth = 100;
+
+ if (gTreasureActor)
+ removeActor(gTreasureActor);
+ gTreasureActor = NULL;
+ gTreasureFound = false;
+
+ while(mPhysicsActors.size())
+ {
+ removeActor(mPhysicsActors[0]);
+ }
+
+ freeDeletedActors();
+
+ createDynamicActors();
+
+ // init camera orientation
+ mSubmarineCameraController->init(PxVec3(-90, 60, 50), PxVec3(0.28f, 2.05f, 0.0f));
+ mSubmarineCameraController->setMouseSensitivity(0.5f);
+ mSubmarineCameraController->setFollowingMode(true);
+ mCameraAttachedToActor = mSubmarineActor;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::onShutdown()
+{
+ {
+ PxSceneWriteLock scopedLock(*mScene);
+
+ const size_t nbCrabs = mCrabs.size();
+ for(PxU32 i=0;i<nbCrabs;i++)
+ delete mCrabs[i];
+ mCrabs.clear();
+
+ // free crabs' memory
+ const size_t nbDelCrabsMem = mCrabsMemoryDeleteList.size();
+ for(PxU32 i = 0; i < nbDelCrabsMem; i++)
+ SAMPLE_FREE(mCrabsMemoryDeleteList[i]);
+ mCrabsMemoryDeleteList.clear();
+
+ gCrab = NULL;
+
+ const size_t nbJoints = mJoints.size();
+ for(PxU32 i=0;i<nbJoints;i++)
+ mJoints[i]->release();
+ mJoints.clear();
+
+ const size_t nbSeamines = mSeamines.size();
+ for(PxU32 i=0;i<nbSeamines;i++)
+ delete mSeamines[i];
+ mSeamines.clear();
+
+ gTreasureActor = NULL;
+
+ DELETESINGLE(mSubmarineCameraController);
+ }
+
+ PhysXSample::onShutdown();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::onSubstep(float dtime)
+{
+ // user input -> forces
+ handleInput();
+
+ // delay free crabs' memory
+ const size_t nbDelCrabsMem = mCrabsMemoryDeleteList.size();
+ for(PxU32 i = 0; i < nbDelCrabsMem; i++)
+ SAMPLE_FREE(mCrabsMemoryDeleteList[i]);
+ mCrabsMemoryDeleteList.clear();
+
+ // change current every 0.01s
+ static PxReal sElapsedTime = 0.0f;
+ sElapsedTime += mPause ? 0 : dtime;
+ if(sElapsedTime > 0.01f)
+ {
+ static PxReal angle = 0;
+ angle += sElapsedTime*0.01f;
+ angle = angle < (PxTwoPi) ? angle : angle - PxTwoPi;
+ sElapsedTime = 0;
+
+ gBuoyancy.z = 0.15f * PxSin(angle * 50);
+ PxQuat yRot = PxQuat(angle, PxVec3(0,1,0));
+ gBuoyancy = yRot.rotate(gBuoyancy);
+
+ // apply external forces to seamines
+ PxSceneWriteLock scopedLock(*mScene);
+ const size_t nbSeamines = mSeamines.size();
+ for(PxU32 i = 0; i < nbSeamines; i++)
+ {
+ Seamine* mine = mSeamines[i];
+ mine->mMineHead->addForce(gBuoyancy, PxForceMode::eACCELERATION);
+ const size_t nbLinks = mine->mLinks.size();
+ for(PxU32 j = 0; j < nbLinks; j++)
+ {
+ mine->mLinks[j]->addForce(gBuoyancy, PxForceMode::eACCELERATION);
+ }
+ }
+ }
+
+ if(mSubmarineActor)
+ {
+ PxSceneWriteLock scopedLock(*mScene);
+
+ //convert forces from submarine the submarine's body local space to global space
+ PxQuat submarineOrientation = mSubmarineActor->getGlobalPose().q;
+ gForce = submarineOrientation.rotate(gForce);
+ gTorque = submarineOrientation.rotate(gTorque);
+
+ // add also current forces to submarine
+ gForce.z += gBuoyancy.z * 5.0f;
+
+ // apply forces in global space and reset
+ mSubmarineActor->addForce(gForce);
+ mSubmarineActor->addTorque(gTorque);
+ gForce = PxVec3(0);
+ gTorque = PxVec3(0);
+ }
+}
+
+void SampleSubmarine::onSubstepSetup(float dt, PxBaseTask* completionTask)
+{
+ // set Crabs continuation to ensure the completion task
+ // is not run before Crab update has completed
+ const size_t nbCrabs = mCrabs.size();
+ for(PxU32 i = 0; i < nbCrabs; i++)
+ {
+ Crab* crab = mCrabs[i];
+ crab->update(dt);
+ crab->setContinuation(completionTask);
+ }
+}
+
+void SampleSubmarine::onSubstepStart(float dtime)
+{
+ // kick off crab updates in parallel to simulate
+ const size_t nbCrabs = mCrabs.size();
+ for(PxU32 i = 0; i < nbCrabs; i++)
+ {
+ Crab* crab = mCrabs[i];
+ // inverted stepper: skip crab updates right after creation,
+ // crab task is not in the pipeline at this point (onSubstepSetup not yet called).
+ if(crab->getTaskManager() == NULL)
+ continue;
+ crab->removeReference();
+ }
+}
+
+void SampleSubmarine::onTickPreRender(float dtime)
+{
+ mScene->lockWrite();
+
+ if(gResetScene)
+ resetScene();
+
+ // handle mine (and submarine) explosion
+ if(mSubmarineActor)
+ {
+ // explode all touched mines, apply damage and force to submarine
+ PxVec3 subMarinePos = mSubmarineActor->getGlobalPose().p;
+ const size_t nbExplodeSeamines = mMinesToExplode.size();
+ for(PxU32 i=0; i < nbExplodeSeamines; i++)
+ {
+ Seamine* mine = mMinesToExplode[i];
+ PxVec3 explosionPos = mine->mMineHead->getGlobalPose().p;
+
+ // disable contact trigger callback of the chain & enable gravity
+ const size_t nbLinks = mine->mLinks.size();
+ for(PxU32 j = 0; j < nbLinks; j++)
+ {
+ PxRigidDynamic* link = mine->mLinks[j];
+ setupFiltering(link, 0, 0);
+ link->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, false);
+ }
+
+ // remove mine head
+ std::vector<Seamine*>::iterator mineIter = std::find(mSeamines.begin(), mSeamines.end(), mine);
+ if(mineIter != mSeamines.end())
+ mSeamines.erase(mineIter);
+ removeActor(mine->mMineHead);
+ delete mine;
+
+ // give damage to submarine
+ static const PxReal strength = 400.0f;
+ PxVec3 explosion = subMarinePos - explosionPos;
+ PxReal len = explosion.normalize();
+ PxReal damage = strength * (1.0f/len);
+ explosion *= damage;
+ mSubmarineActor->addForce(explosion*300);
+ gSubmarineHealth = PxMax(gSubmarineHealth-PxI32(damage), 0);
+ if(gSubmarineHealth == 0)
+ {
+ mSubmarineCameraController->init(subMarinePos - getCamera().getViewDir()*10.0f, getCamera().getRot());
+ explode(mSubmarineActor, subMarinePos /*- explosion*0.2f*/, damage);
+ mCameraAttachedToActor = NULL;
+ mSubmarineCameraController->setFollowingMode(false);
+ mSubmarineActor = NULL;
+ break;
+ }
+ }
+ mMinesToExplode.clear();
+ }
+
+ // respawn Crabs
+ const size_t nbCrabs = mCrabs.size();
+ for(PxU32 i = 0; i < nbCrabs; i++)
+ {
+ Crab* crab = mCrabs[i];
+ if(crab->needsRespawn())
+ {
+ PxRigidDynamic* prevBody = crab->getCrabBody();
+ PxVec3 prevPos = prevBody->getGlobalPose().p;
+ delete crab;
+ mCrabs[i] = SAMPLE_NEW(Crab)(*this, prevPos, mManagedMaterials[MATERIAL_RED]);
+ if(gCrab == crab)
+ gCrab = mCrabs[i];
+ if(mCameraAttachedToActor == prevBody)
+ mCameraAttachedToActor = mCrabs[i]->getCrabBody();
+ }
+ }
+
+ // update camera
+ if(mCameraAttachedToActor)
+ mSubmarineCameraController->updateFollowingMode(getCamera(), dtime, mCameraAttachedToActor->getGlobalPose().p);
+
+ mScene->unlockWrite();
+
+ // start the simulation
+ PhysXSample::onTickPreRender(dtime);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::explode(PxRigidActor* actor, const PxVec3& explosionPos, const PxReal explosionStrength)
+{
+ size_t numRenderActors = mRenderActors.size();
+ for(PxU32 i = 0; i < numRenderActors; i++)
+ {
+ if(mRenderActors[i]->getPhysicsActor() == actor)
+ {
+ PxShape* shape = mRenderActors[i]->getPhysicsShape();
+ PxTransform pose = PxShapeExt::getGlobalPose(*shape, *actor);
+
+ PxGeometryHolder geom = shape->getGeometry();
+
+ // create new actor from shape (to split compound)
+ PxRigidDynamic* newActor = mPhysics->createRigidDynamic(pose);
+ if(!newActor) fatalError("createRigidDynamic failed!");
+
+ PxShape* newShape = PxRigidActorExt::createExclusiveShape(*newActor, geom.any(), *mMaterial);
+ unlink(mRenderActors[i], shape, actor);
+ link(mRenderActors[i], newShape, newActor);
+
+ newActor->setActorFlag(PxActorFlag::eVISUALIZATION, true);
+ newActor->setLinearDamping(10.5f);
+ newActor->setAngularDamping(0.5f);
+ PxRigidBodyExt::updateMassAndInertia(*newActor, 1.0f);
+ mScene->addActor(*newActor);
+ mPhysicsActors.push_back(newActor);
+
+ PxVec3 explosion = pose.p - explosionPos;
+ PxReal len = explosion.normalize();
+ explosion *= (explosionStrength / len);
+ newActor->setLinearVelocity(explosion);
+ newActor->setAngularVelocity(PxVec3(1,2,3));
+
+ }
+ }
+
+ removeActor(actor);
+}
+///////////////////////////////////////////////////////////////////////////////
+
+
+PxFilterFlags SampleSubmarineFilterShader(
+ PxFilterObjectAttributes attributes0, PxFilterData filterData0,
+ PxFilterObjectAttributes attributes1, PxFilterData filterData1,
+ PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
+{
+ // let triggers through
+ if(PxFilterObjectIsTrigger(attributes0) || PxFilterObjectIsTrigger(attributes1))
+ {
+ pairFlags = PxPairFlag::eTRIGGER_DEFAULT;
+ return PxFilterFlag::eDEFAULT;
+ }
+ // generate contacts for all that were not filtered above
+ pairFlags = PxPairFlag::eCONTACT_DEFAULT;
+
+ // trigger the contact callback for pairs (A,B) where
+ // the filtermask of A contains the ID of B and vice versa.
+ if((filterData0.word0 & filterData1.word1) && (filterData1.word0 & filterData0.word1))
+ pairFlags |= PxPairFlag::eNOTIFY_TOUCH_FOUND;
+
+ return PxFilterFlag::eDEFAULT;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::customizeSceneDesc(PxSceneDesc& sceneDesc)
+{
+ sceneDesc.filterShader = SampleSubmarineFilterShader;
+ sceneDesc.simulationEventCallback = this;
+ sceneDesc.flags |= PxSceneFlag::eREQUIRE_RW_LOCK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs)
+{
+ for(PxU32 i=0; i < nbPairs; i++)
+ {
+ const PxContactPair& cp = pairs[i];
+
+ if(cp.events & PxPairFlag::eNOTIFY_TOUCH_FOUND)
+ {
+ if((pairHeader.actors[0] == mSubmarineActor) || (pairHeader.actors[1] == mSubmarineActor))
+ {
+ PxActor* otherActor = (mSubmarineActor == pairHeader.actors[0]) ? pairHeader.actors[1] : pairHeader.actors[0];
+ Seamine* mine = reinterpret_cast<Seamine*>(otherActor->userData);
+ // insert only once
+ if(std::find(mMinesToExplode.begin(), mMinesToExplode.end(), mine) == mMinesToExplode.end())
+ mMinesToExplode.push_back(mine);
+
+ break;
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::onTrigger(PxTriggerPair* pairs, PxU32 count)
+{
+ for(PxU32 i=0; i < count; i++)
+ {
+ // ignore pairs when shapes have been deleted
+ if (pairs[i].flags & (PxTriggerPairFlag::eREMOVED_SHAPE_TRIGGER | PxTriggerPairFlag::eREMOVED_SHAPE_OTHER))
+ continue;
+
+ if((pairs[i].otherActor == mSubmarineActor) && (pairs[i].triggerActor == gTreasureActor))
+ {
+ gTreasureFound = true;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::helpRender(PxU32 x, PxU32 y, PxU8 textAlpha)
+{
+ SampleRenderer::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;
+
+ msg = mApplication.inputInfoMsg("Press "," to toggle various debug visualization", TOGGLE_VISUALIZATION, -1);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
+ msg = mApplication.inputInfoMsg("Press "," to restart", SCENE_RESET,-1);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
+ 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);
+ msg = mApplication.inputInfoMsg("Press "," to switch between submarine/crab/flyCam", CAMERA_SWITCH, -1);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
+
+ if(mCameraAttachedToActor == mSubmarineActor)
+ {
+ renderer->print(x, y += yInc, "Submarine Controller:", scale, shadowOffset, textColor);
+ const char* msg = mApplication.inputInfoMsg("Press "," to move along view direction", SUBMARINE_FORWARD, SUBMARINE_BACKWARD);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
+ msg = mApplication.inputInfoMsg("Press "," to raise and dive", SUBMARINE_UP, SUBMARINE_DOWN);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
+ }
+ else if(gCrab && (mCameraAttachedToActor == gCrab->getCrabBody()))
+ {
+ renderer->print(x, y += yInc, "Crab Controller:", scale, shadowOffset, textColor);
+ if (isPadSupported)
+ renderer->print(x, y += yInc, "Use left stick to move the crab", scale, shadowOffset, textColor);
+ const char* msg = mApplication.inputMoveInfoMsg("Press "," to move the crab", CRAB_FORWARD, CRAB_BACKWARD, CRAB_LEFT, CRAB_RIGHT);
+ if(msg)
+ renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
+ }
+ else
+ {
+ renderer->print(x, y += yInc, "Fly Cam Controller:", scale, shadowOffset, textColor);
+ if (isPadSupported)
+ renderer->print(x, y += yInc, "Use left stick to move",scale, shadowOffset, textColor);
+ const char* 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);
+ }
+}
+
+void SampleSubmarine::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 creation of jointed systems. In particular,";
+ char line1[256]="a complex system of driven joints is introduced to model crab motion,";
+ char line2[256]="while distance joints are used to model the tethering of exploding sea";
+ char line3[256]="mines to the seabed. Trigger shapes are presented to detect the";
+ char line4[256]="arrival of the submarine at a treasure chest on the ocean floor.";
+ char line5[256]="Similarly, contact notification is used to report the overlap of the";
+ char line6[256]="submarine with the exploding sea mines. Crab logic is governed by sdk";
+ char line7[256]="raycast results, and illustrates the application of the PhysX SDK task";
+ char line8[256]="scheduler.";
+
+ renderer->print(x, y+=yInc, line0, scale, shadowOffset, textColor);
+ renderer->print(x, y+=yInc, line1, scale, shadowOffset, textColor);
+ renderer->print(x, y+=yInc, line2, scale, shadowOffset, textColor);
+ renderer->print(x, y+=yInc, line3, scale, shadowOffset, textColor);
+ renderer->print(x, y+=yInc, line4, scale, shadowOffset, textColor);
+ renderer->print(x, y+=yInc, line5, scale, shadowOffset, textColor);
+ renderer->print(x, y+=yInc, line6, scale, shadowOffset, textColor);
+ renderer->print(x, y+=yInc, line7, scale, shadowOffset, textColor);
+ renderer->print(x, y+=yInc, line8, scale, shadowOffset, textColor);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::customizeRender()
+{
+ SampleRenderer::Renderer* renderer = getRenderer();
+ const PxU32 yInc = 18;
+ const RendererColor textColor(255, 255, 255, 255);
+
+ PxU32 width, height;
+ renderer->getWindowSize(width, height);
+ char healthBar[20];
+ PxU32 h = gSubmarineHealth;
+ sprintf(healthBar, "Health:%c%c%c%c%c%c%c%c%c%c", (h>90?'I':' '), (h>80?'I':' '), (h>70?'I':' '),(h>60?'I':' '),(h>50?'I':' '),
+ (h>40?'I':' '), (h>30?'I':' '), (h>20?'I':' '),(h>10?'I':' '),(h>0?'I':' '));
+ renderer->print(width-130, height-yInc, healthBar);
+ if(gTreasureFound)
+ renderer->print(width-160, height-2*yInc, "Treasure Found!");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void setFlag(PxU32& flags, PxU32 flag, bool set)
+{
+ if(set)
+ flags |= flag;
+ else
+ flags &= ~flag;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::onPointerInputEvent(const SampleFramework::InputEvent& ie, physx::PxU32 x, physx::PxU32 y, physx::PxReal dx, physx::PxReal dy, bool val)
+{
+ if(ie.m_Id== CAMERA_MOUSE_LOOK || !mSubmarineActor || mCameraAttachedToActor != mSubmarineActor)
+ PhysXSample::onPointerInputEvent(ie,x,y,dx,dy, val);
+
+ switch (ie.m_Id)
+ {
+ case SUBMARINE_FORWARD:
+ {
+ setFlag(gKeyFlags, Movement::eSUBMAINE_FWD, val);
+ }
+ break;
+ case SUBMARINE_BACKWARD:
+ {
+ setFlag(gKeyFlags, Movement::eSUBMAINE_BCKWD, val);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents)
+{
+ PhysXSample::collectInputEvents(inputEvents);
+
+ getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(CAMERA_MOVE_UP);
+ getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(CAMERA_MOVE_DOWN);
+ getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(CAMERA_SPEED_INCREASE);
+ getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(CAMERA_SPEED_DECREASE);
+ getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(CAMERA_MOVE_BUTTON);
+ getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(MOUSE_LOOK_BUTTON);
+ getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(SPAWN_DEBUG_OBJECT);
+
+ //digital mouse events
+ DIGITAL_INPUT_EVENT_DEF(SUBMARINE_FORWARD, MOUSE_BUTTON_LEFT, XKEY_UNKNOWN, X1KEY_UNKNOWN, PS3KEY_UNKNOWN, PS4KEY_UNKNOWN, AKEY_UNKNOWN, MOUSE_BUTTON_LEFT, IKEY_UNKNOWN, MOUSE_BUTTON_LEFT, WIIUKEY_UNKNOWN);
+ DIGITAL_INPUT_EVENT_DEF(SUBMARINE_BACKWARD, MOUSE_BUTTON_RIGHT, XKEY_UNKNOWN, X1KEY_UNKNOWN, PS3KEY_UNKNOWN, PS4KEY_UNKNOWN, AKEY_UNKNOWN, MOUSE_BUTTON_RIGHT, IKEY_UNKNOWN, MOUSE_BUTTON_RIGHT, WIIUKEY_UNKNOWN);
+
+ //digital keyboard events
+ DIGITAL_INPUT_EVENT_DEF(CRAB_FORWARD, SCAN_CODE_FORWARD, XKEY_W, X1KEY_W, PS3KEY_W, PS4KEY_W, AKEY_UNKNOWN, SCAN_CODE_FORWARD, IKEY_UNKNOWN, SCAN_CODE_FORWARD, WIIUKEY_UNKNOWN);
+ DIGITAL_INPUT_EVENT_DEF(CRAB_BACKWARD, SCAN_CODE_BACKWARD, XKEY_S, X1KEY_S, PS3KEY_S, PS4KEY_S, AKEY_UNKNOWN, SCAN_CODE_BACKWARD, IKEY_UNKNOWN, SCAN_CODE_BACKWARD, WIIUKEY_UNKNOWN);
+ DIGITAL_INPUT_EVENT_DEF(CRAB_LEFT, SCAN_CODE_LEFT, XKEY_A, X1KEY_A, PS3KEY_A, PS4KEY_A, AKEY_UNKNOWN, SCAN_CODE_LEFT, IKEY_UNKNOWN, SCAN_CODE_LEFT, WIIUKEY_UNKNOWN);
+ DIGITAL_INPUT_EVENT_DEF(CRAB_RIGHT, SCAN_CODE_RIGHT, XKEY_D, X1KEY_D, PS3KEY_D, PS4KEY_D, AKEY_UNKNOWN, SCAN_CODE_RIGHT, IKEY_UNKNOWN, SCAN_CODE_RIGHT, WIIUKEY_UNKNOWN);
+ DIGITAL_INPUT_EVENT_DEF(SUBMARINE_UP, SCAN_CODE_FORWARD, XKEY_E, X1KEY_E, PS3KEY_E, PS4KEY_E, AKEY_UNKNOWN, SCAN_CODE_FORWARD, IKEY_UNKNOWN, SCAN_CODE_FORWARD, WIIUKEY_UNKNOWN);
+ DIGITAL_INPUT_EVENT_DEF(SUBMARINE_DOWN, SCAN_CODE_BACKWARD, XKEY_D, X1KEY_D, PS3KEY_D, PS4KEY_D, AKEY_UNKNOWN, SCAN_CODE_BACKWARD, IKEY_UNKNOWN, SCAN_CODE_BACKWARD, WIIUKEY_UNKNOWN);
+ DIGITAL_INPUT_EVENT_DEF(CAMERA_SWITCH, SCAN_CODE_DOWN, XKEY_C, X1KEY_C, PS3KEY_C, PS4KEY_C, AKEY_UNKNOWN, SCAN_CODE_DOWN, IKEY_UNKNOWN, SCAN_CODE_DOWN, WIIUKEY_UNKNOWN);
+ DIGITAL_INPUT_EVENT_DEF(SCENE_RESET, WKEY_R, XKEY_R, X1KEY_R, PS3KEY_R, PS4KEY_R, AKEY_UNKNOWN, OSXKEY_R, IKEY_UNKNOWN, LINUXKEY_R, WIIUKEY_UNKNOWN);
+
+ //digital gamepad events
+ DIGITAL_INPUT_EVENT_DEF(SUBMARINE_FORWARD, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, AKEY_UNKNOWN, GAMEPAD_RIGHT_SHOULDER_BOT, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_RIGHT_SHOULDER_BOT);
+ DIGITAL_INPUT_EVENT_DEF(SUBMARINE_BACKWARD, GAMEPAD_LEFT_SHOULDER_BOT, GAMEPAD_LEFT_SHOULDER_BOT, GAMEPAD_LEFT_SHOULDER_BOT, GAMEPAD_LEFT_SHOULDER_BOT, GAMEPAD_LEFT_SHOULDER_BOT, AKEY_UNKNOWN, GAMEPAD_LEFT_SHOULDER_BOT, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_LEFT_SHOULDER_BOT);
+ DIGITAL_INPUT_EVENT_DEF(SUBMARINE_UP, 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(SUBMARINE_DOWN, 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);
+ DIGITAL_INPUT_EVENT_DEF(CAMERA_SWITCH, GAMEPAD_RIGHT_STICK, GAMEPAD_RIGHT_STICK, GAMEPAD_RIGHT_STICK, GAMEPAD_RIGHT_STICK, GAMEPAD_RIGHT_STICK, AKEY_UNKNOWN, GAMEPAD_RIGHT_STICK, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_RIGHT_STICK);
+ DIGITAL_INPUT_EVENT_DEF(SCENE_RESET, GAMEPAD_LEFT_STICK, GAMEPAD_LEFT_STICK, GAMEPAD_LEFT_STICK, GAMEPAD_LEFT_STICK, GAMEPAD_LEFT_STICK, AKEY_UNKNOWN, GAMEPAD_LEFT_STICK, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_LEFT_STICK);
+
+ // analog gamepad events
+ ANALOG_INPUT_EVENT_DEF(CRAB_LEFT_RIGHT, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, LINUXKEY_UNKNOWN, GAMEPAD_LEFT_STICK_X);
+ ANALOG_INPUT_EVENT_DEF(CRAB_FORWARD_BACKWARD, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, LINUXKEY_UNKNOWN, GAMEPAD_LEFT_STICK_Y);
+ ANALOG_INPUT_EVENT_DEF(SUBMARINE_FORWARD_BACKWARD, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_STICK_Y, XKEY_UNKNOWN, X1KEY_UNKNOWN, PS3KEY_UNKNOWN, PS4KEY_UNKNOWN, GAMEPAD_LEFT_STICK_Y, OSXKEY_UNKNOWN, GAMEPAD_LEFT_STICK_Y, LINUXKEY_UNKNOWN, WIIUKEY_UNKNOWN);
+
+ //touch events
+ TOUCH_INPUT_EVENT_DEF(SCENE_RESET, "Reset", ABUTTON_5, IBUTTON_5);
+ TOUCH_INPUT_EVENT_DEF(CAMERA_SWITCH, "Switch Cam", ABUTTON_6, IBUTTON_6);
+ TOUCH_INPUT_EVENT_DEF(SUBMARINE_UP, "Rise", ABUTTON_7, IBUTTON_7);
+ TOUCH_INPUT_EVENT_DEF(SUBMARINE_DOWN, "Drop", ABUTTON_8, IBUTTON_8);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::onDigitalInputEvent(const SampleFramework::InputEvent& ie, bool val)
+{
+ if(mSubmarineActor && mCameraAttachedToActor == mSubmarineActor)
+ {
+ switch (ie.m_Id)
+ {
+ case SUBMARINE_FORWARD:
+ setFlag(gKeyFlags, Movement::eSUBMAINE_FWD, val);
+ break;
+ case SUBMARINE_BACKWARD:
+ setFlag(gKeyFlags, Movement::eSUBMAINE_BCKWD, val);
+ break;
+ case SUBMARINE_UP:
+ setFlag(gKeyFlags, Movement::eSUBMAINE_UP, val);
+ break;
+ case SUBMARINE_DOWN:
+ setFlag(gKeyFlags, Movement::eSUBMAINE_DOWN, val);
+ break;
+ }
+ }
+ else if (gCrab && mCameraAttachedToActor == gCrab->getCrabBody())
+ {
+ switch (ie.m_Id)
+ {
+ case CRAB_FORWARD:
+ setFlag(gKeyFlags, Movement::eCRAB_FWD, val);
+ break;
+ case CRAB_BACKWARD:
+ setFlag(gKeyFlags, Movement::eCRAB_BCKWD, val);
+ break;
+ case CRAB_LEFT:
+ setFlag(gKeyFlags, Movement::eCRAB_ROTATE_LEFT, val);
+ break;
+ case CRAB_RIGHT:
+ setFlag(gKeyFlags, Movement::eCRAB_ROTATE_RIGHT, val);
+ break;
+ }
+ }
+
+ if (val)
+ {
+ switch (ie.m_Id)
+ {
+ case CAMERA_SWITCH:
+ {
+ // cycle camera
+ if(mSubmarineActor && mCameraAttachedToActor == NULL)
+ mCameraAttachedToActor = mSubmarineActor;
+ else if(gCrab && mCameraAttachedToActor != gCrab->getCrabBody())
+ mCameraAttachedToActor = gCrab->getCrabBody();
+ else
+ mCameraAttachedToActor = NULL;
+
+ mSubmarineCameraController->init(getCamera().getPos(), getCamera().getRot());
+ mSubmarineCameraController->setFollowingMode(mCameraAttachedToActor != NULL);
+ }
+ break;
+ case SCENE_RESET:
+ {
+ gResetScene = true;
+ }
+ break;
+ }
+ }
+
+ PhysXSample::onDigitalInputEvent(ie,val);
+}
+
+void SampleSubmarine::onAnalogInputEvent(const SampleFramework::InputEvent& ie, float val)
+{
+ if (mSubmarineActor && mCameraAttachedToActor == mSubmarineActor)
+ {
+ switch (ie.m_Id)
+ {
+ case SUBMARINE_FORWARD_BACKWARD:
+ {
+ setFlag(gKeyFlags, Movement::eSUBMAINE_FWD, val > 0.3f);
+ setFlag(gKeyFlags, Movement::eSUBMAINE_BCKWD, val < -0.3f);
+ }
+ break;
+ }
+ }
+ if(gCrab && mCameraAttachedToActor == gCrab->getCrabBody())
+ {
+ switch (ie.m_Id)
+ {
+ case CRAB_FORWARD_BACKWARD:
+ {
+ setFlag(gKeyFlags, Movement::eCRAB_FWD, val > 0.3f);
+ setFlag(gKeyFlags, Movement::eCRAB_BCKWD, val < -0.3f);
+ }
+ break;
+ case CRAB_LEFT_RIGHT:
+ {
+ setFlag(gKeyFlags, Movement::eCRAB_ROTATE_LEFT, val > 0.3f);
+ setFlag(gKeyFlags, Movement::eCRAB_ROTATE_RIGHT, val < -0.3f);
+ }
+ break;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SampleSubmarine::handleInput()
+{
+ if(gCrab && mCameraAttachedToActor == gCrab->getCrabBody())
+ {
+ PxReal accFactor = 3.0f;
+ PxReal forward = 0, rot = 0;
+ if(gKeyFlags & Movement::eCRAB_FWD)
+ forward = 1.0f;
+ if(gKeyFlags & Movement::eCRAB_BCKWD)
+ forward = -1.0f;
+ if(gKeyFlags & Movement::eCRAB_ROTATE_LEFT)
+ rot = 1.0f;
+ if(gKeyFlags & Movement::eCRAB_ROTATE_RIGHT)
+ rot = -1.0f;
+ PxReal left = rot + forward;
+ PxReal right = -rot + forward;
+ gCrab->setAcceleration(left*accFactor, right*accFactor);
+ }
+ else if(mSubmarineActor && mCameraAttachedToActor == mSubmarineActor)
+ {
+ if(gKeyFlags & Movement::eSUBMAINE_FWD)
+ gForce.x -= gLinPower;
+ if(gKeyFlags & Movement::eSUBMAINE_BCKWD)
+ gForce.x += gLinPower;
+ if(gKeyFlags & Movement::eSUBMAINE_UP)
+ gForce.y += gLinPower;
+ if(gKeyFlags & Movement::eSUBMAINE_DOWN)
+ gForce.y -= gLinPower;
+
+ if(gKeyFlags & (Movement::eSUBMAINE_FWD|Movement::eSUBMAINE_BCKWD))
+ {
+ PxSceneReadLock scopedLock(*mScene);
+
+ static const PxReal camEpsilon = 0.001f;
+ PxTransform subPose = mSubmarineActor->getGlobalPose();
+ PxVec3 cameraDir = getCamera().getViewDir();
+ PxVec3 cameraDirInSub = subPose.rotateInv(cameraDir).getNormalized();
+ PxVec3 cameraUpInSub = subPose.rotateInv(PxVec3(0,1,0)).getNormalized();
+
+ if(PxAbs(cameraDirInSub.z) > camEpsilon)
+ gTorque.y += gAngPower*cameraDirInSub.z;
+ if(PxAbs(cameraDirInSub.y) > camEpsilon)
+ gTorque.z -= gAngPower*cameraDirInSub.y;
+ if(PxAbs(cameraUpInSub.z) > camEpsilon)
+ gTorque.x += gAngPower*cameraUpInSub.z;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+