This commit is contained in:
2025-11-28 23:13:44 +05:30
commit a3a8e79709
7360 changed files with 1156074 additions and 0 deletions

View File

@ -0,0 +1,238 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 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 "characterkinematic/PxControllerManager.h"
#include "PxPhysicsAPI.h"
#include "SampleNorthPole.h"
#include "SampleNorthPoleCameraController.h"
#include "SampleUtils.h"
#include "SampleCommandLine.h"
#include "SampleAllocatorSDKClasses.h"
#include "RendererMemoryMacros.h"
#include "RenderMaterial.h"
#include "SampleNorthPoleInputEventIds.h"
#include <SamplePlatform.h>
#include <SampleUserInput.h>
REGISTER_SAMPLE(SampleNorthPole, "SampleNorthPole")
using namespace SampleFramework;
using namespace SampleRenderer;
///////////////////////////////////////////////////////////////////////////////
SampleNorthPole::SampleNorthPole(PhysXSampleApplication& app) :
PhysXSample (app),
mNorthPoleCamera (NULL),
mController (NULL),
mControllerManager (NULL),
mDoStandup (false)
{
mCreateGroundPlane = false;
//mStepperType = FIXED_STEPPER;
mStandingSize = 1.0f;
mCrouchingSize = 0.20f;
mControllerRadius = 0.3f;
mControllerInitialPosition = PxExtendedVec3(5,mStandingSize,5);
memset(mSnowBalls,0,sizeof(mSnowBalls));
memset(mSnowBallsRenderActors,0,sizeof(mSnowBallsRenderActors));
}
SampleNorthPole::~SampleNorthPole()
{
}
///////////////////////////////////////////////////////////////////////////////
void SampleNorthPole::customizeSample(SampleSetup& setup)
{
setup.mName = "SampleNorthPole";
}
///////////////////////////////////////////////////////////////////////////////
void SampleNorthPole::onInit()
{
PhysXSample::onInit();
PxSceneWriteLock scopedLock(*mScene);
mApplication.setMouseCursorHiding(true);
mApplication.setMouseCursorRecentering(true);
getRenderer()->setAmbientColor(RendererColor(100, 100, 100));
// some colors for the rendering
mSnowMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(), PxVec3(0.85f, 0.85f, 0.95f), 1.0f, false, 0, NULL);
mCarrotMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(), PxVec3(1.00f, 0.50f, 0.00f), 1.0f, false, 1, NULL);
mButtonMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(), PxVec3(0.00f, 0.00f, 0.00f), 1.0f, false, 2, NULL);
mRenderMaterials.push_back(mSnowMaterial);
mRenderMaterials.push_back(mCarrotMaterial);
mRenderMaterials.push_back(mButtonMaterial);
// PhysX
buildHeightField();
buildIglooTriMesh();
// add some stand-up characters
cookCarrotConvexMesh();
createSnowMen();
mControllerManager = PxCreateControllerManager(getActiveScene());
mController = createCharacter(mControllerInitialPosition);
mNorthPoleCamera = SAMPLE_NEW(SampleNorthPoleCameraController)(*mController,*this);
setCameraController(mNorthPoleCamera);
mNorthPoleCamera->setView(0,0);
}
void SampleNorthPole::onShutdown()
{
{
PxSceneWriteLock scopedLock(*mScene);
DELETESINGLE(mNorthPoleCamera);
mControllerManager->release();
}
PhysXSample::onShutdown();
}
void SampleNorthPole::helpRender(PxU32 x, PxU32 y, PxU8 textAlpha)
{
Renderer* renderer = getRenderer();
const PxU32 yInc = 18;
const PxReal scale = 0.5f;
const PxReal shadowOffset = 6.0f;
const RendererColor textColor(255, 255, 255, textAlpha);
const bool isMouseSupported = getApplication().getPlatform()->getSampleUserInput()->mouseSupported();
const bool isPadSupported = getApplication().getPlatform()->getSampleUserInput()->gamepadSupported();
const char* msg;
if (isMouseSupported && isPadSupported)
renderer->print(x, y += yInc, "Use mouse or right stick to rotate the camera", scale, shadowOffset, textColor);
else if (isMouseSupported)
renderer->print(x, y += yInc, "Use mouse to rotate the camera", scale, shadowOffset, textColor);
else if (isPadSupported)
renderer->print(x, y += yInc, "Use right stick to rotate the camera", scale, shadowOffset, textColor);
if (isPadSupported)
renderer->print(x, y += yInc, "Use left stick to move",scale, shadowOffset, textColor);
msg = mApplication.inputMoveInfoMsg("Press "," to move", CAMERA_MOVE_FORWARD,CAMERA_MOVE_BACKWARD, CAMERA_MOVE_LEFT, CAMERA_MOVE_RIGHT);
if(msg)
renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
msg = mApplication.inputInfoMsg("Press "," to move fast", CAMERA_SHIFT_SPEED, -1);
if(msg)
renderer->print(x, y += yInc, msg, scale, shadowOffset, textColor);
msg = mApplication.inputInfoMsg("Press "," to crouch", CROUCH, -1);
if(msg)
renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
msg = mApplication.inputInfoMsg("Press "," to reset scene", RESET_SCENE, -1);
if(msg)
renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
msg = mApplication.inputInfoMsg("Press "," to throw a ball", THROW_BALL, -1);
if(msg)
renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
}
void SampleNorthPole::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 dynamic objects (snowmen) with";
char line1[256]="multiple shapes. The snowmen, though visibly identical, are configured";
char line2[256]="with different masses, inertias and centres of mass in order to show how";
char line3[256]="to set up these properties using the sdk, and the effect they have on";
char line4[256]="behavior. A technical description of the snowmen's rigid body properties";
char line5[256]="can be found in the PhysX Guide documentation in Rigid Body Dynamics:";
char line6[256]="Mass Properties. The sample also introduces contact notification reports as";
char line7[256]="a mechanism to detach snowman body parts, and applies ccd flags in order";
char line8[256]="to prevent small objects such as snowballs and detached snowman body parts ";
char line9[256]="from tunneling through collision geometry.";
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);
renderer->print(x, y+=yInc, line9, scale, shadowOffset, textColor);
}
}
void SampleNorthPole::onTickPreRender(PxReal dtime)
{
if(mDoStandup)
tryStandup();
PhysXSample::onTickPreRender(dtime);
}
void SampleNorthPole::onSubstep(float dtime)
{
detach();
}
void SampleNorthPole::onPointerInputEvent(const SampleFramework::InputEvent& ie, physx::PxU32 x, physx::PxU32 y, physx::PxReal dx, physx::PxReal dy, bool val)
{
if((ie.m_Id == THROW_BALL) && val)
{
throwBall();
}
if((ie.m_Id == RAYCAST_HIT) && val)
{
PxRaycastBuffer hit;
getActiveScene().raycast(getCamera().getPos()+getCamera().getViewDir(), getCamera().getViewDir(), 1.0f, hit);
shdfnd::printFormatted("hits: %p\n",hit.block.shape);
}
PhysXSample::onPointerInputEvent(ie,x,y,dx,dy,val);
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,196 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SAMPLE_NORTHPOLE_H
#define SAMPLE_NORTHPOLE_H
#include "PhysXSample.h"
#include "PxSimulationEventCallback.h"
#include "characterkinematic/PxController.h" // for PxUserControllerHitReport
#include "characterkinematic/PxControllerBehavior.h"
#include "PxShape.h"
namespace physx
{
class PxCapsuleController;
class PxControllerManager;
}
class SampleNorthPoleCameraController;
#define NUM_SNOWMEN 10
#define NUM_BALLS 50
struct SnowMan
{
PxShape* eyeL;
PxShape* eyeR;
void changeMood()
{
PxTransform tl = eyeL->getLocalPose();
PxTransform tr = eyeR->getLocalPose();
eyeL->setLocalPose(PxTransform(tl.p,tr.q));
eyeR->setLocalPose(PxTransform(tr.p,tl.q));
}
};
class SampleNorthPole : public PhysXSample,
public PxSimulationEventCallback,
public PxUserControllerHitReport,
public PxControllerBehaviorCallback
{
public:
SampleNorthPole(PhysXSampleApplication& app);
virtual ~SampleNorthPole();
///////////////////////////////////////////////////////////////////////////////
// Implements SampleApplication
virtual void onInit();
virtual void onInit(bool restart) { onInit(); }
virtual void onShutdown();
virtual void onTickPreRender(PxReal dtime);
virtual void onPointerInputEvent(const SampleFramework::InputEvent& ie, physx::PxU32 x, physx::PxU32 y, physx::PxReal dx, physx::PxReal dy, bool val);
virtual void onDigitalInputEvent(const SampleFramework::InputEvent& , bool val);
virtual void collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents);
///////////////////////////////////////////////////////////////////////////////
// Implements PhysXSampleApplication
virtual void helpRender(PxU32 x, PxU32 y, PxU8 textAlpha);
virtual void descriptionRender(PxU32 x, PxU32 y, PxU8 textAlpha);
virtual void customizeSample(SampleSetup&);
virtual void customizeSceneDesc(PxSceneDesc&);
virtual void onSubstep(float dtime);
///////////////////////////////////////////////////////////////////////////////
// Implements PxSimulationEventCallback
virtual void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs);
virtual void onTrigger(PxTriggerPair*, PxU32) {}
virtual void onConstraintBreak(PxConstraintInfo*, PxU32) {}
virtual void onWake(PxActor** , PxU32 ) {}
virtual void onSleep(PxActor** , PxU32 ){}
virtual void onAdvance(const PxRigidBody*const*, const PxTransform*, const PxU32) {}
///////////////////////////////////////////////////////////////////////////////
// Implements PxUserControllerHitReport
virtual void onShapeHit(const PxControllerShapeHit& hit);
virtual void onControllerHit(const PxControllersHit& hit) {}
virtual void onObstacleHit(const PxControllerObstacleHit& hit) {}
// Implements PxControllerBehaviorCallback
virtual PxControllerBehaviorFlags getBehaviorFlags(const PxShape&, const PxActor&) { return PxControllerBehaviorFlags(0); }
virtual PxControllerBehaviorFlags getBehaviorFlags(const PxController&) { return PxControllerBehaviorFlags(0); }
virtual PxControllerBehaviorFlags getBehaviorFlags(const PxObstacle&) { return PxControllerBehaviorFlags(0); }
///////////////////////////////////////////////////////////////////////////////
// Implements PxSimulationFilterShader
static PxFilterFlags filter( PxFilterObjectAttributes attributes0,
PxFilterData filterData0,
PxFilterObjectAttributes attributes1,
PxFilterData filterData1,
PxPairFlags& pairFlags,
const void* constantBlock,
PxU32 constantBlockSize);
///////////////////////////////////////////////////////////////////////////////
// dynamics
enum
{
CCD_FLAG = 1<<29,
SNOWBALL_FLAG = 1<<30,
DETACHABLE_FLAG = 1<<31
};
void cookCarrotConvexMesh();
PxConvexMesh* mCarrotConvex;
PxRigidDynamic* throwBall();
PxRigidDynamic* mSnowBalls[NUM_BALLS];
RenderBaseActor* mSnowBallsRenderActors[NUM_BALLS];
void createSnowMen();
PxRigidDynamic* createSnowMan(const PxTransform& pos, const PxU32 mode, const PxU32 index);
SnowMan mSnowman[NUM_SNOWMEN+1]; // 1 extra so that NUM_SNOWMEN can be set to 0 for debugging
void resetScene();
static void setSnowball(PxShape& shape);
static void setDetachable(PxShape& shape);
static bool isDetachable(PxFilterData& filterData);
static bool needsContactReport(const PxFilterData& filterData0, const PxFilterData& filterData1);
static void setCCDActive(PxShape& shape, PxRigidBody* rigidBody);
static bool isCCDActive(PxFilterData& filterData);
void detach();
std::vector<PxShape*> mDetaching;
///////////////////////////////////////////////////////////////////////////////
// static landscape
std::vector<PxVec3> mVerts;
std::vector<PxVec3> mNorms;
std::vector<PxU32> mTris;
PxRigidStatic* buildIglooTriMesh();
void addBlock(PxVec3 blockVerts[8]);
PxRigidStatic* buildHeightField();
void createLandscape(PxReal* heightmap, PxU32 size, PxReal scale, PxReal* outVerts, PxReal* outNorms, PxU32* outTris);
PxRigidStatic* createHeightField(PxReal* heightmap, PxReal scale, PxU32 size);
///////////////////////////////////////////////////////////////////////////////
// Camera and Controller
SampleNorthPoleCameraController* mNorthPoleCamera;
PxCapsuleController* mController;
PxControllerManager* mControllerManager;
PxExtendedVec3 mControllerInitialPosition;
bool mDoStandup;
PxReal mControllerRadius;
PxReal mStandingSize;
PxReal mCrouchingSize;
PxCapsuleController* createCharacter(const PxExtendedVec3& position);
void tryStandup();
void resizeController(PxReal height);
///////////////////////////////////////////////////////////////////////////////
// rendering
RenderMaterial* mSnowMaterial;
RenderMaterial* mCarrotMaterial;
RenderMaterial* mButtonMaterial;
};
#endif

View File

@ -0,0 +1,450 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxPhysicsAPI.h"
#include "PxTkStream.h"
#include "SampleNorthPole.h"
using namespace PxToolkit;
#define USE_MESH_LANDSCAPE // PT: define this to use a triangle mesh for the landscape, instead of a heightfield
static PxReal randomScaled(PxReal value)
{
PxReal val = value*(getSampleRandom().randomFloat());
return val;
}
static void computeTerrain(bool* done, PxReal* pVB, PxU32 x0, PxU32 y0, PxU32 currentSize, PxReal value, PxU32 initSize)
{
// Compute new size
currentSize>>=1;
if (currentSize > 0) {
PxU32 x1 = (x0+currentSize) % initSize;
PxU32 x2 = (x0+currentSize+currentSize) % initSize;
PxU32 y1 = (y0+currentSize) % initSize;
PxU32 y2 = (y0+currentSize+currentSize) % initSize;
if(!done[x1 + y0*initSize]) pVB[(x1 + y0*initSize)] = randomScaled(value) + 0.5f * (pVB[(x0 + y0*initSize)] + pVB[(x2 + y0*initSize)]);
if(!done[x0 + y1*initSize]) pVB[(x0 + y1*initSize)] = randomScaled(value) + 0.5f * (pVB[(x0 + y0*initSize)] + pVB[(x0 + y2*initSize)]);
if(!done[x2 + y1*initSize]) pVB[(x2 + y1*initSize)] = randomScaled(value) + 0.5f * (pVB[(x2 + y0*initSize)] + pVB[(x2 + y2*initSize)]);
if(!done[x1 + y2*initSize]) pVB[(x1 + y2*initSize)] = randomScaled(value) + 0.5f * (pVB[(x0 + y2*initSize)] + pVB[(x2 + y2*initSize)]);
if(!done[x1 + y1*initSize]) pVB[(x1 + y1*initSize)] = randomScaled(value) + 0.5f * (pVB[(x0 + y1*initSize)] + pVB[(x2 + y1*initSize)]);
done[x1 + y0*initSize] = true; done[x0 + y1*initSize] = true; done[x2 + y1*initSize] = true; done[x1 + y2*initSize] = true; done[x1 + y1*initSize] = true;
// Recurse through 4 corners
value *= 0.5f;
computeTerrain(done, pVB, x0, y0, currentSize, value, initSize);
computeTerrain(done, pVB, x0, y1, currentSize, value, initSize);
computeTerrain(done, pVB, x1, y0, currentSize, value, initSize);
computeTerrain(done, pVB, x1, y1, currentSize, value, initSize);
}
}
static void fractalize(PxReal* heights, const PxU32 size, const PxReal roughness)
{
PxU32 num = size*size;
bool* done = (bool*)SAMPLE_ALLOC(sizeof(bool)*num);
for(PxU32 i=0; i<num; i++)
done[i]=false;
computeTerrain(done,heights,0,0,size,roughness,size);
SAMPLE_FREE(done);
}
PxRigidStatic* SampleNorthPole::buildHeightField()
{
// create a height map
PxU32 hfSize = 32; // some power of 2
PxU32 hfNumVerts = hfSize*hfSize;
PxReal hfScale = 8.0f; // this is how wide one heightfield square is
PxReal* heightmap = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal)*hfNumVerts);
for(PxU32 i = 0; i < hfNumVerts; i++)
heightmap[i]=-9.0f;
getSampleRandom().setSeed(42);
fractalize(heightmap,hfSize,16);
{ // make a plateau to place the igloo
const PxU32 i = hfSize*hfSize/2+hfSize/2;
PxReal h = 0;
heightmap[i-hfSize-1]=h; heightmap[i-hfSize]=h; heightmap[i-hfSize+1]=h;
heightmap[i-1]=h; heightmap[i]=h; heightmap[i+1]=h;
heightmap[i+hfSize-1]=h; heightmap[i+hfSize]=h; heightmap[i+hfSize+1]=h;
}
{ // make render terrain
PxReal* hfVerts = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal)*hfNumVerts*3);
PxReal* hfNorms = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal)*hfNumVerts*3);
PxU32 hfNumTris = (hfSize-1)*(hfSize-1)*2;
PxU32* hfTris = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*hfNumTris*3);
createLandscape(heightmap,hfSize,hfScale,hfVerts,hfNorms,hfTris);
RAWMesh data;
data.mName = "terrain";
data.mTransform = PxTransform(PxIdentity);
data.mTransform.p = PxVec3(-(hfSize/2*hfScale),0,-(hfSize/2*hfScale));
data.mNbVerts = hfNumVerts;
data.mVerts = (PxVec3*)hfVerts;
data.mVertexNormals = (PxVec3*)hfNorms;
data.mUVs = 0;
data.mMaterialID = 0;
data.mNbFaces = hfNumTris;
data.mIndices = hfTris;
#ifdef USE_MESH_LANDSCAPE
setFilename(getSampleMediaFilename("SampleNorthPole_Mesh"));
newMesh(data);
#else
createRenderMeshFromRawMesh(data);
#endif
SAMPLE_FREE(hfTris);
SAMPLE_FREE(hfNorms);
SAMPLE_FREE(hfVerts);
}
#ifndef USE_MESH_LANDSCAPE
// eventually create the physics heightfield
PxRigidStatic* hfActor = createHeightField(heightmap,hfScale,hfSize);
#endif
SAMPLE_FREE(heightmap);
#ifdef USE_MESH_LANDSCAPE
return 0;
#else
return hfActor;
#endif
}
void SampleNorthPole::createLandscape(PxReal* heightmap, PxU32 width, PxReal hfScale, PxReal* outVerts, PxReal* outNorms, PxU32* outTris)
{
for(PxU32 y=0; y<width; y++)
{
for(PxU32 x=0; x<width; x++)
{
PxU32 index=(x+y*width)*3;
outVerts[index+0]=(PxReal(x))* hfScale;
outVerts[index+1]=heightmap[x+y*width];
outVerts[index+2]=(PxReal(y))*hfScale;
outNorms[index+0]=0;
outNorms[index+1]=1;
outNorms[index+2]=0;
}
}
// Sobel filter
for (PxU32 y=1;y<width-1;y++) {
for (PxU32 x=1;x<width-1;x++) {
// 1 0 -1
// 2 0 -2
// 1 0 -1
PxReal dx;
dx = outVerts[((x-1)+(y-1)*width)*3+1];
dx -= outVerts[((x+1)+(y-1)*width)*3+1];
dx += 2.0f*outVerts[((x-1)+(y+0)*width)*3+1];
dx -= 2.0f*outVerts[((x+1)+(y+0)*width)*3+1];
dx += outVerts[((x-1)+(y+1)*width)*3+1];
dx -= outVerts[((x+1)+(y+1)*width)*3+1];
// 1 2 1
// 0 0 0
// -1 -2 -1
PxReal dy;
dy = outVerts[((x-1)+(y-1)*width)*3+1];
dy += 2.0f*outVerts[((x+0)+(y-1)*width)*3+1];
dy += outVerts[((x+1)+(y-1)*width)*3+1];
dy -= outVerts[((x-1)+(y+1)*width)*3+1];
dy -= 2.0f*outVerts[((x+0)+(y+1)*width)*3+1];
dy -= outVerts[((x+1)+(y+1)*width)*3+1];
PxReal nx = dx/hfScale*0.15f;
PxReal ny = 1.0f;
PxReal nz = dy/hfScale*0.15f;
PxReal len = sqrtf(nx*nx+ny*ny+nz*nz);
outNorms[(x+y*width)*3+0] = nx/len;
outNorms[(x+y*width)*3+1] = ny/len;
outNorms[(x+y*width)*3+2] = nz/len;
}
}
PxU32 numTris = 0;
for(PxU32 j=0; j<width-1; j++)
{
for(PxU32 i=0; i<width-1; i++)
{
outTris[3*numTris+0]= i + j *(width);
outTris[3*numTris+1]= i + (j+1)*(width);
outTris[3*numTris+2]= i+1 + j *(width);
outTris[3*numTris+3]= i + (j+1)*(width);
outTris[3*numTris+4]= i+1 + (j+1)*(width);
outTris[3*numTris+5]= i+1 + j *(width);
numTris+=2;
}
}
}
PxRigidStatic* SampleNorthPole::createHeightField(PxReal* heightmap, PxReal hfScale, PxU32 hfSize)
{
const PxReal heightScale = 0.001f;
PxU32 hfNumVerts = hfSize*hfSize;
PxHeightFieldSample* samples = (PxHeightFieldSample*)SAMPLE_ALLOC(sizeof(PxHeightFieldSample)*hfNumVerts);
memset(samples,0,hfNumVerts*sizeof(PxHeightFieldSample));
for(PxU32 x = 0; x < hfSize; x++)
for(PxU32 y = 0; y < hfSize; y++)
{
samples[x+y*hfSize].height = (PxI16)(heightmap[y+x*hfSize]/heightScale);
samples[x+y*hfSize].setTessFlag();
samples[x+y*hfSize].materialIndex0=1;
samples[x+y*hfSize].materialIndex1=1;
}
PxHeightFieldDesc hfDesc;
hfDesc.format = PxHeightFieldFormat::eS16_TM;
hfDesc.nbColumns = hfSize;
hfDesc.nbRows = hfSize;
hfDesc.samples.data = samples;
hfDesc.samples.stride = sizeof(PxHeightFieldSample);
PxHeightField* heightField = getCooking().createHeightField(hfDesc, getPhysics().getPhysicsInsertionCallback());
if(!heightField)
fatalError("creating the heightfield failed");
PxTransform pose = PxTransform(PxIdentity);
pose.p = PxVec3(-(hfSize/2*hfScale),0,-(hfSize/2*hfScale));
PxRigidStatic* hfActor = getPhysics().createRigidStatic(pose);
if(!hfActor)
fatalError("creating heightfield actor failed");
PxHeightFieldGeometry hfGeom(heightField, PxMeshGeometryFlags(), heightScale, hfScale, hfScale);
PxShape* hfShape = PxRigidActorExt::createExclusiveShape(*hfActor, hfGeom, getDefaultMaterial());
//setCCDActive(*hfShape);
if(!hfShape)
fatalError("creating heightfield shape failed");
getActiveScene().addActor(*hfActor);
SAMPLE_FREE(samples);
return hfActor;
}
PxRigidStatic* SampleNorthPole::buildIglooTriMesh()
{
{ // construct the mesh data
const PxReal innerR = 2.7f;
const PxReal outerR = 3;
const PxU32 numBlocks = 16;
const PxU32 numRows = 8;
const PxU32 doorHeight = 2;
const PxReal accesslength = outerR*1.2f;
const PxReal step = PxPi*2/numBlocks;
const PxReal step2 = PxPi/2/numRows;
const PxReal thickness = (outerR - innerR);
const PxVec3 initpos(1,0,0);
const PxU32 n = 2*numBlocks;
PxVec3 bufferVerts[2][n+2];
PxU32 buf = 0;
PxVec3* currentVerts = bufferVerts[buf];
for(int i = 0; i < (int)numBlocks; i++)
{
PxQuat rotY(i*step-step/2,PxVec3(0,1,0));
PxVec3 pos = rotY.rotate(initpos);
currentVerts[2*i] = pos*innerR;
currentVerts[2*i+1] = pos*outerR;
}
currentVerts[n] = currentVerts[0];
currentVerts[n+1] = currentVerts[1];
for(int j = 0; j < (int)numRows; j++)
{
PxVec3* previousVerts = currentVerts;
currentVerts = bufferVerts[buf=1-buf];
PxQuat rotZ((j+1)*step2,PxVec3(0,0,1));
PxVec3 posX = rotZ.rotate(initpos);
for(int i = 0; i < (int)numBlocks; i++)
{
PxQuat rotY(i*step-step/2,PxVec3(0,1,0));
PxVec3 pos = rotY.rotate(posX);
currentVerts[2*i] = pos*innerR;
currentVerts[2*i+1] = pos*outerR;
}
currentVerts[n] = currentVerts[0];
currentVerts[n+1] = currentVerts[1];
for(int i = 0; i < (int)numBlocks; i++)
{
if( (i==0 && (j<(int)doorHeight)) || (i==numBlocks/3 && j==numRows/2) )
{
// omit the door and window
continue;
}
PxVec3 block[8] =
{
previousVerts[2*i],previousVerts[2*i+1],previousVerts[2*i+2],previousVerts[2*i+3],
currentVerts[2*i], currentVerts[2*i+1], currentVerts[2*i+2], currentVerts[2*i+3]
};
addBlock(block);
}
}
PxQuat rotZ((doorHeight)*step2,PxVec3(0,0,1));
PxQuat rotY(step/2,PxVec3(0,1,0));
PxVec3 topIL = rotY.rotate(rotZ.rotate(initpos))*innerR;
PxVec3 topIR = rotY.rotateInv(rotZ.rotate(initpos))*innerR;
PxVec3 topOL = topIL; topOL.x = accesslength;
PxVec3 topOR = topIR; topOR.x = accesslength;
PxVec3 bottomIL = rotY.rotate(initpos)*innerR;
PxVec3 bottomIR = rotY.rotateInv(initpos)*innerR;
PxVec3 bottomOL = topOL; bottomOL.y = 0;
PxVec3 bottomOR = topOR; bottomOR.y = 0;
PxVec3 dZ = PxVec3(0,0,thickness);
PxVec3 dY = PxVec3(0,thickness,0);
PxVec3 blockL[8] =
{
bottomIL, bottomOL, bottomIL-dZ, bottomOL-dZ,
topIL, topOL, topIL-dZ, topOL-dZ
};
addBlock(blockL);
PxVec3 blockR[8] =
{
bottomIR+dZ, bottomOR+dZ, bottomIR, bottomOR,
topIR+dZ, topOR+dZ, topIR, topOR
};
addBlock(blockR);
PxVec3 blockT[8] =
{
topIR+dZ, topOR+dZ, topIL-dZ, topOL-dZ,
topIR+dY, topOR+dY, topIL+dY, topOL+dY
};
addBlock(blockT);
}
const PxU32 numTris = (PxU32)(mTris.size()/3);
const PxU32 numVerts = (PxU32)(mVerts.size());
// make render mesh
RAWMesh data;
data.mIndices = &mTris[0];
data.mNbFaces = numTris;
data.mVerts = &mVerts[0];
data.mNbVerts = numVerts;
data.mVertexNormals = &mVerts[0];
data.mMaterialID = 0;
data.mTransform = PxTransform(PxVec3(0,0,0));
createRenderMeshFromRawMesh(data);
PxTriangleMesh* triMesh = PxToolkit::createTriangleMesh32(getPhysics(), getCooking(), &mVerts[0], numVerts, &mTris[0], numTris);
if(!triMesh)
fatalError("creating the triangle mesh failed");
mVerts.clear();
mTris.clear();
mNorms.clear();
// create actor
PxRigidStatic* iglooActor = getPhysics().createRigidStatic(PxTransform(PxVec3(0,0,0)));
if(!iglooActor)
fatalError("creating igloo actor failed");
PxTriangleMeshGeometry geom(triMesh);
PxShape* iglooShape = PxRigidActorExt::createExclusiveShape(*iglooActor, geom,getDefaultMaterial());
if(!iglooShape)
fatalError("creating igloo shape failed");
//setCCDActive(*iglooShape);
getActiveScene().addActor(*iglooActor);
return iglooActor;
}
void SampleNorthPole::addBlock(PxVec3 blockVerts[8])
{
PxU32 n = 8;
PxVec3* v = blockVerts;
const PxU32 offset = (PxU32)mVerts.size();
while(n--)
mVerts.push_back(*v++);
// bottom
mTris.push_back(0 + offset); mTris.push_back(3 + offset); mTris.push_back(1 + offset);
mTris.push_back(0 + offset); mTris.push_back(2 + offset); mTris.push_back(3 + offset);
// top
mTris.push_back(4 + offset); mTris.push_back(5 + offset); mTris.push_back(7 + offset);
mTris.push_back(4 + offset); mTris.push_back(7 + offset); mTris.push_back(6 + offset);
// right
mTris.push_back(0 + offset); mTris.push_back(1 + offset); mTris.push_back(4 + offset);
mTris.push_back(5 + offset); mTris.push_back(4 + offset); mTris.push_back(1 + offset);
// left
mTris.push_back(6 + offset); mTris.push_back(7 + offset); mTris.push_back(2 + offset);
mTris.push_back(3 + offset); mTris.push_back(2 + offset); mTris.push_back(7 + offset);
// front
mTris.push_back(5 + offset); mTris.push_back(1 + offset); mTris.push_back(7 + offset);
mTris.push_back(3 + offset); mTris.push_back(7 + offset); mTris.push_back(1 + offset);
// back
mTris.push_back(4 + offset); mTris.push_back(6 + offset); mTris.push_back(0 + offset);
mTris.push_back(2 + offset); mTris.push_back(0 + offset); mTris.push_back(6 + offset);
}

View File

@ -0,0 +1,220 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#include "PxPhysicsAPI.h"
#include "extensions/PxExtensionsAPI.h"
#include "characterkinematic/PxControllerManager.h"
#include "characterkinematic/PxCapsuleController.h"
#include "SampleNorthPole.h"
#include "SampleNorthPoleCameraController.h"
#include "SampleNorthPoleInputEventIds.h"
#include <SamplePlatform.h>
#include <SampleUserInput.h>
#include <SampleUserInputIds.h>
#include <SampleUserInputDefines.h>
using namespace SampleRenderer;
using namespace SampleFramework;
void SampleNorthPole::tryStandup()
{
PxSceneWriteLock scopedLock(*mScene);
// overlap with upper part
PxReal r = mController->getRadius();
PxReal dh = mStandingSize-mCrouchingSize-2*r;
PxCapsuleGeometry geom(r, dh*.5f);
PxExtendedVec3 position = mController->getPosition();
PxVec3 pos((float)position.x,(float)position.y+mStandingSize*.5f+r,(float)position.z);
PxQuat orientation(PxHalfPi, PxVec3(0.0f, 0.0f, 1.0f));
PxOverlapBuffer hit;
if(getActiveScene().overlap(geom, PxTransform(pos,orientation),hit,
PxQueryFilterData(PxQueryFlag::eANY_HIT|PxQueryFlag::eSTATIC|PxQueryFlag::eDYNAMIC)))
return;
// if no hit, we can stand up
resizeController(mStandingSize);
mDoStandup = false;
}
void SampleNorthPole::resizeController(PxReal height)
{
PxSceneWriteLock scopedLock(*mScene);
mController->resize(height);
}
PxCapsuleController* SampleNorthPole::createCharacter(const PxExtendedVec3& position)
{
PxCapsuleControllerDesc cDesc;
cDesc.material = &getDefaultMaterial();
cDesc.position = position;
cDesc.height = mStandingSize;
cDesc.radius = mControllerRadius;
cDesc.slopeLimit = 0.0f;
cDesc.contactOffset = 0.1f;
cDesc.stepOffset = 0.02f;
cDesc.reportCallback = this;
cDesc.behaviorCallback = this;
mControllerInitialPosition = cDesc.position;
PxCapsuleController* ctrl = static_cast<PxCapsuleController*>(mControllerManager->createController(cDesc));
// remove controller shape from scene query for standup overlap test
PxRigidDynamic* actor = ctrl->getActor();
if(actor)
{
if(actor->getNbShapes())
{
PxShape* ctrlShape;
actor->getShapes(&ctrlShape,1);
ctrlShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE,false);
}
else
fatalError("character actor has no shape");
}
else
fatalError("character could not create actor");
// uncomment the next line to render the character
//createRenderObjectsFromActor(ctrl->getActor());
return ctrl;
}
void SampleNorthPole::onShapeHit(const PxControllerShapeHit& hit)
{
PxRigidDynamic* actor = hit.shape->getActor()->is<PxRigidDynamic>();
if(actor)
{
// We only allow horizontal pushes. Vertical pushes when we stand on dynamic objects creates
// useless stress on the solver. It would be possible to enable/disable vertical pushes on
// particular objects, if the gameplay requires it.
if(hit.dir.y==0.0f)
{
PxReal coeff = actor->getMass() * hit.length;
PxRigidBodyExt::addForceAtLocalPos(*actor,hit.dir*coeff, PxVec3(0,0,0), PxForceMode::eIMPULSE);
}
}
}
void SampleNorthPole::resetScene()
{
PxSceneWriteLock scopedLock(*mScene);
mController->setPosition(mControllerInitialPosition);
mNorthPoleCamera->setView(0,0);
while(mPhysicsActors.size())
{
PxRigidActor* actor = mPhysicsActors.back();
removeActor(actor);
}
createSnowMen();
buildHeightField();
for(unsigned int b = 0; b < NUM_BALLS; b++)
{
PxRigidDynamic* ball = mSnowBalls[b];
if(ball)
{
removeActor(ball);
ball->release();
mSnowBalls[b] = 0;
// render actor is released inside of removeActor()
mSnowBallsRenderActors[b] = 0;
}
}
}
void SampleNorthPole::collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents)
{
PhysXSample::collectInputEvents(inputEvents);
getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(SPAWN_DEBUG_OBJECT);
getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(CAMERA_MOVE_BUTTON);
//digital keyboard events
DIGITAL_INPUT_EVENT_DEF(CROUCH, SCAN_CODE_DOWN, SCAN_CODE_DOWN, SCAN_CODE_DOWN );
DIGITAL_INPUT_EVENT_DEF(RESET_SCENE, WKEY_R, OSXKEY_R, LINUXKEY_R );
//digital gamepad events
DIGITAL_INPUT_EVENT_DEF(CROUCH, GAMEPAD_WEST, GAMEPAD_WEST, LINUXKEY_UNKNOWN );
DIGITAL_INPUT_EVENT_DEF(RESET_SCENE, GAMEPAD_NORTH, GAMEPAD_NORTH, LINUXKEY_UNKNOWN );
DIGITAL_INPUT_EVENT_DEF(THROW_BALL, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, LINUXKEY_UNKNOWN );
//digital mouse events
if (!isPaused())
{
DIGITAL_INPUT_EVENT_DEF(THROW_BALL, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_LEFT );
}
}
void SampleNorthPole::onDigitalInputEvent(const SampleFramework::InputEvent& ie, bool val)
{
switch (ie.m_Id)
{
case CROUCH:
{
if(val)
{
resizeController(mCrouchingSize);
}
else
{
mDoStandup = true;
}
}
break;
case RESET_SCENE:
{
if(val)
{
resetScene();
}
}
break;
case THROW_BALL:
{
if(val)
{
throwBall();
}
}
break;
}
PhysXSample::onDigitalInputEvent(ie,val);
}

View File

@ -0,0 +1,221 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 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 "SampleNorthPole.h"
#include "SampleNorthPoleCameraController.h"
#include "PxRigidDynamic.h"
#include "geometry/PxCapsuleGeometry.h"
#include "PxShape.h"
#include "characterkinematic/PxCapsuleController.h"
#include <SampleBaseInputEventIds.h>
#include <SamplePlatform.h>
#include <SampleUserInput.h>
#include <SampleUserInputIds.h>
#include <SampleUserInputDefines.h>
using namespace SampleRenderer;
using namespace SampleFramework;
SampleNorthPoleCameraController::SampleNorthPoleCameraController(PxCapsuleController& controlled, SampleNorthPole& base) :
mCCT (controlled),
mBase (base),
mTargetYaw (0.0f-PxPi/2),
mTargetPitch (0.0f),
mPitchMin (-PxHalfPi*.99f),
mPitchMax (PxHalfPi*.99f),
mGamepadPitchInc (0.0f),
mGamepadYawInc (0.0f),
mGamepadForwardInc (0.0f),
mGamepadLateralInc (0.0f),
mSensibility (0.001f),
mFwd (false),
mBwd (false),
mLeft (false),
mRight (false),
mKeyShiftDown (false),
mRunningSpeed (10.0f),
mWalkingSpeed (2.5f),
mFilterMemory (0.0f)
{
mFilterMemory = float(computeCameraTarget().y);
}
void SampleNorthPoleCameraController::collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents)
{
//digital keyboard events
DIGITAL_INPUT_EVENT_DEF(CAMERA_MOVE_FORWARD, SCAN_CODE_FORWARD, SCAN_CODE_FORWARD, SCAN_CODE_FORWARD );
DIGITAL_INPUT_EVENT_DEF(CAMERA_MOVE_BACKWARD, SCAN_CODE_BACKWARD, SCAN_CODE_BACKWARD, SCAN_CODE_BACKWARD );
DIGITAL_INPUT_EVENT_DEF(CAMERA_MOVE_LEFT, SCAN_CODE_LEFT, SCAN_CODE_LEFT, SCAN_CODE_LEFT );
DIGITAL_INPUT_EVENT_DEF(CAMERA_MOVE_RIGHT, SCAN_CODE_RIGHT, SCAN_CODE_RIGHT, SCAN_CODE_RIGHT );
DIGITAL_INPUT_EVENT_DEF(CAMERA_SHIFT_SPEED, SCAN_CODE_LEFT_SHIFT, OSXKEY_SHIFT, LINUXKEY_SHIFT );
//analog gamepad events
ANALOG_INPUT_EVENT_DEF(CAMERA_GAMEPAD_ROTATE_LEFT_RIGHT, GAMEPAD_ROTATE_SENSITIVITY, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, LINUXKEY_UNKNOWN );
ANALOG_INPUT_EVENT_DEF(CAMERA_GAMEPAD_ROTATE_UP_DOWN, GAMEPAD_ROTATE_SENSITIVITY, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, LINUXKEY_UNKNOWN );
ANALOG_INPUT_EVENT_DEF(CAMERA_GAMEPAD_MOVE_LEFT_RIGHT, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, LINUXKEY_UNKNOWN );
ANALOG_INPUT_EVENT_DEF(CAMERA_GAMEPAD_MOVE_FORWARD_BACK, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, LINUXKEY_UNKNOWN );
}
void SampleNorthPoleCameraController::onDigitalInputEvent(const SampleFramework::InputEvent& ie, bool val)
{
if(val)
{
if(ie.m_Id == CAMERA_MOVE_FORWARD) mFwd = true;
else if(ie.m_Id == CAMERA_MOVE_BACKWARD) mBwd = true;
else if(ie.m_Id == CAMERA_MOVE_LEFT) mLeft = true;
else if(ie.m_Id == CAMERA_MOVE_RIGHT) mRight = true;
else if(ie.m_Id == CAMERA_SHIFT_SPEED) mKeyShiftDown = true;
}
else
{
if(ie.m_Id == CAMERA_MOVE_FORWARD) mFwd = false;
else if(ie.m_Id == CAMERA_MOVE_BACKWARD) mBwd = false;
else if(ie.m_Id == CAMERA_MOVE_LEFT) mLeft = false;
else if(ie.m_Id == CAMERA_MOVE_RIGHT) mRight = false;
else if(ie.m_Id == CAMERA_SHIFT_SPEED) mKeyShiftDown = false;
}
}
static PX_FORCE_INLINE PxReal remapAxisValue(PxReal absolutePosition)
{
return absolutePosition * absolutePosition * absolutePosition * 5.0f;
}
void SampleNorthPoleCameraController::onAnalogInputEvent(const SampleFramework::InputEvent& ie, float val)
{
if(ie.m_Id == CAMERA_GAMEPAD_ROTATE_LEFT_RIGHT)
{
mGamepadYawInc = -remapAxisValue(val);
}
else if(ie.m_Id == CAMERA_GAMEPAD_ROTATE_UP_DOWN)
{
// PT: ideally we'd need an option to "invert Y axis" here
// mGamepadPitchInc = - remapAxisValue(val);
mGamepadPitchInc = remapAxisValue(val);
}
else if(ie.m_Id == CAMERA_GAMEPAD_MOVE_LEFT_RIGHT)
{
mGamepadLateralInc = val;
}
else if(ie.m_Id == CAMERA_GAMEPAD_MOVE_FORWARD_BACK)
{
mGamepadForwardInc = val;
}
}
void SampleNorthPoleCameraController::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)
{
mTargetYaw -= dx * mSensibility;
mTargetPitch += dy * mSensibility;
}
}
void SampleNorthPoleCameraController::setView(PxReal pitch, PxReal yaw)
{
mTargetPitch = pitch;
mTargetYaw = yaw;
}
PxExtendedVec3 SampleNorthPoleCameraController::computeCameraTarget()
{
PxRigidActor* characterActor = mCCT.getActor();
PxShape* shape;
characterActor->getShapes(&shape,1);
PxCapsuleGeometry geom;
shape->getCapsuleGeometry(geom);
const PxExtendedVec3 headPos = PxExtendedVec3(0,geom.halfHeight+geom.radius,0);
return mCCT.getPosition() + headPos;
}
static PX_INLINE float feedbackFilter(float val, float& memory, float sharpness)
{
if(sharpness<0.0f) sharpness = 0.0f;
else if(sharpness>1.0f) sharpness = 1.0f;
return memory = val * sharpness + memory * (1.0f - sharpness);
}
void SampleNorthPoleCameraController::update(Camera& camera, PxReal dtime)
{
PxSceneReadLock scopedLock(mBase.getActiveScene());
// Update CCT
if(!mBase.isPaused())
{
PxVec3 targetKeyDisplacement(0);
PxVec3 targetPadDisplacement(0);
PxVec3 forward = camera.getViewDir();
forward.y = 0;
forward.normalize();
PxVec3 up = PxVec3(0,1,0);
PxVec3 right = forward.cross(up);
if(mFwd) targetKeyDisplacement += forward;
if(mBwd) targetKeyDisplacement -= forward;
if(mRight) targetKeyDisplacement += right;
if(mLeft) targetKeyDisplacement -= right;
targetKeyDisplacement *= mKeyShiftDown ? mRunningSpeed : mWalkingSpeed;
targetKeyDisplacement += PxVec3(0,-9.81f,0);
targetKeyDisplacement *= dtime;
targetPadDisplacement += forward * mGamepadForwardInc * mRunningSpeed;
targetPadDisplacement += right * mGamepadLateralInc * mRunningSpeed;
targetPadDisplacement += PxVec3(0,-9.81f,0);
targetPadDisplacement *= dtime;
// PxU32 flags = mCCT.move(targetKeyDisplacement + targetPadDisplacement, 0.001f, dtime, PxControllerFilters(0));
PxU32 flags = mCCT.move(targetKeyDisplacement + targetPadDisplacement, 0.0f, dtime, PxControllerFilters(0));
PX_UNUSED(flags);
}
// Update camera
{
mTargetYaw += mGamepadYawInc * dtime;
mTargetPitch += mGamepadPitchInc * dtime;
// Clamp pitch
if(mTargetPitch<mPitchMin) mTargetPitch = mPitchMin;
if(mTargetPitch>mPitchMax) mTargetPitch = mPitchMax;
camera.setRot(PxVec3(-mTargetPitch,-mTargetYaw,0));
PxExtendedVec3 camTarget = computeCameraTarget();
const float filteredHeight = feedbackFilter((float)camTarget.y, mFilterMemory, dtime*6.0f);
camTarget.y = filteredHeight;
const PxF32 distanceToTarget = 0.0f;
const PxVec3 target = toVec3(camTarget) - camera.getViewDir()*distanceToTarget;
camera.setPos(target);
}
}

View File

@ -0,0 +1,69 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 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 "PhysXSample.h"
#include "SampleCameraController.h"
#include "characterkinematic/PxController.h"
class SampleNorthPoleCameraController : public CameraController
{
public:
SampleNorthPoleCameraController(PxCapsuleController& controlled, SampleNorthPole& base);
virtual void onDigitalInputEvent(const SampleFramework::InputEvent& , bool val);
virtual void onAnalogInputEvent(const SampleFramework::InputEvent& , float val);
virtual void onPointerInputEvent(const SampleFramework::InputEvent&, PxU32 x, PxU32 y, PxReal dx, PxReal dy, bool val);
virtual void collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents);
virtual void update(Camera& camera, PxReal dtime);
void setView(PxReal pitch, PxReal yaw);
private:
SampleNorthPoleCameraController& operator=(const SampleNorthPoleCameraController&);
PxExtendedVec3 computeCameraTarget();
PxCapsuleController& mCCT;
SampleNorthPole& mBase; // PT: TODO: find a way to decouple us from PhysXSampleApplication. Only needed for "recenterCursor". Maybe the app could inherit from the cam...
PxReal mTargetYaw, mTargetPitch;
PxReal mPitchMin, mPitchMax;
PxReal mGamepadPitchInc, mGamepadYawInc;
PxReal mGamepadForwardInc, mGamepadLateralInc;
PxReal mSensibility;
bool mFwd,mBwd,mLeft,mRight,mKeyShiftDown;
PxReal mRunningSpeed;
PxReal mWalkingSpeed;
PxF32 mFilterMemory;
};

View File

@ -0,0 +1,405 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxPhysicsAPI.h"
#include "extensions/PxExtensionsAPI.h"
#include "PxTkStream.h"
#include "SampleNorthPole.h"
#include "RenderBaseActor.h"
#ifdef _MSC_VER
#pragma warning(disable:4305)
#endif
using namespace PxToolkit;
//#define USE_RAYCAST_CCD_FOR_SNOWBALLS
void SampleNorthPole::detach()
{
std::vector<PxShape*>::const_iterator ite;
for(ite=mDetaching.begin(); ite<mDetaching.end(); ++ite)
{
PxSceneWriteLock scopedLock(*mScene);
PxShape* shape = *ite;
PxRigidActor* actor = shape->getActor();
PxMaterial* mat;
shape->getMaterials(&mat,1);
PxGeometryHolder geometry = shape->getGeometry();
PxTransform newActorPose = PxShapeExt::getGlobalPose(*shape, *actor);
PxRigidDynamic* newActor = PxCreateDynamic(*mPhysics, newActorPose, geometry.any(), *mat, 1);
if(!newActor)
fatalError("creating detached actor failed");
getActiveScene().addActor(*newActor);
mPhysicsActors.push_back(newActor);
// the only convex shape is the nose, so we can just test the type
if(geometry.getType() == PxGeometryType::eCONVEXMESH)
{
newActor->addForce(PxVec3(0,0.1f,0),PxForceMode::eFORCE);
size_t index = reinterpret_cast<size_t>(actor->userData);
mSnowman[index].changeMood();
}
// reuse the old shape's rendering actor
RenderBaseActor* render = getRenderActor(actor, shape);
PxShape* newShape;
newActor->getShapes(&newShape,1);
unlink(render, shape, actor);
link(render, newShape, newActor);
setCCDActive(*newShape, newActor);
actor->detachShape(*shape);
}
mDetaching.clear();
}
void SampleNorthPole::cookCarrotConvexMesh()
{
static const PxVec3 carrotVerts[] = {PxVec3(0,0,.3),PxVec3(.05,0,0),PxVec3(-.05,0,0),PxVec3(0,.05,0),PxVec3(0,-.05,0)};
mCarrotConvex = PxToolkit::createConvexMesh(getPhysics(), getCooking(), carrotVerts, 5, PxConvexFlag::eCOMPUTE_CONVEX);
if(!mCarrotConvex)
fatalError("creating the convex mesh failed");
}
PxRigidDynamic* SampleNorthPole::throwBall()
{
PxSceneWriteLock scopedLock(*mScene);
static unsigned int numBall = 0;
PxVec3 vel = getCamera().getViewDir() * 20.0f;
PxRigidDynamic* ballActor = getPhysics().createRigidDynamic(PxTransform(getCamera().getPos()+getCamera().getViewDir()));
if(!ballActor)
fatalError("creating ball actor failed");
ballActor->setLinearVelocity(vel);
PxShape* ballShape = PxRigidActorExt::createExclusiveShape(*ballActor, PxSphereGeometry(0.1f),getDefaultMaterial());
if(!ballShape)
fatalError("creating ball shape failed");
setSnowball(*ballShape);
PxRigidBodyExt::updateMassAndInertia(*ballActor,1);
#ifndef USE_RAYCAST_CCD_FOR_SNOWBALLS
setCCDActive(*ballShape, ballActor);
#endif
getActiveScene().addActor(*ballActor);
RenderBaseActor* actor = mSnowBallsRenderActors[numBall];;
if(actor)
{
link(actor, ballShape, ballActor);
}
else
{
actor = createRenderObjectFromShape(ballActor, ballShape, mSnowMaterial);
mSnowBallsRenderActors[numBall] = actor;
}
#ifdef USE_RAYCAST_CCD_FOR_SNOWBALLS
if(ballShape)
{
RenderBaseActor* renderActor = getRenderActor(ballActor, ballShape);
renderActor->setRaycastCCD(true);
}
#endif
PxRigidDynamic* oldBall = mSnowBalls[numBall];
if(oldBall)
{
removeActor(oldBall);
oldBall->release();
}
mSnowBalls[numBall] = ballActor;
if(! (++numBall < NUM_BALLS))
numBall=0;
return ballActor;
}
void SampleNorthPole::createSnowMen()
{
PxU32 numSnowmen = NUM_SNOWMEN; // can't have NUM_SNOWMEN in the loop since setting to 0 causes compiler warnings
for(PxU32 i=0; i<numSnowmen; i++)
{
PxVec3 pos(0,1,-8);
PxQuat rot(2*PxPi*i/numSnowmen,PxVec3(0,1,0));
createSnowMan(PxTransform(rot.rotate(pos),rot),i,i);
}
}
PxRigidDynamic* SampleNorthPole::createSnowMan(const PxTransform& pos, const PxU32 mode, const PxU32 index)
{
PxRigidDynamic* snowmanActor = getPhysics().createRigidDynamic(PxTransform(pos));
if(!snowmanActor)
fatalError("create snowman actor failed");
PxMaterial& material = getDefaultMaterial();
PxShape* armL = NULL; PxShape* armR = NULL;
switch(mode%5)
{
case 0: // with a weight at the bottom
{
PxShape* shape = NULL;
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.2),material);
if(!shape)
fatalError("creating snowman shape failed");
shape->setLocalPose(PxTransform(PxVec3(0,-.29,0)));
PxRigidBodyExt::updateMassAndInertia(*snowmanActor,10);
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.5),material);
if(!shape)
fatalError("creating snowman shape failed");
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.4),material);
if(!shape)
fatalError("creating snowman shape failed");
shape->setLocalPose(PxTransform(PxVec3(0,.6,0)));
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.3),material);
if(!shape)
fatalError("creating snowman shape failed");
shape->setLocalPose(PxTransform(PxVec3(0,1.1,0)));
armL = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxCapsuleGeometry(.1,.1),material);
if(!armL)
fatalError("creating snowman shape failed");
armL->setLocalPose(PxTransform(PxVec3(-.4,.7,0)));
armR = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxCapsuleGeometry(.1,.1),material);
if(!armR)
fatalError("creating snowman shape failed");
armR->setLocalPose(PxTransform(PxVec3( .4,.7,0)));
}
break;
case 1: // only considering lowest shape mass
{
PxShape* shape = NULL;
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.5),material);
if(!shape)
fatalError("creating snowman shape failed");
PxRigidBodyExt::updateMassAndInertia(*snowmanActor,1);
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.4),material);
if(!shape)
fatalError("creating snowman shape failed");
shape->setLocalPose(PxTransform(PxVec3(0,.6,0)));
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.3),material);
if(!shape)
fatalError("creating snowman shape failed");
shape->setLocalPose(PxTransform(PxVec3(0,1.1,0)));
armL = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxCapsuleGeometry(.1,.1),material);
if(!armL)
fatalError("creating snowman shape failed");
armL->setLocalPose(PxTransform(PxVec3(-.4,.7,0)));
armR = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxCapsuleGeometry(.1,.1),material);
if(!armR)
fatalError("creating snowman shape failed");
armR->setLocalPose(PxTransform(PxVec3( .4,.7,0)));
snowmanActor->setCMassLocalPose(PxTransform(PxVec3(0,-.5,0)));
}
break;
case 2: // considering whole mass
{
PxShape* shape = NULL;
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.5),material);
if(!shape)
fatalError("creating snowman shape failed");
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.4),material);
if(!shape)
fatalError("creating snowman shape failed");
shape->setLocalPose(PxTransform(PxVec3(0,.6,0)));
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.3),material);
if(!shape)
fatalError("creating snowman shape failed");
shape->setLocalPose(PxTransform(PxVec3(0,1.1,0)));
armL = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxCapsuleGeometry(.1,.1),material);
if(!armL)
fatalError("creating snowman shape failed");
armL->setLocalPose(PxTransform(PxVec3(-.4,.7,0)));
armR = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxCapsuleGeometry(.1,.1),material);
if(!armR)
fatalError("creating snowman shape failed");
armR->setLocalPose(PxTransform(PxVec3( .4,.7,0)));
PxRigidBodyExt::updateMassAndInertia(*snowmanActor,1);
snowmanActor->setCMassLocalPose(PxTransform(PxVec3(0,-.5,0)));
}
break;
case 3: // considering whole mass with low COM
{
PxShape* shape = NULL;
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.5),material);
if(!shape)
fatalError("creating snowman shape failed");
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.4),material);
if(!shape)
fatalError("creating snowman shape failed");
shape->setLocalPose(PxTransform(PxVec3(0,.6,0)));
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.3),material);
if(!shape)
fatalError("creating snowman shape failed");
shape->setLocalPose(PxTransform(PxVec3(0,1.1,0)));
armL = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxCapsuleGeometry(.1,.1),material);
if(!armL)
fatalError("creating snowman shape failed");
armL->setLocalPose(PxTransform(PxVec3(-.4,.7,0)));
armR = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxCapsuleGeometry(.1,.1),material);
if(!armR)
fatalError("creating snowman shape failed");
armR->setLocalPose(PxTransform(PxVec3( .4,.7,0)));
const PxVec3 localPos = PxVec3(0,-.5,0);
PxRigidBodyExt::updateMassAndInertia(*snowmanActor,1,&localPos);
}
break;
case 4: // setting up mass properties manually
{
PxShape* shape = NULL;
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.5),material);
if(!shape)
fatalError("creating snowman shape failed");
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.4),material);
if(!shape)
fatalError("creating snowman shape failed");
shape->setLocalPose(PxTransform(PxVec3(0,.6,0)));
shape = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.3),material);
if(!shape)
fatalError("creating snowman shape failed");
shape->setLocalPose(PxTransform(PxVec3(0,1.1,0)));
armL = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxCapsuleGeometry(.1,.1),material);
if(!armL)
fatalError("creating snowman shape failed");
armL->setLocalPose(PxTransform(PxVec3(-.4,.7,0)));
armR = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxCapsuleGeometry(.1,.1),material);
if(!armR)
fatalError("creating snowman shape failed");
armR->setLocalPose(PxTransform(PxVec3( .4,.7,0)));
snowmanActor->setMass(1);
snowmanActor->setCMassLocalPose(PxTransform(PxVec3(0,-.5,0)));
snowmanActor->setMassSpaceInertiaTensor(PxVec3(.05,100,100));
}
break;
default:
break;
}
setDetachable(*armL);
setDetachable(*armR);
createRenderObjectsFromActor(snowmanActor,mSnowMaterial);
PxShape* carrot = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxConvexMeshGeometry(mCarrotConvex),material);
if(!carrot)
fatalError("create snowman shape failed");
carrot->setLocalPose(PxTransform(PxVec3(0,1.1,.3)));
setDetachable(*carrot);
createRenderObjectFromShape(snowmanActor, carrot, mCarrotMaterial);
PxShape* button = NULL;
button = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxCapsuleGeometry(.02,.05),material);
if(!button)
fatalError("create snowman shape failed");
button->setLocalPose(PxTransform(PxVec3(.1,1.2,.3),PxQuat(PxHalfPi/3,PxVec3(0,0,1))));
button->setFlag(PxShapeFlag::eSIMULATION_SHAPE,false);
mSnowman[index].eyeL = button;
createRenderObjectFromShape(snowmanActor, button, mButtonMaterial);
button = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxCapsuleGeometry(.02,.05),material);
if(!button)
fatalError("create snowman shape failed");
button->setLocalPose(PxTransform(PxVec3(-.1,1.2,.3),PxQuat(-PxHalfPi/3,PxVec3(0,0,1))));
button->setFlag(PxShapeFlag::eSIMULATION_SHAPE,false);
mSnowman[index].eyeR = button;
createRenderObjectFromShape(snowmanActor, button, mButtonMaterial);
button = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.05),material);
if(!button)
fatalError("create snowman shape failed");
button->setLocalPose(PxTransform(PxVec3(0,.8,.35)));
setDetachable(*button);
createRenderObjectFromShape(snowmanActor, button, mButtonMaterial);
button = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.05),material);
if(!button)
fatalError("create snowman shape failed");
button->setLocalPose(PxTransform(PxVec3(0,.6,.4)));
setDetachable(*button);
createRenderObjectFromShape(snowmanActor, button, mButtonMaterial);
button = PxRigidActorExt::createExclusiveShape(*snowmanActor, PxSphereGeometry(.05),material);
if(!button)
fatalError("create snowman shape failed");
button->setLocalPose(PxTransform(PxVec3(0,.4,.35)));
setDetachable(*button);
createRenderObjectFromShape(snowmanActor, button, mButtonMaterial);
getActiveScene().addActor(*snowmanActor);
snowmanActor->userData = (void*)size_t(index);
mPhysicsActors.push_back(snowmanActor);
return snowmanActor;
}

View File

@ -0,0 +1,127 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxPhysicsAPI.h"
#include "SampleNorthPole.h"
void SampleNorthPole::customizeSceneDesc(PxSceneDesc& sceneDesc)
{
sceneDesc.gravity = PxVec3(0,-9.81f,0);
sceneDesc.filterShader = filter;
sceneDesc.simulationEventCallback = this;
sceneDesc.flags |= PxSceneFlag::eENABLE_CCD;
sceneDesc.flags |= PxSceneFlag::eREQUIRE_RW_LOCK;
}
void SampleNorthPole::setSnowball(PxShape& shape)
{
PxFilterData fd = shape.getSimulationFilterData();
fd.word3 |= SNOWBALL_FLAG;
shape.setSimulationFilterData(fd);
}
bool SampleNorthPole::needsContactReport(const PxFilterData& filterData0, const PxFilterData& filterData1)
{
const PxU32 needsReport = PxU32(DETACHABLE_FLAG | SNOWBALL_FLAG);
PxU32 flags = (filterData0.word3 | filterData1.word3);
return (flags & needsReport) == needsReport;
}
void SampleNorthPole::setDetachable(PxShape& shape)
{
PxFilterData fd = shape.getSimulationFilterData();
fd.word3 |= PxU32(DETACHABLE_FLAG);
shape.setSimulationFilterData(fd);
}
bool SampleNorthPole::isDetachable(PxFilterData& filterData)
{
return filterData.word3 & PxU32(DETACHABLE_FLAG) ? true : false;
}
void SampleNorthPole::setCCDActive(PxShape& shape, PxRigidBody* rigidBody)
{
rigidBody->setRigidBodyFlag(PxRigidBodyFlag::eENABLE_CCD, true);
PxFilterData fd = shape.getSimulationFilterData();
fd.word3 |= CCD_FLAG;
shape.setSimulationFilterData(fd);
}
bool SampleNorthPole::isCCDActive(PxFilterData& filterData)
{
return filterData.word3 & CCD_FLAG ? true : false;
}
PxFilterFlags SampleNorthPole::filter( PxFilterObjectAttributes attributes0,
PxFilterData filterData0,
PxFilterObjectAttributes attributes1,
PxFilterData filterData1,
PxPairFlags& pairFlags,
const void* constantBlock,
PxU32 constantBlockSize)
{
if (isCCDActive(filterData0) || isCCDActive(filterData1))
{
pairFlags |= PxPairFlag::eSOLVE_CONTACT;
pairFlags |= PxPairFlag::eDETECT_CCD_CONTACT;
}
if (needsContactReport(filterData0, filterData1))
{
pairFlags |= PxPairFlag::eNOTIFY_TOUCH_FOUND;
}
pairFlags |= PxPairFlag::eCONTACT_DEFAULT;
return PxFilterFlags();
}
void SampleNorthPole::onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs)
{
for(PxU32 i=0; i < nbPairs; i++)
{
PxU32 n = 2;
const PxContactPairFlag::Enum delShapeFlags[] = { PxContactPairFlag::eREMOVED_SHAPE_0, PxContactPairFlag::eREMOVED_SHAPE_1 };
const PxContactPair& cp = pairs[i];
while(n--)
{
if(!(cp.flags & delShapeFlags[n]))
{
PxShape* shape = cp.shapes[n];
PxFilterData fd = shape->getSimulationFilterData();
if(isDetachable(fd))
{
mDetaching.push_back(shape);
}
}
}
}
}

View File

@ -0,0 +1,46 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#ifndef _SAMPLE_NORTH_POLE_INPUT_EVENT_IDS_H
#define _SAMPLE_NORTH_POLE_INPUT_EVENT_IDS_H
#include <SampleBaseInputEventIds.h>
// InputEvents used by SampleNorthPole
enum SampleNorthPoleInputEventIds
{
SAMPLE_NORTH_POLE_FIRST = NUM_SAMPLE_BASE_INPUT_EVENT_IDS,
THROW_BALL ,
RAYCAST_HIT,
CROUCH ,
CROUCH_TOGGLE ,
RESET_SCENE ,
NUM_SAMPLE_NORTH_POLE_INPUT_EVENT_IDS,
};
#endif