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,683 @@
//
// 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 <stdio.h>
#include "AcclaimLoader.h"
#include "FrameworkFoundation.h"
#include "PsMathUtils.h"
#include "PxTkFile.h"
#include "SampleAllocatorSDKClasses.h"
#include "SampleArray.h"
#define MAX_FILE_BUFFER_SIZE 4096
#define MAX_TOKEN_LENGTH 512
///////////////////////////////////////////////////////////////////////////////
static inline bool isWhiteSpace(int c)
{
return ( c == ' ') || (c == '\t');
}
///////////////////////////////////////////////////////////////////////////////
static inline bool isWhiteSpaceAndNewline(int c)
{
return ( c == ' ') || (c == '\t') || (c == '\n') || (c == '\r') ;
}
///////////////////////////////////////////////////////////////////////////////
static inline bool isNumeric(int c)
{
return ('0' <= c) && (c <= '9');
}
///////////////////////////////////////////////////////////////////////////////
class SampleFileBuffer
{
SampleFramework::File* mFP;
char mBuffer[MAX_FILE_BUFFER_SIZE];
int mCurrentBufferSize;
int mCurrentCounter;
int mEOF;
public:
SampleFileBuffer(SampleFramework::File* fp) :
mFP(fp),
mCurrentBufferSize(0),
mCurrentCounter(0),
mEOF(0)
{}
///////////////////////////////////////////////////////////////////////////
inline void rewind(int offset = 1)
{
mCurrentCounter -= offset;
}
///////////////////////////////////////////////////////////////////////////
void readBuffer()
{
mCurrentBufferSize = (int)fread(mBuffer, 1, MAX_FILE_BUFFER_SIZE, mFP);
mEOF = feof(mFP);
mCurrentCounter = 0;
}
///////////////////////////////////////////////////////////////////////////
char getCharacter()
{
if (mCurrentCounter >= mCurrentBufferSize)
{
if (mEOF) return EOF;
readBuffer();
if (mCurrentBufferSize == 0)
return EOF;
}
return mBuffer[mCurrentCounter++];
}
///////////////////////////////////////////////////////////////////////////
bool skipWhiteSpace(bool stopAtEndOfLine)
{
char c = 0;
do
{
c = getCharacter();
bool skip = (stopAtEndOfLine) ? isWhiteSpace(c) : isWhiteSpaceAndNewline(c);
if (skip == false)
{
rewind();
return true;
}
} while (c != EOF);
return false; // end of file
}
///////////////////////////////////////////////////////////////////////////////
bool getNextToken(char* token, bool stopAtEndOfLine)
{
if (skipWhiteSpace(stopAtEndOfLine) == false)
return false;
char* str = token;
char c = 0;
do
{
c = getCharacter();
if (c == EOF)
{
*str = 0;
}
else if (isWhiteSpaceAndNewline(c) == true)
{
*str = 0;
rewind();
return (strlen(token) > 0);
}
else
*str++ = (char) c;
} while (c != EOF);
return false;
}
///////////////////////////////////////////////////////////////////////////////
bool getNextTokenButMarker(char* token)
{
if (skipWhiteSpace(false) == false)
return 0;
char* str = token;
char c = 0;
do
{
c = getCharacter();
if (c == ':')
{
rewind();
*str = 0;
return false;
}
if (c == EOF)
{
*str = 0;
}
else if (isWhiteSpaceAndNewline(c) == true)
{
*str = 0;
rewind();
return (strlen(token) > 0);
}
else
*str++ = (char) c;
} while (c != EOF);
return false;
}
///////////////////////////////////////////////////////////////////////////////
bool getNextTokenButNumeric(char* token)
{
if (skipWhiteSpace(false) == false)
return 0;
char* str = token;
char c = 0;
do
{
c = getCharacter();
if (isNumeric(c))
{
rewind();
*str = 0;
return false;
}
if (c == EOF)
{
*str = 0;
}
else if (isWhiteSpaceAndNewline(c) == true)
{
*str = 0;
rewind();
return (strlen(token) > 0);
}
else
*str++ = (char) c;
} while (c != EOF);
return false;
}
///////////////////////////////////////////////////////////////////////////////
void skipUntilNextLine()
{
char c = 0;
do
{
c = getCharacter();
} while ((c != '\n') && (c != EOF));
}
///////////////////////////////////////////////////////////////////////////////
void skipUntilNextBlock()
{
char dummy[MAX_TOKEN_LENGTH];
while (getNextTokenButMarker(dummy) == true)
;
}
///////////////////////////////////////////////////////////////////////////////
bool getNextFloat(float& val, bool stopAtEndOfLine = true)
{
char dummy[MAX_TOKEN_LENGTH];
if (getNextToken(dummy, stopAtEndOfLine) == false)
return false;
val = float(atof(dummy));
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool getNextInt(int& val, bool stopAtEndOfLine = true)
{
char dummy[MAX_TOKEN_LENGTH];
if (getNextToken(dummy, stopAtEndOfLine) == false)
return false;
val = int(atoi(dummy));
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool getNextString(char* val, bool stopAtEndOfLine = true)
{
char dummy[MAX_TOKEN_LENGTH];
if (getNextToken(dummy, stopAtEndOfLine) == false)
return false;
strcpy(val, dummy);
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool getNextVec3(PxVec3& val, bool stopAtEndOfLine = true)
{
if (getNextFloat(val.x, stopAtEndOfLine) == false)
return false;
if (getNextFloat(val.y, stopAtEndOfLine) == false)
return false;
if (getNextFloat(val.z, stopAtEndOfLine) == false)
return false;
return true;
}
};
///////////////////////////////////////////////////////////////////////////////
static bool readHeader(SampleFileBuffer& buffer, Acclaim::ASFData& data)
{
using namespace Acclaim;
char token[MAX_TOKEN_LENGTH], value[MAX_TOKEN_LENGTH];
while (buffer.getNextTokenButMarker(token) == true)
{
if (strcmp(token, "mass") == 0)
{
if (buffer.getNextFloat(data.mHeader.mMass) == false)
return false;
}
else if (strcmp(token, "length") == 0)
{
if (buffer.getNextFloat(data.mHeader.mLengthUnit) == false)
return false;
}
else if (strcmp(token, "angle") == 0)
{
if (buffer.getNextToken(value, true) == false)
return false;
data.mHeader.mAngleInDegree = (strcmp(value, "deg") == 0);
}
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
static bool readRoot(SampleFileBuffer& buffer, Acclaim::ASFData& data)
{
using namespace Acclaim;
char token[MAX_TOKEN_LENGTH];
while (buffer.getNextTokenButMarker(token) == true)
{
if (strcmp(token, "order") == 0)
buffer.skipUntilNextLine();
else if (strcmp(token, "axis") == 0)
buffer.skipUntilNextLine();
else if (strcmp(token, "position") == 0)
{
if (buffer.getNextVec3(data.mRoot.mPosition) == false)
return false;
}
else if (strcmp(token, "orientation") == 0)
{
if (buffer.getNextVec3(data.mRoot.mOrientation) == false)
return false;
}
else
{
buffer.skipUntilNextLine();
}
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
static bool readBone(SampleFileBuffer& buffer, Acclaim::Bone& bone)
{
using namespace Acclaim;
int nbDOF = 0;
char token[MAX_TOKEN_LENGTH], dummy[MAX_TOKEN_LENGTH];
if (buffer.getNextTokenButMarker(token) == false)
return false;
if (strcmp(token, "begin") != 0)
return false;
while (buffer.getNextToken(token, false) == true)
{
if (strcmp(token, "id") == 0)
{
if (buffer.getNextInt(bone.mID) == false) return false;
}
else if (strcmp(token, "name") == 0)
{
if (buffer.getNextString(bone.mName) == false) return false;
}
else if (strcmp(token, "direction") == 0)
{
if (buffer.getNextVec3(bone.mDirection) == false) return false;
}
else if (strcmp(token, "length") == 0)
{
if (buffer.getNextFloat(bone.mLength) == false) return false;
}
else if (strcmp(token, "axis") == 0)
{
if (buffer.getNextVec3(bone.mAxis) == false) return false;
buffer.getNextToken(dummy, true);
}
else if (strcmp(token, "dof") == 0)
{
while ((buffer.getNextToken(dummy, true) == true))
{
if (strcmp(dummy, "rx") == 0)
{
bone.mDOF |= BoneDOFFlag::eRX;
nbDOF++;
}
else if (strcmp(dummy, "ry") == 0)
{
bone.mDOF |= BoneDOFFlag::eRY;
nbDOF++;
}
else if (strcmp(dummy, "rz") == 0)
{
bone.mDOF |= BoneDOFFlag::eRZ;
nbDOF++;
}
else if (strcmp(dummy, "l") == 0)
{
bone.mDOF |= BoneDOFFlag::eLENGTH;
nbDOF++;
}
}
continue;
}
else if (strcmp(token, "limits") == 0)
{
int cnt = 0;
while ( cnt++ < nbDOF)
{
// we ignore limit data for now
if (buffer.getNextToken(dummy, false) == false) return false;
if (buffer.getNextToken(dummy, false) == false) return false;
}
}
else if (strcmp(token, "end") == 0)
break;
else
buffer.skipUntilNextLine();
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
static bool readBoneData(SampleFileBuffer& buffer, Acclaim::ASFData& data)
{
using namespace Acclaim;
Bone tempBones[MAX_BONE_NUMBER];
PxU32 nbBones = 0;
// read all the temporary bones onto temporary buffer
bool moreBone = false;
do {
moreBone = readBone(buffer, tempBones[nbBones]);
if (moreBone)
nbBones++;
PX_ASSERT(nbBones <= MAX_BONE_NUMBER);
} while (moreBone == true);
// allocate the right size and copy the bone data
data.mBones = (Bone*)malloc(sizeof(Bone) * nbBones);
data.mNbBones = nbBones;
for (PxU32 i = 0; i < nbBones; i++)
{
data.mBones[i] = tempBones[i];
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
static Acclaim::Bone* getBoneFromName(Acclaim::ASFData& data, const char* name)
{
// use a simple linear search -> probably we could use hash map if performance is an issue
for (PxU32 i = 0; i < data.mNbBones; i++)
{
if (strcmp(name, data.mBones[i].mName) == 0)
return &data.mBones[i];
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////
static bool readHierarchy(SampleFileBuffer& buffer, Acclaim::ASFData& data)
{
using namespace Acclaim;
char token[MAX_TOKEN_LENGTH];
char dummy[MAX_TOKEN_LENGTH];
while (buffer.getNextTokenButMarker(token) == true)
{
if (strcmp(token, "begin") == 0)
;
else if (strcmp(token, "end") == 0)
break;
else
{
Bone* parent = getBoneFromName(data, token);
while (buffer.getNextToken(dummy, true) == true)
{
Bone* child = getBoneFromName(data, dummy);
if (!child)
return false;
child->mParent = parent;
}
}
buffer.skipUntilNextLine();
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
static bool readFrameData(SampleFileBuffer& buffer, Acclaim::ASFData& asfData, Acclaim::FrameData& frameData)
{
using namespace Acclaim;
char token[MAX_TOKEN_LENGTH];
while (buffer.getNextTokenButNumeric(token) == true)
{
if (strcmp(token, "root") == 0)
{
buffer.getNextVec3(frameData.mRootPosition);
buffer.getNextVec3(frameData.mRootOrientation);
}
else
{
Bone* bone = getBoneFromName(asfData, token);
if (bone == 0)
return false;
int id = bone->mID - 1;
float val = 0;
if (bone->mDOF & BoneDOFFlag::eRX)
{
buffer.getNextFloat(val);
frameData.mBoneFrameData[id].x = val;
}
if (bone->mDOF & BoneDOFFlag::eRY)
{
buffer.getNextFloat(val);
frameData.mBoneFrameData[id].y = val;
}
if (bone->mDOF & BoneDOFFlag::eRZ)
{
buffer.getNextFloat(val);
frameData.mBoneFrameData[id].z = val;
}
}
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool Acclaim::readASFData(const char* filename, Acclaim::ASFData& data)
{
using namespace Acclaim;
char token[MAX_TOKEN_LENGTH];
SampleFramework::File* fp = NULL;
PxToolkit::fopen_s(&fp, filename, "r");
if (!fp)
return false;
SampleFileBuffer buffer(fp);
while (buffer.getNextToken(token, false) == true)
{
if (token[0] == '#') // comment
{
buffer.skipUntilNextLine();
continue;
}
else if (token[0] == ':') // blocks
{
const char* str = token + 1; // remainder of the string
if (strcmp(str, "version") == 0) // ignore version number
buffer.skipUntilNextLine();
else if (strcmp(str, "name") == 0) // probably 'VICON'
buffer.skipUntilNextLine();
else if (strcmp(str, "units") == 0)
{
if ( readHeader(buffer, data) == false)
return false;
}
else if (strcmp(str, "documentation") == 0)
buffer.skipUntilNextBlock();
else if (strcmp(str, "root") == 0)
{
if (readRoot(buffer, data) == false)
return false;
}
else if (strcmp(str, "bonedata") == 0)
{
if (readBoneData(buffer, data) == false)
return false;
}
else if (strcmp(str, "hierarchy") == 0)
{
if (readHierarchy(buffer, data) == false)
return false;
}
else
{
// ERROR! - unrecognized block name
}
}
else
{
// ERRROR!
continue;
}
}
fclose(fp);
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool Acclaim::readAMCData(const char* filename, Acclaim::ASFData& asfData, Acclaim::AMCData& amcData)
{
using namespace Acclaim;
char token[MAX_TOKEN_LENGTH];
SampleArray<FrameData> tempFrameData;
tempFrameData.reserve(300);
SampleFramework::File* fp = NULL;
PxToolkit::fopen_s(&fp, filename, "r");
if (!fp)
return false;
SampleFileBuffer buffer(fp);
while (buffer.getNextToken(token, false) == true)
{
if (token[0] == '#') // comment
{
buffer.skipUntilNextLine();
continue;
}
else if (token[0] == ':') // blocks
{
const char* str = token + 1; // remainder of the string
if (strcmp(str, "FULLY-SPECIFIED") == 0)
continue;
else if (strcmp(str, "DEGREES") == 0)
continue;
}
else if (isNumeric(token[0]) == true)
{
// frame number
//int frameNo = atoi(token);
FrameData frameData;
if (readFrameData(buffer, asfData, frameData) == true)
tempFrameData.pushBack(frameData);
}
}
amcData.mNbFrames = tempFrameData.size();
amcData.mFrameData = (FrameData*)malloc(sizeof(FrameData) * amcData.mNbFrames);
memcpy(amcData.mFrameData, tempFrameData.begin(), sizeof(FrameData) * amcData.mNbFrames);
fclose(fp);
return true;
}

View File

@ -0,0 +1,132 @@
//
// 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 ACCLAIM_LOADER
#define ACCLAIM_LOADER
#include "foundation/PxFlags.h"
#include "foundation/PxTransform.h"
#include "SampleAllocator.h"
#include "SampleArray.h"
namespace Acclaim
{
#define MAX_BONE_NAME_CHARACTER_LENGTH 100
#define MAX_BONE_NUMBER 32
///////////////////////////////////////////////////////////////////////////////
struct BoneDOFFlag
{
enum Enum
{
eRX = (1<<0),
eRY = (1<<1),
eRZ = (1<<2),
eLENGTH = (1<<3)
};
};
typedef PxFlags<BoneDOFFlag::Enum,PxU16> BoneDOFFlags;
PX_FLAGS_OPERATORS(BoneDOFFlag::Enum, PxU16)
///////////////////////////////////////////////////////////////////////////////
struct Bone
{
int mID;
char mName[MAX_BONE_NAME_CHARACTER_LENGTH];
PxVec3 mDirection;
PxReal mLength;
PxVec3 mAxis;
BoneDOFFlags mDOF;
Bone* mParent;
public:
Bone() :
mID(-1),
mDirection(0.0f),
mLength(0.0f),
mAxis(0.0f, 0.0f, 1.0f),
mDOF(0),
mParent(NULL)
{
}
};
///////////////////////////////////////////////////////////////////////////////
struct ASFData
{
struct Header
{
PxReal mMass;
PxReal mLengthUnit;
bool mAngleInDegree;
};
struct Root
{
PxVec3 mPosition;
PxVec3 mOrientation;
};
Header mHeader;
Root mRoot;
Bone* mBones;
PxU32 mNbBones;
public:
void release() { if (mBones) free(mBones); }
};
///////////////////////////////////////////////////////////////////////////////
struct FrameData
{
PxVec3 mRootPosition;
PxVec3 mRootOrientation;
PxVec3 mBoneFrameData[MAX_BONE_NUMBER];
PxU32 mNbBones;
};
///////////////////////////////////////////////////////////////////////////////
struct AMCData
{
FrameData* mFrameData;
PxU32 mNbFrames;
public:
void release() { if (mFrameData) free(mFrameData); }
};
///////////////////////////////////////////////////////////////////////////////
bool readASFData(const char* filename, ASFData& data);
bool readAMCData(const char* filename, ASFData& asfData, AMCData& amcData);
}
#endif // ACCLAIM_LOADER

View File

@ -0,0 +1,49 @@
//
// 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.
// PT: dummy file to test each header can be included on his own without anything else
// DON'T REMOVE.
//#include "SampleErrorStream.h"
//#include "RenderBaseActor.h"
//#include "RenderBoxActor.h"
//#include "RenderSphereActor.h"
//#include "RenderCapsuleActor.h"
//#include "RenderMeshActor.h"
//#include "RenderGridActor.h"
//#include "RenderMaterial.h"
//#include "RawLoader.h"
//#include "RenderPhysX3Debug.h"
//#include "SampleBase.h"
//#include "SampleBridges.h"
//#include "SampleMain.h"
//#include "SampleMouseFilter.h"
//#include "SampleUtils.h"
//#include "SampleCamera.h"
//#include "SampleCameraController.h"
#include "SampleStepper.h"

View File

@ -0,0 +1,162 @@
//
// 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 "InputEventBuffer.h"
#include "PhysXSampleApplication.h"
using namespace physx;
using namespace SampleRenderer;
using namespace SampleFramework;
using namespace PxToolkit;
InputEventBuffer::InputEventBuffer(PhysXSampleApplication& p)
: mResetInputCacheReq(0)
, mResetInputCacheAck(0)
, mLastKeyDownEx(NULL)
, mLastDigitalInput(NULL)
, mLastAnalogInput(NULL)
, mLastPointerInput(NULL)
, mApp(p)
, mClearBuffer(false)
{
}
InputEventBuffer::~InputEventBuffer()
{
}
void InputEventBuffer::onKeyDownEx(SampleFramework::SampleUserInput::KeyCode keyCode, PxU32 wParam)
{
checkResetLastInput();
if(mLastKeyDownEx && mLastKeyDownEx->isEqual(keyCode, wParam))
return;
if(mRingBuffer.isFull())
return;
KeyDownEx& event = mRingBuffer.front().get<KeyDownEx>();
PX_PLACEMENT_NEW(&event, KeyDownEx);
event.keyCode = keyCode;
event.wParam = wParam;
mLastKeyDownEx = &event;
mRingBuffer.incFront(1);
}
void InputEventBuffer::onAnalogInputEvent(const SampleFramework::InputEvent& e, float val)
{
checkResetLastInput();
if(mLastAnalogInput && mLastAnalogInput->isEqual(e, val))
return;
if(mRingBuffer.isFull() || (mRingBuffer.size() > MAX_ANALOG_EVENTS))
return;
AnalogInput& event = mRingBuffer.front().get<AnalogInput>();
PX_PLACEMENT_NEW(&event, AnalogInput);
event.e = e;
event.val = val;
mLastAnalogInput = &event;
mRingBuffer.incFront(1);
}
void InputEventBuffer::onDigitalInputEvent(const SampleFramework::InputEvent& e, bool val)
{
checkResetLastInput();
if(mLastDigitalInput && mLastDigitalInput->isEqual(e, val))
return;
if(mRingBuffer.isFull())
return;
DigitalInput& event = mRingBuffer.front().get<DigitalInput>();
PX_PLACEMENT_NEW(&event, DigitalInput);
event.e = e;
event.val = val;
mLastDigitalInput = &event;
mRingBuffer.incFront(1);
}
void InputEventBuffer::onPointerInputEvent(const SampleFramework::InputEvent& e, PxU32 x, PxU32 y, PxReal dx, PxReal dy, bool val)
{
checkResetLastInput();
if(mLastPointerInput && mLastPointerInput->isEqual(e, x, y, dx, dy, val))
return;
if(mRingBuffer.isFull() || (mRingBuffer.size() > MAX_MOUSE_EVENTS))
return;
PointerInput& event = mRingBuffer.front().get<PointerInput>();
PX_PLACEMENT_NEW(&event, PointerInput);
event.e = e;
event.x = x;
event.y = y;
event.dx = dx;
event.dy = dy;
event.val = val;
mLastPointerInput = &event;
mRingBuffer.incFront(1);
}
void InputEventBuffer::clear()
{
mClearBuffer = true;
}
void InputEventBuffer::flush()
{
if(mResetInputCacheReq==mResetInputCacheAck)
mResetInputCacheReq++;
PxU32 size = mRingBuffer.size();
Ps::memoryBarrier();
// do not work on more than size, else input cache might become overwritten
while(size-- && !mClearBuffer)
{
mRingBuffer.back().get<EventType>().report(mApp);
mRingBuffer.incBack(1);
}
if(mClearBuffer)
{
mRingBuffer.clear();
mClearBuffer = false;
}
}
void InputEventBuffer::KeyDownEx::report(PhysXSampleApplication& app) const
{
app.onKeyDownEx(keyCode, wParam);
}
void InputEventBuffer::AnalogInput::report(PhysXSampleApplication& app) const
{
app.onAnalogInputEvent(e, val);
}
void InputEventBuffer::DigitalInput::report(PhysXSampleApplication& app) const
{
app.onDigitalInputEvent(e, val);
}
void InputEventBuffer::PointerInput::report(PhysXSampleApplication& app) const
{
app.onPointerInputEvent(e, x, y, dx, dy, val);
}

View File

@ -0,0 +1,228 @@
//
// 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 INPUT_BUFFER_H
#define INPUT_BUFFER_H
#include "SamplePreprocessor.h"
#include "SampleAllocator.h"
#include "SampleUserInput.h"
#include "foundation/PxAssert.h"
#include "PsIntrinsics.h"
class PhysXSampleApplication;
template<typename T, PxU32 SIZE>
class RingBuffer
{
public:
RingBuffer()
: mReadCount(0)
, mWriteCount(0)
{
// SIZE has to be power of two
#if PX_VC
PX_COMPILE_TIME_ASSERT(SIZE > 0);
PX_COMPILE_TIME_ASSERT((SIZE&(SIZE-1)) == 0);
#else
PX_ASSERT(SIZE > 0);
PX_ASSERT((SIZE&(SIZE-1)) == 0);
#endif
}
PX_FORCE_INLINE bool isEmpty() const { return mReadCount==mWriteCount; }
PX_FORCE_INLINE bool isFull() const { return isFull(mReadCount, mWriteCount); }
PX_FORCE_INLINE PxU32 size() const { return size(mReadCount, mWriteCount); }
PX_FORCE_INLINE PxU32 capacity() const { return SIZE; }
// clear is only save if called from reader thread!
PX_FORCE_INLINE void clear() { mReadCount=mWriteCount; }
PX_FORCE_INLINE const T& back() const { PX_ASSERT(!isEmpty()); return mRing[mReadCount&moduloMask]; }
PX_FORCE_INLINE T& front() { return mRing[mWriteCount&moduloMask]; }
PX_FORCE_INLINE void incFront(PxU32 inc) { PX_ASSERT(SIZE-size() >= inc); mWriteCount+=inc; }
PX_FORCE_INLINE void incBack(PxU32 inc) { PX_ASSERT(size() >= inc); mReadCount+=inc; }
PX_FORCE_INLINE bool pushFront(const T& e)
{
if(!isFull())
{
mRing[mWriteCount&moduloMask] = e;
Ps::memoryBarrier();
mWriteCount++;
return true;
}
else
return false;
}
PX_FORCE_INLINE bool popBack(T& e)
{
if(!isEmpty())
{
e = mRing[mReadCount&moduloMask];
mReadCount++;
return true;
}
else
return false;
}
private:
PX_FORCE_INLINE static PxU32 moduloDistance(PxI32 r, PxI32 w) { return PxU32((w-r)&moduloMask); }
PX_FORCE_INLINE static bool isFull(PxI32 r, PxI32 w) { return r!=w && moduloDistance(r,w)==0; }
PX_FORCE_INLINE static PxU32 size(PxI32 r, PxI32 w) { return isFull(r, w) ? SIZE : moduloDistance(r, w); }
private:
static const PxU32 moduloMask = SIZE-1;
T mRing[SIZE];
volatile PxI32 mReadCount;
volatile PxI32 mWriteCount;
};
class InputEventBuffer: public SampleFramework::InputEventListener, public SampleAllocateable
{
public:
InputEventBuffer(PhysXSampleApplication& p);
virtual ~InputEventBuffer();
virtual void onKeyDownEx(SampleFramework::SampleUserInput::KeyCode keyCode, PxU32 wParam);
virtual void onAnalogInputEvent(const SampleFramework::InputEvent& , float val);
virtual void onDigitalInputEvent(const SampleFramework::InputEvent& , bool val);
virtual void onPointerInputEvent(const SampleFramework::InputEvent&, PxU32 x, PxU32 y, PxReal dx, PxReal dy, bool val);
void clear();
void flush();
private:
PX_FORCE_INLINE void checkResetLastInput()
{
if(mResetInputCacheReq!=mResetInputCacheAck)
{
mLastKeyDownEx = NULL;
mLastDigitalInput = NULL;
mLastAnalogInput = NULL;
mLastPointerInput = NULL;
mResetInputCacheAck++;
PX_ASSERT(mResetInputCacheReq==mResetInputCacheAck);
}
}
struct EventType
{
virtual ~EventType() {}
virtual void report(PhysXSampleApplication& app) const { }
};
struct KeyDownEx: public EventType
{
virtual void report(PhysXSampleApplication& app) const;
bool isEqual(SampleFramework::SampleUserInput::KeyCode _keyCode, PxU32 _wParam)
{
return (_keyCode == keyCode) && (_wParam == wParam);
}
SampleFramework::SampleUserInput::KeyCode keyCode;
PxU32 wParam;
};
struct AnalogInput: public EventType
{
virtual void report(PhysXSampleApplication& app) const;
bool isEqual(SampleFramework::InputEvent _e, float _val)
{
return (_e.m_Id == e.m_Id) && (_e.m_Analog == e.m_Analog) && (_e.m_Sensitivity == e.m_Sensitivity) && (_val == val);
}
SampleFramework::InputEvent e;
float val;
};
struct DigitalInput: public EventType
{
virtual void report(PhysXSampleApplication& app) const;
bool isEqual(SampleFramework::InputEvent _e, bool _val)
{
return (_e.m_Id == e.m_Id) && (_e.m_Analog == e.m_Analog) && (_e.m_Sensitivity == e.m_Sensitivity) && (_val == val);
}
SampleFramework::InputEvent e;
bool val;
};
struct PointerInput: public EventType
{
virtual void report(PhysXSampleApplication& app) const;
bool isEqual(SampleFramework::InputEvent _e, PxU32 _x, PxU32 _y, PxReal _dx, PxReal _dy, bool _val)
{
return (_e.m_Id == e.m_Id) && (_e.m_Analog == e.m_Analog) && (_e.m_Sensitivity == e.m_Sensitivity) &&
(_x == x) && (_y == y) && (_dx == dx) && (_dy == dy) && (_val == val);
}
SampleFramework::InputEvent e;
PxU32 x;
PxU32 y;
PxReal dx;
PxReal dy;
bool val;
};
struct EventsUnion
{
template<class Event> PX_CUDA_CALLABLE PX_FORCE_INLINE Event& get()
{
return reinterpret_cast<Event&>(events);
}
template<class Event> PX_CUDA_CALLABLE PX_FORCE_INLINE const Event& get() const
{
return reinterpret_cast<const Event&>(events);
}
union
{
PxU8 eventType[sizeof(EventType)];
PxU8 keyDownEx[sizeof(KeyDownEx)];
PxU8 analogInput[sizeof(AnalogInput)];
PxU8 digitalInput[sizeof(DigitalInput)];
PxU8 pointerInput[sizeof(PointerInput)];
} events;
};
static const PxU32 MAX_EVENTS = 64;
static const PxU32 MAX_MOUSE_EVENTS = 48;
static const PxU32 MAX_ANALOG_EVENTS = 48;
RingBuffer<EventsUnion, MAX_EVENTS> mRingBuffer;
volatile PxU32 mResetInputCacheReq;
volatile PxU32 mResetInputCacheAck;
KeyDownEx* mLastKeyDownEx;
DigitalInput* mLastDigitalInput;
AnalogInput* mLastAnalogInput;
PointerInput* mLastPointerInput;
PhysXSampleApplication& mApp;
bool mClearBuffer;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,344 @@
//
// 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 PHYSX_SAMPLE_H
#define PHYSX_SAMPLE_H
#include "PhysXSampleApplication.h"
#include "SampleStepper.h"
#include "SampleDirManager.h"
#include "PxPhysicsAPI.h"
#include "extensions/PxExtensionsAPI.h"
namespace SampleFramework
{
class SampleInputAsset;
}
namespace physx
{
class Picking;
}
struct PhysXShape
{
PxRigidActor* mActor;
PxShape* mShape;
PhysXShape(PxRigidActor* actor, PxShape* shape) : mActor(actor), mShape(shape) {}
PhysXShape(const PhysXShape& shape) : mActor(shape.mActor), mShape(shape.mShape) {}
bool operator<(const PhysXShape& shape) const { return mActor == shape.mActor ? mShape < shape.mShape : mActor < shape.mActor; }
};
enum StepperType
{
DEFAULT_STEPPER,
FIXED_STEPPER,
VARIABLE_STEPPER
};
class PhysXSample : public RAWImportCallback
, public SampleAllocateable
, public PxDeletionListener
{
typedef std::map<PhysXShape, RenderBaseActor*> PhysXShapeToRenderActorMap;
public:
PhysXSample(PhysXSampleApplication& app, PxU32 maxSubSteps=8);
virtual ~PhysXSample();
public:
void render();
void displayFPS();
SampleFramework::SampleAsset* getAsset(const char* relativePath, SampleFramework::SampleAsset::Type type, bool abortOnError = true);
void importRAWFile(const char* relativePath, PxReal scale, bool recook=false);
void removeActor(PxRigidActor* actor);
void removeRenderObject(RenderBaseActor *renderAcotr);
void createRenderObjectsFromActor(PxRigidActor* actor, RenderMaterial* material=NULL);
RenderBaseActor* createRenderBoxFromShape(PxRigidActor* actor, PxShape* shape, RenderMaterial* material=NULL, const PxReal* uvs=NULL);
RenderBaseActor* createRenderObjectFromShape(PxRigidActor* actor, PxShape* shape, RenderMaterial* material=NULL);
RenderMeshActor* createRenderMeshFromRawMesh(const RAWMesh& data, PxShape* shape = NULL);
RenderTexture* createRenderTextureFromRawTexture(const RAWTexture& data);
RenderMaterial* createRenderMaterialFromTextureFile(const char* filename);
PxRigidActor* createGrid(RenderMaterial* material=NULL);
PxRigidDynamic* createBox(const PxVec3& pos, const PxVec3& dims, const PxVec3* linVel=NULL, RenderMaterial* material=NULL, PxReal density=1.0f);
PxRigidDynamic* createSphere(const PxVec3& pos, PxReal radius, const PxVec3* linVel=NULL, RenderMaterial* material=NULL, PxReal density=1.0f);
PxRigidDynamic* createCapsule(const PxVec3& pos, PxReal radius, PxReal halfHeight, const PxVec3* linVel=NULL, RenderMaterial* material=NULL, PxReal density=1.0f);
PxRigidDynamic* createConvex(const PxVec3& pos, const PxVec3* linVel=NULL, RenderMaterial* material=NULL, PxReal density=1.0f);
PxRigidDynamic* createCompound(const PxVec3& pos, const std::vector<PxTransform>& localPoses, const std::vector<const PxGeometry*>& geometries, const PxVec3* linVel=NULL, RenderMaterial* material=NULL, PxReal density=1.0f);
PxRigidDynamic* createTestCompound(const PxVec3& pos, PxU32 nbBoxes, float boxSize, float amplitude, const PxVec3* linVel, RenderMaterial* material, PxReal density, bool makeSureVolumeEmpty = false);
void createRenderObjectsFromScene();
void setSubStepper(const PxReal stepSize, const PxU32 maxSteps) { getStepper()->setSubStepper(stepSize, maxSteps); }
void togglePause();
void toggleFlyCamera();
void initRenderObjects();
// project from world coords to screen coords (can be used for text rendering)
void project(const PxVec3& v, int& x, int& y, float& depth);
public:
virtual void onInit();
virtual void onInit(bool restart) { onInit(); }
virtual void onShutdown();
// called after simulate() has completed
virtual void onSubstep(float dtime) {}
// called after simulate() has completed, but before fetchResult() is called
virtual void onSubstepPreFetchResult() {}
// called before simulate() is called
virtual void onSubstepSetup(float dtime, PxBaseTask* cont) {}
// called after simulate() has started
virtual void onSubstepStart(float dtime) {}
virtual void onTickPreRender(float dtime);
virtual void customizeRender() {}
virtual void helpRender(PxU32 x, PxU32 y, PxU8 textAlpha) {}
virtual void descriptionRender(PxU32 x, PxU32 y, PxU8 textAlpha) {}
virtual void onTickPostRender(float dtime);
virtual void onAnalogInputEvent(const SampleFramework::InputEvent& , float val);
virtual void onDigitalInputEvent(const SampleFramework::InputEvent& , bool val);
virtual void onPointerInputEvent(const SampleFramework::InputEvent& ie, PxU32 x, PxU32 y, PxReal dx, PxReal dy, bool val);
virtual void onKeyDownEx(SampleFramework::SampleUserInput::KeyCode keyCode, PxU32 param);
virtual void onResize(PxU32 width, PxU32 height);
virtual void newMaterial(const RAWMaterial&);
virtual void newMesh(const RAWMesh&);
virtual void newShape(const RAWShape&);
virtual void newHelper(const RAWHelper&);
virtual void newTexture(const RAWTexture&);
void unregisterInputEvents();
void registerInputEvents(bool ignoreSaved = false);
virtual void collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents);
virtual SampleFramework::SampleDirManager& getSampleOutputDirManager();
// delete listener
virtual void onRelease(const PxBase* observed, void* userData, PxDeletionEventFlag::Enum deletionEvent);
protected:
// Let samples override this
virtual void getDefaultSceneDesc(PxSceneDesc&) {}
virtual void customizeSceneDesc(PxSceneDesc&) {}
virtual void customizeTolerances(PxTolerancesScale&) {}
virtual void renderScene() {}
// this lets samples customize the debug objects
enum DebugObjectType
{
DEBUG_OBJECT_BOX = (1 << 0),
DEBUG_OBJECT_SPHERE = (1 << 1),
DEBUG_OBJECT_CAPSULE = (1 << 2),
DEBUG_OBJECT_CONVEX = (1 << 3),
DEBUG_OBJECT_COMPOUND = (1 << 4),
DEBUG_OBJECT_ALL = (DEBUG_OBJECT_BOX | DEBUG_OBJECT_SPHERE | DEBUG_OBJECT_CAPSULE | DEBUG_OBJECT_CONVEX | DEBUG_OBJECT_COMPOUND)
};
virtual PxU32 getDebugObjectTypes() const { return DEBUG_OBJECT_ALL; }
virtual PxReal getDebugObjectsVelocity() const { return 20.0f; }
virtual PxVec3 getDebugBoxObjectExtents() const { return PxVec3(0.3f, 0.3f, 1.0f); }
virtual PxReal getDebugSphereObjectRadius() const { return 0.3f; }
virtual PxReal getDebugCapsuleObjectRadius() const { return 0.3f; }
virtual PxReal getDebugCapsuleObjectHalfHeight() const { return 1.0f; }
virtual PxReal getDebugConvexObjectScale() const { return 0.3f; }
virtual void onDebugObjectCreation(PxRigidDynamic* actor){ }
Stepper* getStepper();
void prepareInputEventUserInputInfo(const char* sampleName,PxU32 &userInputCS, PxU32 &inputEventCS);
private:
///////////////////////////////////////////////////////////////////////////////
PhysXSample& operator= (const PhysXSample&);
public: // Helpers from PhysXSampleApplication
PX_FORCE_INLINE void fatalError(const char* msg) { mApplication.fatalError(msg); }
PX_FORCE_INLINE void setCameraController(CameraController* c) { mApplication.setCameraController(c); }
PX_FORCE_INLINE void toggleVisualizationParam(PxScene& scene, PxVisualizationParameter::Enum param)
{
PxSceneWriteLock scopedLock(scene);
const bool visualization = scene.getVisualizationParameter(param) == 1.0f;
scene.setVisualizationParameter(param, visualization ? 0.0f : 1.0f);
mApplication.refreshVisualizationMenuState(param);
}
public: // getter & setter
PX_FORCE_INLINE void setDefaultMaterial(PxMaterial* material) { mMaterial = material; }
PX_FORCE_INLINE void setFilename(const char* name) { mFilename = name; }
PX_FORCE_INLINE PhysXSampleApplication& getApplication() const { return mApplication; }
PX_FORCE_INLINE PxPhysics& getPhysics() const { return *mPhysics; }
PX_FORCE_INLINE PxCooking& getCooking() const { return *mCooking; }
PX_FORCE_INLINE PxScene& getActiveScene() const { return *mScene; }
PX_FORCE_INLINE PxMaterial& getDefaultMaterial() const { return *mMaterial; }
RenderMaterial* getMaterial(PxU32 materialID);
PX_FORCE_INLINE Camera& getCamera() const { return mApplication.getCamera(); }
PX_FORCE_INLINE SampleRenderer::Renderer* getRenderer() const { return mApplication.getRenderer(); }
PX_FORCE_INLINE RenderPhysX3Debug* getDebugRenderer() const { return mApplication.getDebugRenderer(); }
PX_FORCE_INLINE Console* getConsole() const { return mApplication.mConsole; }
PX_FORCE_INLINE CameraController* getCurrentCameraController() const { return mApplication.mCurrentCameraController; }
PX_FORCE_INLINE DefaultCameraController& getDefaultCameraController() const { return mCameraController; }
PX_FORCE_INLINE const PxMat44& getEyeTransform(void) const { return mApplication.m_worldToView.getInverseTransform();}
PX_FORCE_INLINE PxReal getSimulationTime() const { return mSimulationTime; }
PX_FORCE_INLINE PxReal getDebugRenderScale() const { return mDebugRenderScale; }
PX_FORCE_INLINE bool isPaused() const { return mApplication.isPaused(); }
PX_FORCE_INLINE bool isConnectedPvd() const { return mPvd ? mPvd->isConnected() : false; }
#if PX_SUPPORT_GPU_PHYSX
PX_FORCE_INLINE bool isGpuSupported() const { return mCudaContextManager && mCudaContextManager->contextIsValid(); }
#else
PX_FORCE_INLINE bool isGpuSupported() const { return false; }
#endif
PX_FORCE_INLINE void setMenuExpandState(bool menuExpand) { mApplication.mMenuExpand = menuExpand; }
PX_FORCE_INLINE void setEyeTransform(const PxVec3& pos, const PxVec3& rot) {mApplication.setEyeTransform(pos, rot); }
PX_FORCE_INLINE void resetExtendedHelpText() { mExtendedHelpPage = 0; }
PX_FORCE_INLINE void addPhysicsActors(PxRigidActor* actor) { mPhysicsActors.push_back(actor); }
void unlink(RenderBaseActor* renderActor, PxShape* shape, PxRigidActor* actor);
void link(RenderBaseActor* renderActor, PxShape* shape, PxRigidActor* actor);
RenderBaseActor* getRenderActor(PxRigidActor* actor, PxShape* shape);
const char* getSampleOutputFilePath(const char* inFilePath, const char* outExtension);
void showExtendedInputEventHelp(PxU32 x, PxU32 y);
void freeDeletedActors();
PX_FORCE_INLINE StepperType getStepperType() const { return mStepperType; }
protected:
void updateRenderObjectsFromRigidActor(PxRigidActor& actor, RenderMaterial* mat = NULL);
void updateRenderObjectsFromArticulation(PxArticulationBase& articulation);
protected:
void togglePvdConnection();
void createPvdConnection();
void bufferActiveTransforms();
void updateRenderObjectsDebug(float dtime); // update of render actors debug draw information, will be called while the simulation is NOT running
void updateRenderObjectsSync(float dtime); // update of render objects while the simulation is NOT running
void updateRenderObjectsAsync(float dtime); // update of render objects, potentially while the simulation is running (for rigid bodies etc. because data is double buffered)
void saveUserInputs();
void saveInputEvents(const std::vector<const SampleFramework::InputEvent*>& );
void parseSampleOutputAsset(const char* sampleName, PxU32 , PxU32 );
void spawnDebugObject();
void removeRenderActorsFromPhysicsActor(const PxRigidActor* actor);
protected: // configurations
bool mInitialDebugRender;
bool mCreateCudaCtxManager;
bool mCreateGroundPlane;
StepperType mStepperType;
PxU32 mMaxNumSubSteps;
PxU32 mNbThreads;
PxReal mDefaultDensity;
protected: // control
bool mDisplayFPS;
bool& mPause;
bool& mOneFrameUpdate;
bool& mShowHelp;
bool& mShowDescription;
bool& mShowExtendedHelp;
bool mHideGraphics;
bool mEnableAutoFlyCamera;
DefaultCameraController& mCameraController;
DefaultCameraController mFlyCameraController;
PhysXSampleApplication::PvdParameters& mPvdParams;
protected:
PhysXSampleApplication& mApplication;
PxFoundation* mFoundation;
PxPhysics* mPhysics;
PxCooking* mCooking;
PxScene* mScene;
PxMaterial* mMaterial;
PxDefaultCpuDispatcher* mCpuDispatcher;
physx::PxPvd* mPvd;
physx::PxPvdTransport* mTransport;
physx::PxPvdInstrumentationFlags mPvdFlags;
#if PX_SUPPORT_GPU_PHYSX
PxCudaContextManager* mCudaContextManager;
#endif
std::vector<PxRigidActor*> mPhysicsActors;
std::vector<RenderBaseActor*> mDeletedRenderActors;
std::vector<RenderBaseActor*> mRenderActors;
std::vector<RenderTexture*> mRenderTextures;
std::vector<SampleFramework::SampleAsset*> mManagedAssets;
std::vector<RenderMaterial*> mRenderMaterials;
RenderMaterial* (&mManagedMaterials)[MATERIAL_COUNT];
SampleFramework::SampleInputAsset* mSampleInputAsset;
PxActor** mBufferedActiveActors;
std::vector<PxActor*> mDeletedActors;
PxU32 mActiveTransformCount;
PxU32 mActiveTransformCapacity;
bool mIsFlyCamera;
PhysXShapeToRenderActorMap mPhysXShapeToRenderActorMap;
private:
PxU32 mMeshTag;
const char* mFilename;
PxReal mScale;
PxReal mDebugRenderScale;
protected:
bool mWaitForResults;
private:
PxToolkit::FPS mFPS;
CameraController* mSavedCameraController;
DebugStepper mDebugStepper;
FixedStepper mFixedStepper;
VariableStepper mVariableStepper;
bool mWireFrame;
PxReal mSimulationTime;
Picking* mPicking;
bool mPicked;
physx::PxU8 mExtendedHelpPage;
physx::PxU32 mDebugObjectType;
static const PxU32 SCRATCH_BLOCK_SIZE = 1024*128;
void* mScratchBlock;
};
PxToolkit::BasicRandom& getSampleRandom();
PxErrorCallback& getSampleErrorCallback();
#endif // PHYSX_SAMPLE_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,362 @@
//
// 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 PHYSX_SAMPLE_APPLICATION_H
#define PHYSX_SAMPLE_APPLICATION_H
#include "SamplePreprocessor.h"
#include "SampleApplication.h"
#include "SampleCamera.h"
#include "SampleCameraController.h"
#include "SampleAllocator.h"
#include "PxFiltering.h"
#include "RawLoader.h"
#include "RendererMeshContext.h"
#include "PxTkFPS.h"
#include "PxVisualizationParameter.h"
#include "PxTkRandom.h"
#include <PsThread.h>
#include <PsSync.h>
#include "PsHashMap.h"
#include "PsUtilities.h"
#include "SampleArray.h"
#if PX_WINDOWS
#include "task/PxTask.h"
#endif
#define SAMPLE_MEDIA_PATH "samples/media/"
#define SAMPLE_OUTPUT_PATH "samples/media/user/"
namespace physx
{
class PxDefaultCpuDispatcher;
class PxPhysics;
class PxCooking;
class PxScene;
class PxGeometry;
class PxMaterial;
class PxRigidActor;
};
class RenderPhysX3Debug;
class RenderBaseActor;
class RenderMaterial;
class RenderMeshActor;
class RenderTexture;
class Stepper;
class Console;
class PhysXSampleApplication;
class PhysXSample;
class InputEventBuffer;
namespace Test
{
class TestGroup;
}
class PhysXSampleCreator
{
public:
virtual ~PhysXSampleCreator() {}
virtual PhysXSample* operator()(PhysXSampleApplication& app) const = 0;
};
typedef PhysXSampleCreator *SampleCreator;
typedef PhysXSample* (*FunctionCreator)(PhysXSampleApplication& app);
// typedef PhysXSample* (*SampleCreator)(PhysXSampleApplication& app);
struct SampleSetup
{
SampleSetup() :
mName (NULL),
mWidth (0),
mHeight (0),
mFullscreen (false)
{
}
const char* mName;
PxU32 mWidth;
PxU32 mHeight;
bool mFullscreen;
};
// Default materials created by PhysXSampleApplication
enum MaterialIndex
{
MATERIAL_GREY,
MATERIAL_RED,
MATERIAL_GREEN,
MATERIAL_BLUE,
MATERIAL_YELLOW,
MATERIAL_FLAT,
MATERIAL_COUNT,
};
template <typename Container>
void releaseAll(Container& container)
{
for (PxU32 i = 0; i < container.size(); ++i)
container[i]->release();
container.clear();
}
class PhysXSampleApplication : public SampleFramework::SampleApplication, public SampleAllocateable, public Ps::ThreadT<Ps::RawAllocator>
{
public:
using SampleAllocateable::operator new;
using SampleAllocateable::operator delete;
private:
friend class PhysXSample;
struct PvdParameters
{
char ip[256];
PxU32 port;
PxU32 timeout;
bool useFullPvdConnection;
PvdParameters()
: port(5425)
, timeout(10)
, useFullPvdConnection(true)
{
Ps::strlcpy(ip, 256, "127.0.0.1");
}
};
struct MenuKey
{
enum Enum
{
NONE,
ESCAPE,
SELECT,
NAVI_UP,
NAVI_DOWN,
NAVI_LEFT,
NAVI_RIGHT
};
};
// menu events
struct MenuType
{
enum Enum
{
NONE,
HELP,
SETTINGS,
VISUALIZATIONS,
TESTS
};
};
struct MenuTogglableItem
{
MenuTogglableItem(PxU32 c, const char* n) : toggleCommand(c), toggleState(false), name(n) {}
PxU32 toggleCommand;
bool toggleState;
const char* name;
};
public:
PhysXSampleApplication(const SampleFramework::SampleCommandLine& cmdline);
virtual ~PhysXSampleApplication();
///////////////////////////////////////////////////////////////////////////////
// PsThread interface
virtual void execute();
///////////////////////////////////////////////////////////////////////////////
// Implements SampleApplication/RendererWindow
virtual void onInit();
virtual void onShutdown();
virtual float tweakElapsedTime(float dtime);
virtual void onTickPreRender(float dtime);
virtual void onRender();
virtual void onTickPostRender(float dtime);
void onKeyDownEx(SampleFramework::SampleUserInput::KeyCode keyCode, PxU32 wParam);
void onAnalogInputEvent(const SampleFramework::InputEvent& , float val);
void onDigitalInputEvent(const SampleFramework::InputEvent& , bool val);
void onPointerInputEvent(const SampleFramework::InputEvent&, PxU32 x, PxU32 y, PxReal dx, PxReal dy, bool val);
virtual void onResize(PxU32 width, PxU32 height);
void baseTickPreRender(float dtime);
void baseTickPostRender(float dtime);
void baseResize(PxU32 width, PxU32 height);
///////////////////////////////////////////////////////////////////////////////
void customizeSample(SampleSetup&);
// void onSubstep(float dtime);
///////////////////////////////////////////////////////////////////////////////
void applyDefaultVisualizationSettings();
void saveCameraState();
void restoreCameraState();
// Camera functions
PX_FORCE_INLINE void setDefaultCameraController() { mCurrentCameraController = &mCameraController; mCameraController = DefaultCameraController();}
PX_FORCE_INLINE void resetDefaultCameraController() { mCameraController = DefaultCameraController(); }
PX_FORCE_INLINE void setCameraController(CameraController* c) { mCurrentCameraController = c; }
PX_FORCE_INLINE PxReal getTextAlpha1() const { return mTextAlphaHelp; }
PX_FORCE_INLINE PxReal getTextAlpha2() const { return mTextAlphaDesc; }
PX_FORCE_INLINE bool isPaused() const { return mPause; }
PX_FORCE_INLINE Camera& getCamera() { return mCamera; }
PX_FORCE_INLINE RenderPhysX3Debug* getDebugRenderer() const { return mDebugRenderer; }
PX_FORCE_INLINE Ps::MutexT<Ps::RawAllocator>& getInputMutex() { return mInputMutex; }
bool isConsoleActive() const;
void showCursor(bool show);
void setMouseCursorHiding(bool hide);
void setMouseCursorRecentering(bool recenter);
void handleMouseVisualization();
void updateEngine();
void setPvdParams(const SampleFramework::SampleCommandLine& cmdLine);
PX_FORCE_INLINE void registerLight(SampleRenderer::RendererLight* light) { mLights.push_back(light); }
void collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents);
const char* inputInfoMsg(const char* firstPart,const char* secondPart, PxI32 inputEventId1, PxI32 inputEventId2);
const char* inputInfoMsg_Aor_BandC(const char* firstPart,const char* secondPart, PxI32 inputEventIdA, PxI32 inputEventIdB, PxI32 inputEventIdC);
const char* inputMoveInfoMsg(const char* firstPart,const char* secondPart, PxI32 inputEventId1, PxI32 inputEventId2,PxI32 inputEventId3,PxI32 inputEventId4);
void requestToClose() { mIsCloseRequested = true; }
bool isCloseRequested() { return mIsCloseRequested; }
private:
PxReal mTextAlphaHelp;
PxReal mTextAlphaDesc;
MenuType::Enum mMenuType;
std::vector<MenuTogglableItem> mMenuVisualizations;
size_t mMenuVisualizationsIndexSelected;
void setMenuVisualizations(MenuTogglableItem& togglableItem);
char m_Msg[512];
PxTransform mSavedView;
bool mIsCloseRequested;
protected:
Console* mConsole;
Camera mCamera;
DefaultCameraController mCameraController;
CameraController* mCurrentCameraController;
std::vector<SampleRenderer::RendererLight*> mLights;
RenderMaterial* mManagedMaterials[MATERIAL_COUNT];
RenderPhysX3Debug* mDebugRenderer;
bool mPause;
bool mOneFrameUpdate;
bool mSwitchSample;
bool mShowHelp;
bool mShowDescription;
bool mShowExtendedHelp;
volatile bool mHideMouseCursor;
InputEventBuffer* mInputEventBuffer;
Ps::MutexT<RawAllocator> mInputMutex;
bool mDrawScreenQuad;
SampleRenderer::RendererColor mScreenQuadTopColor;
SampleRenderer::RendererColor mScreenQuadBottomColor;
PvdParameters mPvdParams;
void updateCameraViewport(PxU32 w, PxU32 h);
bool initLogo();
private:
bool handleMenuKey(MenuKey::Enum menuKey);
void handleSettingMenuKey(MenuKey::Enum menuKey);
void refreshVisualizationMenuState(PxVisualizationParameter::Enum p);
void toggleDebugRenderer();
//-----------------------------------------------------------------------------
// PhysXSampleManager
//-----------------------------------------------------------------------------
public:
static bool registerSample(SampleCreator creator, const char* fullPath)
{
return addSample(getSampleTreeRoot(), creator, fullPath);
}
bool getNextSample();
void switchSample();
protected:
static Test::TestGroup* mSampleTreeRoot;
static Test::TestGroup& getSampleTreeRoot();
static bool addSample(Test::TestGroup& root, SampleCreator creator, const char* fullPath);
public:
bool mMenuExpand;
Test::TestGroup* mRunning;
Test::TestGroup* mSelected;
PhysXSample* mSample;
const char* mDefaultSamplePath;
};
const char* getSampleMediaFilename(const char* filename);
PxToolkit::BasicRandom& getSampleRandom();
PxErrorCallback& getSampleErrorCallback();
//=============================================================================
// macro REGISTER_SAMPLE
//-----------------------------------------------------------------------------
class SampleFunctionCreator : public PhysXSampleCreator
{
public:
SampleFunctionCreator(FunctionCreator func) : mFunc(func) {}
virtual PhysXSample* operator()(PhysXSampleApplication& app) const { return (*mFunc)(app); }
private:
FunctionCreator mFunc;
};
#define SAMPLE_CREATOR(className) create##className
#define SAMPLE_STARTER(className) className##Starter
#define SAMPLE_CREATOR_VAR(className) g##className##creator
#define REGISTER_SAMPLE(className, fullPath) \
static PhysXSample* SAMPLE_CREATOR(className)(PhysXSampleApplication& app) { \
return SAMPLE_NEW(className)(app); \
} \
static SampleFunctionCreator SAMPLE_CREATOR_VAR(className)(SAMPLE_CREATOR(className)); \
struct SAMPLE_STARTER(className) { \
SAMPLE_STARTER(className)() { \
PhysXSampleApplication::registerSample(&SAMPLE_CREATOR_VAR(className), fullPath); \
} \
} g##className##Starter;
///////////////////////////////////////////////////////////////////////////////
#endif

View File

@ -0,0 +1,289 @@
//
// 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 "PxScene.h"
#include "PxQueryReport.h"
#include "PxBatchQueryDesc.h"
#include "extensions/PxJoint.h"
#include "PxRigidDynamic.h"
#include "extensions/PxDistanceJoint.h"
#include "extensions/PxSphericalJoint.h"
#include "PxArticulationLink.h"
#include "PxShape.h"
#include "Picking.h"
#include "RendererMemoryMacros.h"
#if PX_UNIX_FAMILY
#include <stdio.h>
#endif
using namespace physx; // PT: please DO NOT indent the whole file
Picking::Picking(PhysXSample& frame) :
mSelectedActor (NULL),
mMouseJoint (NULL),
mMouseActor (NULL),
mMouseActorToDelete (NULL),
mDistanceToPicked (0.0f),
mMouseScreenX (0),
mMouseScreenY (0),
mFrame (frame)
{
}
Picking::~Picking() {}
bool Picking::isPicked() const
{
return mMouseJoint!=0;
}
void Picking::moveCursor(PxI32 x, PxI32 y)
{
mMouseScreenX = x;
mMouseScreenY = y;
}
/*void Picking::moveCursor(PxReal deltaDepth)
{
const PxReal range[2] = { 0.0f, 1.0f };
const PxReal r = (range[1] - range[0]);
const PxReal d = (mMouseDepth - range[0])/r;
const PxReal delta = deltaDepth*0.02f*(1.0f - d);
mMouseDepth = PxClamp(mMouseDepth + delta, range[0], range[1]);
}*/
void Picking::tick()
{
if(mMouseJoint)
moveActor(mMouseScreenX,mMouseScreenY);
// PT: delete mouse actor one frame later to avoid crashes
SAFE_RELEASE(mMouseActorToDelete);
}
void Picking::computeCameraRay(PxVec3& orig, PxVec3& dir, PxI32 x, PxI32 y) const
{
const PxVec3& camPos = mFrame.getCamera().getPos();
// compute picking ray
// const PxVec3 rayOrig = unProject(x, y, 0.0f); // PT: what the frell is that?
const PxVec3 rayOrig = camPos;
const PxVec3 rayDir = (unProject(x, y, 1.0f) - rayOrig).getNormalized();
orig = rayOrig;
dir = rayDir;
}
bool Picking::pick(int x, int y)
{
PxScene& scene = mFrame.getActiveScene();
PxVec3 rayOrig, rayDir;
computeCameraRay(rayOrig, rayDir, x, y);
// raycast rigid bodies in scene
PxRaycastHit hit; hit.shape = NULL;
PxRaycastBuffer hit1;
scene.raycast(rayOrig, rayDir, PX_MAX_F32, hit1, PxHitFlag::ePOSITION);
hit = hit1.block;
if(hit.shape)
{
const char* shapeName = hit.shape->getName();
if(shapeName)
shdfnd::printFormatted("Picked shape name: %s\n", shapeName);
PxRigidActor* actor = hit.actor;
PX_ASSERT(actor);
mSelectedActor = static_cast<PxRigidActor*>(actor->is<PxRigidDynamic>());
if(!mSelectedActor)
mSelectedActor = static_cast<PxRigidActor*>(actor->is<PxArticulationLink>());
//ML::this is very useful to debug some collision problem
PxTransform t = actor->getGlobalPose();
PX_UNUSED(t);
shdfnd::printFormatted("id = %i\n PxTransform transform(PxVec3(%f, %f, %f), PxQuat(%f, %f, %f, %f))\n", reinterpret_cast<size_t>(actor->userData), t.p.x, t.p.y, t.p.z, t.q.x, t.q.y, t.q.z, t.q.w);
}
else
mSelectedActor = 0;
if(mSelectedActor)
{
shdfnd::printFormatted("Actor '%s' picked! (userData: %p)\n", mSelectedActor->getName(), mSelectedActor->userData);
//if its a dynamic rigid body, joint it for dragging purposes:
grabActor(hit.position, rayOrig);
}
#ifdef VISUALIZE_PICKING_RAYS
Ray ray;
ray.origin = rayOrig;
ray.dir = rayDir;
mRays.push_back(ray);
#endif
return true;
}
//----------------------------------------------------------------------------//
PxActor* Picking::letGo()
{
// let go any picked actor
if(mMouseJoint)
{
mMouseJoint->release();
mMouseJoint = NULL;
// SAFE_RELEASE(mMouseActor); // PT: releasing immediately crashes
PX_ASSERT(!mMouseActorToDelete);
mMouseActorToDelete = mMouseActor; // PT: instead, we mark for deletion next frame
}
PxActor* returnedActor = mSelectedActor;
mSelectedActor = NULL;
return returnedActor;
}
//----------------------------------------------------------------------------//
void Picking::grabActor(const PxVec3& worldImpact, const PxVec3& rayOrigin)
{
if(!mSelectedActor
|| (mSelectedActor->getType() != PxActorType::eRIGID_DYNAMIC
&& mSelectedActor->getType() != PxActorType::eARTICULATION_LINK))
return;
PxScene& scene = mFrame.getActiveScene();
PxPhysics& physics = scene.getPhysics();
//create a shape less actor for the mouse
{
mMouseActor = physics.createRigidDynamic(PxTransform(worldImpact, PxQuat(PxIdentity)));
mMouseActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
mMouseActor->setMass(1.0f);
mMouseActor->setMassSpaceInertiaTensor(PxVec3(1.0f, 1.0f, 1.0f));
scene.addActor(*mMouseActor);
}
PxRigidActor* pickedActor = static_cast<PxRigidActor*>(mSelectedActor);
#if USE_D6_JOINT_FOR_MOUSE
mMouseJoint = PxD6JointCreate( physics,
mMouseActor,
PxTransform(PxIdentity),
pickedActor,
PxTransform(pickedActor->getGlobalPose().transformInv(worldImpact)));
mMouseJoint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
mMouseJoint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
mMouseJoint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
#elif USE_SPHERICAL_JOINT_FOR_MOUSE
mMouseJoint = PxSphericalJointCreate(physics,
mMouseActor,
PxTransform(PxIdentity),
pickedActor,
PxTransform(pickedActor->getGlobalPose().transformInv(worldImpact)));
#else
mMouseJoint = PxDistanceJointCreate(physics,
mMouseActor,
PxTransform(PxIdentity),
pickedActor,
PxTransform(pickedActor->getGlobalPose().transformInv(worldImpact)));
mMouseJoint->setMaxDistance(0.0f);
mMouseJoint->setMinDistance(0.0f);
mMouseJoint->setDistanceJointFlags(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED);
#endif
mDistanceToPicked = (worldImpact - rayOrigin).magnitude();
}
//----------------------------------------------------------------------------//
void Picking::moveActor(int x, int y)
{
if(!mMouseActor)
return;
PxVec3 rayOrig, rayDir;
computeCameraRay(rayOrig, rayDir, x, y);
const PxVec3 pos = rayOrig + mDistanceToPicked * rayDir;
mMouseActor->setKinematicTarget(PxTransform(pos, PxQuat(PxIdentity)));
}
//----------------------------------------------------------------------------//
PxVec3 Picking::unProject(int x, int y, float depth) const
{
SampleRenderer::Renderer* renderer = mFrame.getRenderer();
const SampleRenderer::RendererProjection& projection = mFrame.getCamera().getProjMatrix();
const PxTransform view = mFrame.getCamera().getViewMatrix().getInverse();
PxU32 windowWidth = 0;
PxU32 windowHeight = 0;
renderer->getWindowSize(windowWidth, windowHeight);
const PxF32 outX = (float)x / (float)windowWidth;
const PxF32 outY = (float)y / (float)windowHeight;
return SampleRenderer::unproject(projection, view, outX * 2 -1, outY * 2 -1, depth * 2 - 1);
}
//----------------------------------------------------------------------------//
void Picking::project(const physx::PxVec3& v, int& xi, int& yi, float& depth) const
{
SampleRenderer::Renderer* renderer = mFrame.getRenderer();
SampleRenderer::RendererProjection projection = mFrame.getCamera().getProjMatrix();
const PxTransform view = mFrame.getCamera().getViewMatrix().getInverse();
PxVec3 pos = SampleRenderer::project(projection, view, v);
///* Map x, y and z to range 0-1 */
pos.x = (pos.x + 1 ) * 0.5f;
pos.y = (pos.y + 1 ) * 0.5f;
pos.z = (pos.z + 1 ) * 0.5f;
PxU32 windowWidth = 0;
PxU32 windowHeight = 0;
renderer->getWindowSize(windowWidth, windowHeight);
/* Map x,y to viewport */
pos.x *= windowWidth;
pos.y *= windowHeight;
depth = (float)pos.z;
xi = (int)(pos.x + 0.5);
yi = (int)(pos.y + 0.5);
}

View File

@ -0,0 +1,121 @@
//
// 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 PICKING_H
#define PICKING_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec3.h"
#include "extensions/PxD6Joint.h"
#include "extensions/PxSphericalJoint.h"
#include "PhysXSample.h"
#include "RendererProjection.h"
#define USE_D6_JOINT_FOR_MOUSE 1 // PT: please keep it 0 for interactive tests where one needs to rotate objects
#define USE_SPHERICAL_JOINT_FOR_MOUSE 0
//#define VISUALIZE_PICKING_RAYS
namespace physx
{
class PxActor;
class PxDistanceJoint;
class PxRigidDynamic;
class PxScene;
class PxPhysics;
}
namespace physx {
struct PickingCommands
{
enum Enum
{
PICK_START, //Bound to mouse 1 down
PICK_STOP, //bound to mouse 1 up
SCREEN_MOTION_CURSOR, //See DefaultMovementStrategy
SCREEN_MOTION_CURSOR_DEPTH, //See DefaultMovementStrategy
};
};
class Picking
{
public:
Picking(PhysXSample& frame);
~Picking();
PX_FORCE_INLINE void lazyPick() { pick(mMouseScreenX, mMouseScreenY); }
bool isPicked() const;
bool pick(int x, int y);
void moveCursor(PxI32 x, PxI32 y);
// void moveCursor(PxReal deltaDepth);
void computeCameraRay(PxVec3& orig, PxVec3& dir, PxI32 x, PxI32 y) const;
// returns picked actor
PxActor* letGo();
void tick();
void project(const physx::PxVec3& v, int& xi, int& yi, float& depth) const;
#ifdef VISUALIZE_PICKING_RAYS
struct Ray
{
PxVec3 origin;
PxVec3 dir;
};
PX_FORCE_INLINE const std::vector<Ray>& getRays() const { return mRays; }
#endif
private:
void grabActor(const PxVec3& worldImpact, const PxVec3& rayOrigin);
void moveActor(int x, int y);
PxVec3 unProject( int x, int y, float depth) const;
PxActor* mSelectedActor;
#if USE_D6_JOINT_FOR_MOUSE
PxD6Joint* mMouseJoint; // was PxDistanceJoint, PxSphericalJoint, PxD6Joint
#elif USE_SPHERICAL_JOINT_FOR_MOUSE
PxSphericalJoint* mMouseJoint;
#else
PxDistanceJoint* mMouseJoint;
#endif
PxRigidDynamic* mMouseActor;
PxRigidDynamic* mMouseActorToDelete;
PxReal mDistanceToPicked;
int mMouseScreenX, mMouseScreenY;
PhysXSample& mFrame;
#ifdef VISUALIZE_PICKING_RAYS
std::vector<Ray> mRays;
#endif
};
}
#endif

View File

@ -0,0 +1,415 @@
//
// 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.
// PT: this file is a loader for "raw" binary files. It should NOT create SDK objects directly.
#include <stdio.h>
#include "foundation/PxPreprocessor.h"
#include "RawLoader.h"
#include "RendererColor.h"
#include "RendererMemoryMacros.h"
#include "SampleAllocatorSDKClasses.h"
#include "PxTkFile.h"
using namespace SampleRenderer;
RAWObject::RAWObject() : mName(NULL)
{
mTransform = PxTransform(PxIdentity);
}
RAWTexture::RAWTexture() :
mID (0xffffffff),
mWidth (0),
mHeight (0),
mHasAlpha (false),
mPixels (NULL)
{
}
RAWMesh::RAWMesh() :
mNbVerts (0),
mNbFaces (0),
mMaterialID (0xffffffff),
mVerts (NULL),
mVertexNormals (NULL),
mVertexColors (NULL),
mUVs (NULL),
mIndices (NULL)
{
}
RAWShape::RAWShape() :
mNbVerts (0),
mVerts (NULL)
{
}
RAWHelper::RAWHelper()
{
}
RAWMaterial::RAWMaterial() :
mID (0xffffffff),
mDiffuseID (0xffffffff),
mOpacity (1.0f),
mDoubleSided (false)
{
mAmbientColor = PxVec3(0);
mDiffuseColor = PxVec3(0);
mSpecularColor = PxVec3(0);
}
#if PX_INTEL_FAMILY
static const bool gFlip = false;
#elif PX_PPC
static const bool gFlip = true;
#elif PX_ARM_FAMILY
static const bool gFlip = false;
#else
#error Unknown platform!
#endif
PX_INLINE void Flip(PxU32& v)
{
PxU8* b = (PxU8*)&v;
PxU8 temp = b[0];
b[0] = b[3];
b[3] = temp;
temp = b[1];
b[1] = b[2];
b[2] = temp;
}
PX_INLINE void Flip(PxI32& v)
{
Flip((PxU32&)v);
}
PX_INLINE void Flip(PxF32& v)
{
Flip((PxU32&)v);
}
static PxU8 read8(File* fp)
{
PxU8 data;
size_t numRead = fread(&data, 1, 1, fp);
if(numRead != 1) { return 0; }
return data;
}
static PxU32 read32(File* fp)
{
PxU32 data;
size_t numRead = fread(&data, 1, 4, fp);
if(numRead != 4) { return 0; }
if(gFlip)
Flip(data);
return data;
}
static PxF32 readFloat(File* fp)
{
PxF32 data;
size_t numRead = fread(&data, 1, 4, fp);
if(numRead != 4) { return 0; }
if(gFlip)
Flip(data);
return data;
}
static PxTransform readTransform(File* fp, PxReal scale)
{
PxTransform tr;
tr.p.x = scale * readFloat(fp);
tr.p.y = scale * readFloat(fp);
tr.p.z = scale * readFloat(fp);
tr.q.x = readFloat(fp);
tr.q.y = readFloat(fp);
tr.q.z = readFloat(fp);
tr.q.w = readFloat(fp);
PX_ASSERT(tr.isValid());
return tr;
}
static void readVertexArray(File* fp, PxVec3* verts, PxU32 nbVerts)
{
const size_t size = 4*3*nbVerts;
size_t numRead = fread(verts, 1, size, fp);
if(numRead != size) { return; }
if(gFlip)
{
for(PxU32 j=0;j<nbVerts;j++)
{
Flip(verts[j].x);
Flip(verts[j].y);
Flip(verts[j].z);
}
}
}
static void readUVs(File* fp, PxReal* uvs, PxU32 nbVerts)
{
const size_t size = 4*2*nbVerts;
size_t numRead = fread(uvs, 1, size, fp);
if(numRead != size) { return; }
if(gFlip)
{
for(PxU32 j=0;j<nbVerts*2;j++)
Flip(uvs[j]);
}
}
static void readVertices(File* fp, PxVec3* verts, PxU32 nbVerts, PxReal scale)
{
readVertexArray(fp, verts, nbVerts);
for(PxU32 j=0;j<nbVerts;j++)
verts[j] *= scale;
}
static void readNormals(File* fp, PxVec3* verts, PxU32 nbVerts)
{
readVertexArray(fp, verts, nbVerts);
}
static void readVertexColors(File* fp, PxVec3* colors, PxU32 nbVerts)
{
readVertexArray(fp, colors, nbVerts);
}
static void readName(File* fp, char* objectName)
{
PxU32 offset=0;
char c;
do
{
size_t numRead = fread(&c, 1, 1, fp);
if(numRead != 1) { c = '\0';}
objectName[offset++] = c;
}while(c);
objectName[offset]=0;
}
bool loadRAWfile(const char* filename, RAWImportCallback& cb, PxReal scale)
{
File* fp = NULL;
PxToolkit::fopen_s(&fp, filename, "rb");
if(!fp)
return false;
// General info
const PxU32 tag = read32(fp);
const PxU32 generalVersion = read32(fp);
const PxU32 nbMaterials = read32(fp);
const PxU32 nbTextures = read32(fp);
const PxU32 nbMeshes = read32(fp);
const PxU32 nbShapes = read32(fp);
const PxU32 nbHelpers = read32(fp);
(void)tag;
(void)generalVersion;
char objectName[512];
// Textures
for(PxU32 i=0;i<nbTextures;i++)
{
RAWTexture data;
readName(fp, objectName);
data.mName = objectName;
data.mTransform = PxTransform(PxIdentity); // PT: texture transform not supported yet
data.mID = read32(fp);
RendererColorAlloc* pixels = NULL;
if(read8(fp))
{
data.mWidth = read32(fp);
data.mHeight = read32(fp);
data.mHasAlpha = read8(fp)!=0;
const PxU32 nbPixels = data.mWidth*data.mHeight;
pixels = SAMPLE_NEW(RendererColorAlloc)[nbPixels];
data.mPixels = pixels;
for(PxU32 i=0;i<nbPixels;i++)
{
pixels[i].r = read8(fp);
pixels[i].g = read8(fp);
pixels[i].b = read8(fp);
if(data.mHasAlpha)
pixels[i].a = read8(fp);
else
pixels[i].a = 0xff;
}
}
else
{
data.mWidth = 0;
data.mHeight = 0;
data.mHasAlpha = false;
data.mPixels = NULL;
}
cb.newTexture(data);
DELETEARRAY(pixels);
}
// Materials
for(PxU32 i=0;i<nbMaterials;i++)
{
RAWMaterial data;
data.mID = read32(fp);
data.mDiffuseID = read32(fp);
data.mOpacity = readFloat(fp);
data.mDoubleSided = read32(fp)!=0;
data.mAmbientColor.x = readFloat(fp);
data.mAmbientColor.y = readFloat(fp);
data.mAmbientColor.z = readFloat(fp);
data.mDiffuseColor.x = readFloat(fp);
data.mDiffuseColor.y = readFloat(fp);
data.mDiffuseColor.z = readFloat(fp);
data.mSpecularColor.x = readFloat(fp);
data.mSpecularColor.y = readFloat(fp);
data.mSpecularColor.z = readFloat(fp);
cb.newMaterial(data);
}
// Meshes
for(PxU32 i=0;i<nbMeshes;i++)
{
RAWMesh data;
readName(fp, objectName);
data.mName = objectName;
data.mTransform = readTransform(fp, scale);
//
data.mNbVerts = read32(fp);
data.mNbFaces = read32(fp);
const PxU32 hasVertexColors = read32(fp);
const PxU32 hasUVs = read32(fp);
data.mMaterialID = read32(fp);
PxVec3Alloc* tmpVerts = SAMPLE_NEW(PxVec3Alloc)[data.mNbVerts];
PxVec3Alloc* tmpNormals = SAMPLE_NEW(PxVec3Alloc)[data.mNbVerts];
PxVec3Alloc* tmpColors = NULL;
PxReal* tmpUVs = NULL;
data.mVerts = tmpVerts;
data.mVertexNormals = tmpNormals;
data.mVertexColors = NULL;
data.mUVs = NULL;
readVertices(fp, tmpVerts, data.mNbVerts, scale);
readNormals(fp, tmpNormals, data.mNbVerts);
if(hasVertexColors)
{
tmpColors = SAMPLE_NEW(PxVec3Alloc)[data.mNbVerts];
data.mVertexColors = tmpColors;
readVertexColors(fp, tmpColors, data.mNbVerts);
}
if(hasUVs)
{
tmpUVs = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal)*data.mNbVerts*2);
data.mUVs = tmpUVs;
readUVs(fp, tmpUVs, data.mNbVerts);
}
PxU32* tmpIndices = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*data.mNbFaces*3);
data.mIndices = tmpIndices;
const size_t size = 4*3*data.mNbFaces;
size_t numRead = fread(tmpIndices, 1, size, fp);
if(numRead != size)
{
SAMPLE_FREE(tmpIndices);
SAMPLE_FREE(tmpUVs);
DELETEARRAY(tmpColors);
DELETEARRAY(tmpNormals);
DELETEARRAY(tmpVerts);
return false;
}
if(gFlip)
{
for(PxU32 j=0;j<data.mNbFaces*3;j++)
{
Flip(tmpIndices[j]);
}
}
cb.newMesh(data);
SAMPLE_FREE(tmpIndices);
SAMPLE_FREE(tmpUVs);
DELETEARRAY(tmpColors);
DELETEARRAY(tmpNormals);
DELETEARRAY(tmpVerts);
}
// Shapes
for(PxU32 i=0;i<nbShapes;i++)
{
RAWShape data;
readName(fp, objectName);
data.mName = objectName;
data.mTransform = readTransform(fp, scale);
//
data.mNbVerts = read32(fp);
PxVec3Alloc* tmp = SAMPLE_NEW(PxVec3Alloc)[data.mNbVerts];
data.mVerts = tmp;
readVertices(fp, tmp, data.mNbVerts, scale);
cb.newShape(data);
DELETEARRAY(tmp);
}
// Helpers
for(PxU32 i=0;i<nbHelpers;i++)
{
RAWHelper data;
readName(fp, objectName);
data.mName = objectName;
data.mTransform = readTransform(fp, scale);
}
return true;
}

View File

@ -0,0 +1,120 @@
//
// 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 RAW_LOADER_H
#define RAW_LOADER_H
#include "SampleAllocator.h"
#include "foundation/PxTransform.h"
namespace SampleRenderer
{
class RendererColor;
}
class RAWObject : public SampleAllocateable
{
public:
RAWObject();
const char* mName;
PxTransform mTransform;
};
class RAWTexture : public RAWObject
{
public:
RAWTexture();
PxU32 mID;
PxU32 mWidth;
PxU32 mHeight;
bool mHasAlpha;
const SampleRenderer::RendererColor* mPixels;
};
class RAWMesh : public RAWObject
{
public:
RAWMesh();
PxU32 mNbVerts;
PxU32 mNbFaces;
PxU32 mMaterialID;
const PxVec3* mVerts;
const PxVec3* mVertexNormals;
const PxVec3* mVertexColors;
const PxReal* mUVs;
const PxU32* mIndices;
};
class RAWShape : public RAWObject
{
public:
RAWShape();
PxU32 mNbVerts;
const PxVec3* mVerts;
};
class RAWHelper : public RAWObject
{
public:
RAWHelper();
};
class RAWMaterial : public SampleAllocateable
{
public:
RAWMaterial();
PxU32 mID;
PxU32 mDiffuseID;
PxReal mOpacity;
PxVec3 mAmbientColor;
PxVec3 mDiffuseColor;
PxVec3 mSpecularColor;
bool mDoubleSided;
};
class RAWImportCallback
{
public:
virtual ~RAWImportCallback() {}
virtual void newMaterial(const RAWMaterial&) = 0;
virtual void newMesh(const RAWMesh&) = 0;
virtual void newShape(const RAWShape&) = 0;
virtual void newHelper(const RAWHelper&) = 0;
virtual void newTexture(const RAWTexture&) = 0;
};
bool loadRAWfile(const char* filename, RAWImportCallback& cb, PxReal scale);
#endif

View File

@ -0,0 +1,252 @@
//
// 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 "RaycastCCD.h"
#include "geometry/PxBoxGeometry.h"
#include "geometry/PxSphereGeometry.h"
#include "geometry/PxCapsuleGeometry.h"
#include "geometry/PxConvexMeshGeometry.h"
#include "geometry/PxConvexMesh.h"
#include "PxQueryReport.h"
#include "PxScene.h"
#include "PxRigidDynamic.h"
#include "extensions/PxShapeExt.h"
#include <stdio.h>
//#define RAYCAST_CCD_PRINT_DEBUG
PxVec3 getShapeCenter(PxRigidActor* actor, PxShape* shape, const PxVec3& localOffset)
{
PxVec3 offset = localOffset;
switch(shape->getGeometryType())
{
case PxGeometryType::eCONVEXMESH:
{
PxConvexMeshGeometry geometry;
bool status = shape->getConvexMeshGeometry(geometry);
PX_UNUSED(status);
PX_ASSERT(status);
PxReal mass;
PxMat33 localInertia;
PxVec3 localCenterOfMass;
geometry.convexMesh->getMassInformation(mass, localInertia, localCenterOfMass);
offset += localCenterOfMass;
}
break;
default:
break;
}
const PxTransform pose = PxShapeExt::getGlobalPose(*shape, *actor);
return pose.transform(offset);
}
static PxReal computeInternalRadius(PxRigidActor* actor, PxShape* shape, const PxVec3& dir, /*PxVec3& offset,*/ const PxVec3& centerOffset)
{
const PxBounds3 bounds = PxShapeExt::getWorldBounds(*shape, *actor);
const PxReal diagonal = (bounds.maximum - bounds.minimum).magnitude();
const PxReal offsetFromOrigin = diagonal * 2.0f;
PxTransform pose = PxShapeExt::getGlobalPose(*shape, *actor);
PxReal internalRadius = 0.0f;
const PxReal length = offsetFromOrigin*2.0f;
// PT: we do a switch here anyway since the code is not *exactly* the same all the time
{
switch(shape->getGeometryType())
{
case PxGeometryType::eBOX:
case PxGeometryType::eCAPSULE:
{
pose.p = PxVec3(0);
const PxVec3 virtualOrigin = pose.p + dir * offsetFromOrigin;
PxRaycastHit hit;
const PxHitFlags sceneQueryFlags = PxHitFlag::ePOSITION|PxHitFlag::eNORMAL;
PxU32 nbHits = PxGeometryQuery::raycast(virtualOrigin, -dir, shape->getGeometry().any(), pose, length, sceneQueryFlags, 1, &hit);
PX_UNUSED(nbHits);
PX_ASSERT(nbHits);
internalRadius = offsetFromOrigin - hit.distance;
// offset = PxVec3(0.0f);
}
break;
case PxGeometryType::eSPHERE:
{
PxSphereGeometry geometry;
bool status = shape->getSphereGeometry(geometry);
PX_UNUSED(status);
PX_ASSERT(status);
internalRadius = geometry.radius;
// offset = PxVec3(0.0f);
}
break;
case PxGeometryType::eCONVEXMESH:
{
/*PxVec3 saved = pose.p;
pose.p = PxVec3(0);
// pose.p = geometry.convexMesh->getCenterOfMass();
// const PxVec3 virtualOrigin = pose.p + dir * offsetFromOrigin;
// const PxVec3 localCenter = computeCenter(geometry.convexMesh);
// const PxVec3 localCenter = geometry.convexMesh->getCenterOfMass();
// const PxVec3 virtualOrigin = pose.rotate(localCenter) + dir * offsetFromOrigin;
const PxVec3 localCenter = pose.rotate(geometry.convexMesh->getCenterOfMass());
const PxVec3 virtualOrigin = localCenter + dir * offsetFromOrigin;
PxRaycastHit hit;
PxU32 nbHits = Gu::raycast_convexMesh(geometry, pose, virtualOrigin, -dir, length, 0xffffffff, 1, &hit);
PX_ASSERT(nbHits);
internalRadius = offsetFromOrigin - hit.distance;
pose.p = localCenter;
PxVec3 shapeCenter = getShapeCenter(shape);
offset = shapeCenter - saved;*/
PxVec3 shapeCenter = getShapeCenter(actor, shape, centerOffset);
shapeCenter -= pose.p;
pose.p = PxVec3(0);
const PxVec3 virtualOrigin = shapeCenter + dir * offsetFromOrigin;
PxRaycastHit hit;
const PxHitFlags sceneQueryFlags = PxHitFlag::ePOSITION|PxHitFlag::eNORMAL;
PxU32 nbHits = PxGeometryQuery::raycast(virtualOrigin, -dir, shape->getGeometry().any(), pose, length, sceneQueryFlags, 1, &hit);
PX_UNUSED(nbHits);
PX_ASSERT(nbHits);
internalRadius = offsetFromOrigin - hit.distance;
// offset = shapeCenter;
}
break;
default:
break;
}
}
return internalRadius;
}
static bool CCDRaycast(PxScene* scene, const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, PxRaycastHit& hit)
{
const PxHitFlags outputFlags = PxHitFlag::ePOSITION|PxHitFlag::eNORMAL;
PxQueryFilterData filterData;
filterData.flags = PxQueryFlag::eSTATIC;
PxQueryFilterCallback* filterCall = NULL;
PxRaycastBuffer buf1;
scene->raycast(origin, unitDir, distance, buf1, outputFlags, filterData, filterCall, NULL);
hit = buf1.block;
return buf1.hasBlock;
}
static PxRigidDynamic* canDoCCD(PxRigidActor& actor, PxShape* shape)
{
PxRigidDynamic* dyna = actor.is<PxRigidDynamic>();
if(!dyna)
return NULL; // PT: no need to do it for statics
const PxU32 nbShapes = dyna->getNbShapes();
if(nbShapes!=1)
return NULL; // PT: only works with simple actors for now
if(dyna->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)
return NULL; // PT: no need to do it for kinematics
return dyna;
}
bool doRaycastCCD(PxRigidActor* actor, PxShape* shape, PxTransform& newPose, PxVec3& newShapeCenter, const PxVec3& ccdWitness, const PxVec3& ccdWitnessOffset)
{
PxRigidDynamic* dyna = canDoCCD(*actor, shape);
if(!dyna)
return true;
bool updateCCDWitness = true;
const PxVec3 offset = newPose.p - newShapeCenter;
const PxVec3& origin = ccdWitness;
const PxVec3& dest = newShapeCenter;
PxVec3 dir = dest - origin;
const PxReal length = dir.magnitude();
if(length!=0.0f)
{
dir /= length;
// Compute internal radius
const PxReal internalRadius = computeInternalRadius(actor, shape, dir, ccdWitnessOffset);
// Compute distance to impact
PxRaycastHit hit;
if(internalRadius!=0.0f && CCDRaycast(actor->getScene(), origin, dir, length, hit))
{
#ifdef RAYCAST_CCD_PRINT_DEBUG
static int count=0;
shdfnd::printFormatted("CCD hit %d\n", count++);
#endif
updateCCDWitness = false;
const PxReal radiusLimit = internalRadius * 0.75f;
if(hit.distance>radiusLimit)
{
newShapeCenter = origin + dir * (hit.distance - radiusLimit);
#ifdef RAYCAST_CCD_PRINT_DEBUG
shdfnd::printFormatted(" Path0: %f | %f\n", hit.distance, radiusLimit);
#endif
}
else
{
newShapeCenter = origin;
#ifdef RAYCAST_CCD_PRINT_DEBUG
shdfnd::printFormatted(" Path1: %f\n", hit.distance);
#endif
}
{
newPose.p = offset + newShapeCenter;
const PxTransform shapeLocalPose = shape->getLocalPose();
const PxTransform inverseShapeLocalPose = shapeLocalPose.getInverse();
PxTransform newGlobalPose = newPose * inverseShapeLocalPose;
dyna->setGlobalPose(newGlobalPose);
}
}
}
return updateCCDWitness;
}

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.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef RAYCAST_CCD_H
#define RAYCAST_CCD_H
#include "common/PxPhysXCommonConfig.h"
using namespace physx;
namespace physx
{
class PxShape;
class PxRigidActor;
}
PxVec3 getShapeCenter(PxRigidActor* actor, PxShape* shape, const PxVec3& localOffset);
bool doRaycastCCD(PxRigidActor* actor, PxShape* shape, PxTransform& pose, PxVec3& newShapeCenter, const PxVec3& ccdWitness, const PxVec3& ccdWitnessOffset);
#endif

View File

@ -0,0 +1,279 @@
//
// 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 "SamplePreprocessor.h"
#include "RenderBaseActor.h"
#include "RenderMaterial.h"
#include "RendererShape.h"
#include "Renderer.h"
#include "RendererMemoryMacros.h"
#include "extensions/PxShapeExt.h"
#include "RaycastCCD.h"
#include "RenderPhysX3Debug.h"
#include "PxRigidDynamic.h"
#include "PxArticulationLink.h"
#include "geometry/PxSphereGeometry.h"
#include "geometry/PxBoxGeometry.h"
#include "RenderSphereActor.h"
#include "RenderCapsuleActor.h"
using namespace physx;
using namespace SampleRenderer;
static const bool gRaycastCCD = true;
RenderBaseActor::RenderBaseActor() :
mRendererShape (NULL),
mPhysicsShape (NULL),
mDynamicActor (NULL),
mArticulationLink (NULL),
mMaterial (NULL),
mEnableCCD (false),
mEnableRender (true),
mEnableDebugRender (true),
mEnableCameraCull (false)
{
mTransform = PxTransform(PxIdentity);
mWorldBounds = PxBounds3(PxVec3(0),PxVec3(0));
mCCDWitness = PxVec3(0);
mCCDWitnessOffset = PxVec3(0);
mPhysicsToGraphicsRot = PxQuat(PxIdentity);
updateScale();
}
RenderBaseActor::RenderBaseActor(const RenderBaseActor& src) : RenderBaseObject(src)
{
mEnableCCD = src.mEnableCCD;
mEnableRender = src.mEnableRender;
mEnableDebugRender = src.mEnableDebugRender;
mEnableCameraCull = src.mEnableCameraCull;
mTransform = src.getTransform();
mWorldBounds = PxBounds3(PxVec3(0.0f), PxVec3(0.0f));
mPhysicsShape = NULL; // PT: the physics shape is not cloned for now
mDynamicActor = NULL; // PT: the physics actor is not cloned for now
mArticulationLink = NULL; // PT: the articulation link is not cloned for now
mMaterial = src.getRenderMaterial();
mRendererShape = NULL;
setRenderShape(src.getRenderShape());
mPhysicsToGraphicsRot = src.mPhysicsToGraphicsRot;
mCCDWitness = src.mCCDWitness;
mCCDWitnessOffset = src.mCCDWitnessOffset;
mScaling = src.mScaling;
updateScale();
}
RenderBaseActor::~RenderBaseActor()
{
deleteRenderShape();
mMaterial = NULL; // PT: we don't own this
mPhysicsShape = NULL; // PT: we don't own this
mDynamicActor = NULL; // PT: we don't own this
}
void RenderBaseActor::update(float deltaTime)
{
// Setup render transform from physics transform, if physics object exists
if(mPhysicsShape)
{
if(!mArticulationLink && ( !mDynamicActor || mDynamicActor->isSleeping()))
return;
PxTransform newPose = PxShapeExt::getGlobalPose(*mPhysicsShape, *mPhysicsActor);
PxVec3 newShapeCenter = getShapeCenter(mPhysicsActor, mPhysicsShape, mCCDWitnessOffset);
bool updateCCDWitness = true;
if(gRaycastCCD && mEnableCCD)
updateCCDWitness = doRaycastCCD(mPhysicsActor, mPhysicsShape, newPose, newShapeCenter, mCCDWitness, mCCDWitnessOffset);
// Copy physics pose to graphics pose
setTransform(PxTransform(newPose.p, newPose.q * mPhysicsToGraphicsRot));
if(updateCCDWitness)
mCCDWitness = newShapeCenter;
setWorldBounds(PxShapeExt::getWorldBounds(*mPhysicsShape, *mPhysicsActor));
}
}
void RenderBaseActor::render(Renderer& renderer, RenderMaterial* material, bool wireFrame)
{
if(!mEnableRender)
return;
RenderMaterial* m = mMaterial ? mMaterial : material;
PX_ASSERT(m);
mRendererMeshContext.cullMode = m->mDoubleSided ? RendererMeshContext::NONE : RendererMeshContext::CLOCKWISE;
mRendererMeshContext.fillMode = wireFrame ? RendererMeshContext::LINE : RendererMeshContext::SOLID;
mRendererMeshContext.material = m->mRenderMaterial;
mRendererMeshContext.materialInstance = m->mRenderMaterialInstance;
mRendererMeshContext.mesh = mRendererShape->getMesh();
mRendererMeshContext.transform = &mScaledTransform;
renderer.queueMeshForRender(mRendererMeshContext);
}
PxBounds3 RenderBaseActor::getWorldBounds() const
{
return mWorldBounds;
}
void RenderBaseActor::setWorldBounds(const PxBounds3& bounds)
{
mWorldBounds = bounds;
}
void RenderBaseActor::updateScale()
{
if (!mScaling.isIdentity())
{
PxMat33 q = PxMat33(mTransform.q) * mScaling.toMat33();
mScaledTransform = PxMat44(q, mTransform.p);
mRendererMeshContext.negativeScale = mScaling.hasNegativeDeterminant();
}
else
{
mScaledTransform = PxMat44(mTransform);
}
}
void RenderBaseActor::setPhysicsShape(PxShape* shape, PxRigidActor* actor)
{
mPhysicsShape = shape;
mPhysicsActor = actor;
if(shape)
{
mCCDWitness = getShapeCenter(actor, shape, mCCDWitnessOffset);
const PxTransform newPose = PxShapeExt::getGlobalPose(*shape, *actor);
setTransform(PxTransform(newPose.p, newPose.q * mPhysicsToGraphicsRot));
PxRigidActor& ra = *actor;
mDynamicActor = ra.is<PxRigidDynamic>();
mArticulationLink = ra.is<PxArticulationLink>();
mWorldBounds = PxShapeExt::getWorldBounds(*mPhysicsShape, *mPhysicsActor);
}
else
{
mDynamicActor = NULL;
}
}
void RenderBaseActor::setRenderMaterial(RenderMaterial* material)
{
mMaterial = material;
}
void RenderBaseActor::setRenderShape(RendererShape* shape)
{
PX_ASSERT(!mRendererShape);
mRendererShape = shape;
if(shape)
{
// PT: we use the user-data as a ref-counter
size_t refCount = size_t(mRendererShape->m_userData);
refCount++;
mRendererShape->m_userData = (void*)refCount;
}
}
void RenderBaseActor::deleteRenderShape()
{
if(mRendererShape)
{
// PT: we use the user-data as a ref-counter
size_t refCount = size_t(mRendererShape->m_userData);
refCount--;
if(!refCount)
{
DELETESINGLE(mRendererShape);
}
else
{
mRendererShape->m_userData = (void*)refCount;
mRendererShape = NULL;
}
}
}
void RenderBaseActor::drawDebug(RenderPhysX3Debug* debug)
{
// return;
if(!mPhysicsShape)
return;
if(0 && mEnableCCD)
{
const PxBounds3 bounds = PxShapeExt::getWorldBounds(*mPhysicsShape, *mPhysicsActor);
const PxReal scale = (bounds.maximum - bounds.minimum).magnitude();
const PxTransform pose = PxShapeExt::getGlobalPose(*mPhysicsShape, *mPhysicsActor);
debug->addLine(pose.p, pose.p+PxVec3(scale, 0.0f, 0.0f), RendererColor(0, 255, 0));
debug->addLine(pose.p, pose.p+PxVec3(0.0f, scale, 0.0f), RendererColor(0, 255, 0));
debug->addLine(pose.p, pose.p+PxVec3(0.0f, 0.0f, scale), RendererColor(0, 255, 0));
const PxVec3 shapeCenter = getShapeCenter(mPhysicsActor, mPhysicsShape, mCCDWitnessOffset);
//shdfnd::printFormatted("Render: %f | %f | %f\n", shapeCenter.x, shapeCenter.y, shapeCenter.z);
debug->addLine(shapeCenter, shapeCenter+PxVec3(scale, 0.0f, 0.0f), RendererColor(255, 0, 0));
debug->addLine(shapeCenter, shapeCenter+PxVec3(0.0f, scale, 0.0f), RendererColor(255, 0, 0));
debug->addLine(shapeCenter, shapeCenter+PxVec3(0.0f, 0.0f, scale), RendererColor(255, 0, 0));
return;
}
/*
BasicRandom rnd(42);
const PxTransform globalShapePose = PxShapeExt::getGlobalPose(*mPhysicsShape);
const RendererColor colorPurple(255, 0, 255);
for(PxU32 i=0;i<50;i++)
{
PxVec3 dir;
rnd.unitRandomPt(dir);
PxVec3 localCenter;
const PxReal internalRadius = computeInternalRadius(mPhysicsShape, dir, localCenter, mCCDWitnessOffset);
const PxVec3 center = globalShapePose.transform(localCenter);
debug->addLine(center, center+dir*internalRadius, colorPurple);
}*/
}

View File

@ -0,0 +1,126 @@
//
// 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 RENDER_BASE_ACTOR_H
#define RENDER_BASE_ACTOR_H
#include "RendererMeshContext.h"
#include "common/PxPhysXCommonConfig.h"
#include "RenderBaseObject.h"
#include "geometry/PxMeshScale.h"
#include "foundation/PxBounds3.h"
namespace SampleRenderer
{
class RendererShape;
}
class RenderMaterial;
namespace physx
{
class PxShape;
class PxRigidActor;
class PxRigidDynamic;
class PxArticulationLink;
class PxMeshScale;
}
class RenderPhysX3Debug;
class RenderBaseActor : public RenderBaseObject
{
public:
RenderBaseActor();
RenderBaseActor(const RenderBaseActor&);
virtual ~RenderBaseActor();
virtual void update(float deltaTime);
virtual void render(SampleRenderer::Renderer& renderer, RenderMaterial* material=NULL, bool wireFrame = false);
virtual void drawDebug(RenderPhysX3Debug*);
PX_FORCE_INLINE void setTransform(const PxTransform& tr) { mTransform = tr; updateScale(); }
PX_FORCE_INLINE void setMeshScale(const PxMeshScale& scaling){ mScaling = scaling; updateScale(); }
void setPhysicsShape(PxShape* shape, PxRigidActor* actor);
void setRenderMaterial(RenderMaterial*);
PX_FORCE_INLINE const PxTransform& getTransform() const { return mTransform; }
PX_FORCE_INLINE PxShape* getPhysicsShape() const { return mPhysicsShape; }
PX_FORCE_INLINE PxRigidActor* getPhysicsActor() const { return mPhysicsActor; }
PX_FORCE_INLINE SampleRenderer::RendererShape* getRenderShape() { return mRendererShape; }
PX_FORCE_INLINE SampleRenderer::RendererShape* getRenderShape() const { return mRendererShape; }
PX_FORCE_INLINE RenderMaterial* getRenderMaterial() { return mMaterial; }
PX_FORCE_INLINE RenderMaterial* getRenderMaterial() const { return mMaterial; }
PxBounds3 getWorldBounds() const;
void setWorldBounds(const PxBounds3& bounds);
PX_FORCE_INLINE void setRaycastCCD(bool flag) { mEnableCCD = flag; }
PX_FORCE_INLINE void setCCDWitnessOffset(const PxVec3& offset) { mCCDWitnessOffset = offset; }
PX_FORCE_INLINE void setRendering(bool flag) { mEnableRender = flag; }
PX_FORCE_INLINE void setEnableDebugRender(bool flag) { mEnableDebugRender = flag; }
PX_FORCE_INLINE bool getEnableDebugRender() const { return mEnableDebugRender; }
PX_FORCE_INLINE void setEnableCameraCull(bool flag) { mEnableCameraCull = flag; }
PX_FORCE_INLINE bool getEnableCameraCull() const { return mEnableCameraCull; }
private:
SampleRenderer::RendererShape* mRendererShape;
PxMeshScale mScaling;
PxTransform mTransform;
PxBounds3 mWorldBounds;
protected:
SampleRenderer::RendererMeshContext mRendererMeshContext;
PxMat44 mScaledTransform;
PxQuat mPhysicsToGraphicsRot;
PxShape* mPhysicsShape;
PxRigidActor* mPhysicsActor;
PxRigidDynamic* mDynamicActor;
PxArticulationLink* mArticulationLink;
RenderMaterial* mMaterial;
PxVec3 mCCDWitness;
PxVec3 mCCDWitnessOffset;
bool mEnableCCD;
bool mEnableRender;
bool mEnableDebugRender;
bool mEnableCameraCull;
protected:
void setRenderShape(SampleRenderer::RendererShape*);
void deleteRenderShape();
private:
void updateScale();
};
#endif

View File

@ -0,0 +1,52 @@
//
// 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 "RenderBaseObject.h"
#include <string.h>
RenderBaseObject::RenderBaseObject()
: mActive(true)
, mUserData (NULL)
{
mName[0] = 0;
}
RenderBaseObject::RenderBaseObject(const RenderBaseObject& src)
{
strcpy(mName, src.mName);
}
RenderBaseObject::~RenderBaseObject()
{
}
void RenderBaseObject::release()
{
delete this;
}

View File

@ -0,0 +1,49 @@
//
// 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 RENDER_BASE_OBJECT_H
#define RENDER_BASE_OBJECT_H
#include "SampleAllocator.h"
class RenderBaseObject : public SampleAllocateable
{
public:
RenderBaseObject();
RenderBaseObject(const RenderBaseObject&);
virtual ~RenderBaseObject();
virtual void release();
bool mActive;
void* mUserData;
char mName[512];
};
#endif

View File

@ -0,0 +1,48 @@
//
// 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 "RenderBoxActor.h"
#include "RendererBoxShape.h"
using namespace physx;
using namespace SampleRenderer;
RenderBoxActor::RenderBoxActor(Renderer& renderer, const PxVec3& extents, const PxReal* uvs)
{
RendererShape* rs = new RendererBoxShape(renderer, extents, uvs);
setRenderShape(rs);
}
RenderBoxActor::RenderBoxActor(const RenderBoxActor& src) : RenderBaseActor(src)
{
}
RenderBoxActor::~RenderBoxActor()
{
}

View File

@ -0,0 +1,49 @@
//
// 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 RENDER_BOX_ACTOR_H
#define RENDER_BOX_ACTOR_H
#include "RenderBaseActor.h"
#include "foundation/PxVec3.h"
namespace SampleRenderer
{
class Renderer;
}
class RenderBoxActor : public RenderBaseActor
{
public:
RenderBoxActor(SampleRenderer::Renderer& renderer, const PxVec3& extents, const PxReal* uvs=NULL);
RenderBoxActor(const RenderBoxActor&);
virtual ~RenderBoxActor();
};
#endif

View File

@ -0,0 +1,58 @@
//
// 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 "RenderCapsuleActor.h"
#include "RendererCapsuleShape.h"
#include "extensions/PxShapeExt.h"
using namespace physx;
using namespace SampleRenderer;
RenderCapsuleActor::RenderCapsuleActor(Renderer& renderer, PxReal radius, PxReal halfHeight)
{
RendererShape* rs = new RendererCapsuleShape(renderer, halfHeight, radius);
setRenderShape(rs);
// PT: seems there's a mismatch between the renderer's and the SDK's idea of what a default capsule pose should be
mPhysicsToGraphicsRot = PxQuat(PxHalfPi, PxVec3(0.0f, 0.0f, 1.0f));
}
void RenderCapsuleActor::setDimensions(PxReal halfHeight, PxReal radius0, PxReal radius1)
{
RendererCapsuleShape* capsuleShape = static_cast<RendererCapsuleShape*>(getRenderShape());
capsuleShape->setDimensions(halfHeight, radius0, radius1);
}
RenderCapsuleActor::RenderCapsuleActor(const RenderCapsuleActor& src) : RenderBaseActor(src)
{
}
RenderCapsuleActor::~RenderCapsuleActor()
{
}

View File

@ -0,0 +1,53 @@
//
// 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 RENDER_CAPSULE_ACTOR_H
#define RENDER_CAPSULE_ACTOR_H
#include "RenderBaseActor.h"
#include "foundation/PxSimpleTypes.h"
namespace SampleRenderer
{
class Renderer;
}
class RenderCapsuleActor : public RenderBaseActor
{
public:
RenderCapsuleActor(SampleRenderer::Renderer& renderer, PxReal radius, PxReal halfHeight);
// resize this capsule
void setDimensions(PxReal halfHeight, PxReal radius0, PxReal radius1);
RenderCapsuleActor(const RenderCapsuleActor&);
virtual ~RenderCapsuleActor();
};
#endif

View File

@ -0,0 +1,50 @@
//
// 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 "RenderGridActor.h"
#include "RendererGridShape.h"
using namespace physx;
using namespace SampleRenderer;
RenderGridActor::RenderGridActor(Renderer& renderer, PxU32 size, PxReal cellSize, PxQuat v)
{
RendererShape* rs = new RendererGridShape(renderer, size, cellSize);
setRenderShape(rs);
mPhysicsToGraphicsRot = v;
}
RenderGridActor::~RenderGridActor()
{
}
void RenderGridActor::update(float deltaTime)
{
}

View File

@ -0,0 +1,49 @@
//
// 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 RENDER_GRID_ACTOR_H
#define RENDER_GRID_ACTOR_H
#include "RenderBaseActor.h"
namespace SampleRenderer
{
class Renderer;
}
class RenderGridActor : public RenderBaseActor
{
public:
RenderGridActor(SampleRenderer::Renderer& renderer, PxU32 size, PxReal cellSize, PxQuat v = PxQuat(PxIdentity));
virtual ~RenderGridActor();
virtual void update(float deltaTime);
};
#endif

View File

@ -0,0 +1,184 @@
//
// 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 "SamplePreprocessor.h"
#include "RenderMaterial.h"
#include "RenderTexture.h"
#include "RendererMaterialDesc.h"
#include "Renderer.h"
#include "RendererMaterial.h"
#include "RendererMaterialInstance.h"
#include "RendererMemoryMacros.h"
using namespace physx;
using namespace SampleRenderer;
const char* defaultMaterialLitVertexShader = "vertex/staticmesh.cg";
const char* defaultMaterialTexturedUnlitFragmentShader = "fragment/sample_diffuse_and_texture.cg";
const char* defaultMaterialTexturedLitFragmentShader = "fragment/sample_diffuse_and_texture.cg";
const char* defaultMaterialFragmentShader = "fragment/sample_diffuse_no_texture.cg";
RenderMaterial::RenderMaterial(Renderer& renderer, const PxVec3& diffuseColor, PxReal opacity, bool doubleSided, PxU32 id, RenderTexture* texture, bool lit, bool flat, bool instanced) :
mRenderMaterial (NULL),
mRenderMaterialInstance (NULL),
mID (id),
mDoubleSided (doubleSided),
mOwnsRendererMaterial (true)
{
RendererMaterialDesc matDesc;
if(lit)
matDesc.type = RendererMaterial::TYPE_LIT;
else
matDesc.type = RendererMaterial::TYPE_UNLIT;
matDesc.alphaTestFunc = RendererMaterial::ALPHA_TEST_ALWAYS;
matDesc.alphaTestRef = 0.0f;
if(opacity==1.0f)
{
matDesc.blending = false;
matDesc.srcBlendFunc = RendererMaterial::BLEND_ONE;
matDesc.dstBlendFunc = RendererMaterial::BLEND_ONE;
}
else
{
matDesc.type = RendererMaterial::TYPE_UNLIT;
matDesc.blending = true;
// matDesc.srcBlendFunc = RendererMaterial::BLEND_ONE;
// matDesc.dstBlendFunc = RendererMaterial::BLEND_ONE;
matDesc.srcBlendFunc = RendererMaterial::BLEND_SRC_ALPHA;
matDesc.dstBlendFunc = RendererMaterial::BLEND_ONE_MINUS_SRC_ALPHA;
}
if(instanced)
{
matDesc.instanced = true;
}
else
{
matDesc.instanced = false;
}
matDesc.geometryShaderPath = NULL;
matDesc.vertexShaderPath = defaultMaterialLitVertexShader;
if(texture)
{
if(lit)
{
matDesc.fragmentShaderPath = defaultMaterialTexturedLitFragmentShader;
}
else
{
matDesc.fragmentShaderPath = defaultMaterialTexturedUnlitFragmentShader;
}
}
else
{
matDesc.fragmentShaderPath = defaultMaterialFragmentShader;
}
PX_ASSERT(matDesc.isValid());
mRenderMaterial = renderer.createMaterial(matDesc);
mRenderMaterialInstance = new RendererMaterialInstance(*mRenderMaterial);
setDiffuseColor(PxVec4(diffuseColor.x, diffuseColor.y, diffuseColor.z, opacity));
setShadeMode(flat);
update(renderer);
if(texture)
{
const RendererMaterial::Variable* var = mRenderMaterialInstance->findVariable("diffuseTexture", RendererMaterial::VARIABLE_SAMPLER2D);
//PX_ASSERT(var);
if(var)
mRenderMaterialInstance->writeData(*var, &texture->mTexture);
}
}
RenderMaterial::RenderMaterial(Renderer& renderer, RendererMaterial* mat, RendererMaterialInstance* matInstance, PxU32 id) :
mRenderMaterial (mat),
mRenderMaterialInstance (matInstance),
mID (id),
mDoubleSided (false),
mOwnsRendererMaterial (false)
{
update(renderer);
}
void RenderMaterial::update(SampleRenderer::Renderer& renderer)
{
const RendererMaterial::Variable* var = mRenderMaterialInstance->findVariable("windowWidth", RendererMaterial::VARIABLE_FLOAT);
if(var)
{
PxU32 tmpWindowWidth, tmpWindowHeight;
renderer.getWindowSize(tmpWindowWidth, tmpWindowHeight);
const PxReal windowWidth = PxReal(tmpWindowWidth);
mRenderMaterialInstance->writeData(*var, &windowWidth);
}
}
void RenderMaterial::setParticleSize(const PxReal particleSize)
{
const RendererMaterial::Variable* var = mRenderMaterialInstance->findVariable("particleSize", RendererMaterial::VARIABLE_FLOAT);
if(var)
{
mRenderMaterialInstance->writeData(*var, &particleSize);
}
}
void RenderMaterial::setDiffuseColor(const PxVec4& color)
{
const RendererMaterial::Variable* var = mRenderMaterialInstance->findVariable("diffuseColor", RendererMaterial::VARIABLE_FLOAT4);
if(var)
{
const PxReal data[] = { color.x, color.y, color.z, color.w };
mRenderMaterialInstance->writeData(*var, data);
}
}
void RenderMaterial::setShadeMode(bool flat)
{
const RendererMaterial::Variable* var = mRenderMaterialInstance->findVariable("shadeMode", RendererMaterial::VARIABLE_FLOAT);
if(var)
{
float shadeMode = flat?1.0f:0.0f;
mRenderMaterialInstance->writeData(*var, &shadeMode);
}
}
RenderMaterial::~RenderMaterial()
{
if(mOwnsRendererMaterial)
{
DELETESINGLE(mRenderMaterialInstance);
SAFE_RELEASE(mRenderMaterial);
}
}

View File

@ -0,0 +1,78 @@
//
// 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 RENDER_MATERIAL_H
#define RENDER_MATERIAL_H
#include "RenderBaseObject.h"
#include "common/PxPhysXCommonConfig.h"
#include "foundation/PxVec3.h"
namespace SampleRenderer
{
class Renderer;
class RendererMaterial;
class RendererMaterialInstance;
}
class RenderTexture;
class RenderMaterial : public RenderBaseObject
{
public:
RenderMaterial(SampleRenderer::Renderer& renderer,
const PxVec3& diffuseColor,
PxReal opacity,
bool doubleSided,
PxU32 id,
RenderTexture* texture,
bool lit = true,
bool flat = false,
bool instanced = false);
RenderMaterial(SampleRenderer::Renderer& renderer,
SampleRenderer::RendererMaterial* mat,
SampleRenderer::RendererMaterialInstance* matInstance,
PxU32 id);
virtual ~RenderMaterial();
// the intent of this function is to update shaders variables, when needed (e.g. on resize)
virtual void update(SampleRenderer::Renderer& renderer);
void setDiffuseColor(const PxVec4& color);
void setParticleSize(const PxReal particleSize);
void setShadeMode(bool flat);
SampleRenderer::RendererMaterial* mRenderMaterial;
SampleRenderer::RendererMaterialInstance* mRenderMaterialInstance;
PxU32 mID;
bool mDoubleSided;
bool mOwnsRendererMaterial;
};
#endif

View File

@ -0,0 +1,68 @@
//
// 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 "RenderMeshActor.h"
#include "RendererMeshShape.h"
#include "RendererMemoryMacros.h"
#include "extensions/PxSmoothNormals.h"
#include "SampleAllocatorSDKClasses.h"
using namespace physx;
using namespace SampleRenderer;
RenderMeshActor::RenderMeshActor( Renderer& renderer,
const PxVec3* verts, PxU32 numVerts,
const PxVec3* vertexNormals,
const PxReal* uvs,
const PxU16* faces16, const PxU32* faces32, PxU32 numFaces, bool flipWinding
)
{
PxVec3Alloc* normals = NULL;
if(!vertexNormals)
{
normals = SAMPLE_NEW(PxVec3Alloc)[numVerts];
PxBuildSmoothNormals(numFaces, numVerts, verts, faces32, faces16, normals, flipWinding);
vertexNormals = normals;
}
RendererShape* rs = new RendererMeshShape(renderer, verts, numVerts, vertexNormals, uvs, faces16, faces32, numFaces, flipWinding);
setRenderShape(rs);
DELETEARRAY(normals);
}
RenderMeshActor::RenderMeshActor(const RenderMeshActor& src) : RenderBaseActor(src)
{
}
RenderMeshActor::~RenderMeshActor()
{
}

View File

@ -0,0 +1,54 @@
//
// 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 RENDER_MESH_ACTOR_H
#define RENDER_MESH_ACTOR_H
#include "RenderBaseActor.h"
#include "foundation/PxVec3.h"
namespace SampleRenderer
{
class Renderer;
}
class RenderMeshActor : public RenderBaseActor
{
public:
RenderMeshActor(SampleRenderer::Renderer& renderer,
const PxVec3* verts, PxU32 numVerts,
const PxVec3* vertexNormals,
const PxReal* uvs,
const PxU16* faces16, const PxU32* faces32, PxU32 numFaces, bool flipWinding=false
);
RenderMeshActor(const RenderMeshActor&);
virtual ~RenderMeshActor();
};
#endif

View File

@ -0,0 +1,923 @@
//
// 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 "RenderPhysX3Debug.h"
#include "RendererColor.h"
#include "common/PxRenderBuffer.h"
#include "foundation/PxSimpleTypes.h"
#include "SampleCamera.h"
#include "geometry/PxConvexMesh.h"
#include "geometry/PxConvexMeshGeometry.h"
#include "geometry/PxCapsuleGeometry.h"
#include "geometry/PxSphereGeometry.h"
#include "geometry/PxBoxGeometry.h"
#include "PsUtilities.h"
#include "PsString.h"
using namespace physx;
using namespace SampleRenderer;
using namespace SampleFramework;
RenderPhysX3Debug::RenderPhysX3Debug(Renderer& renderer, SampleAssetManager& assetmanager) :
SamplePointDebugRender (renderer, assetmanager),
SampleLineDebugRender (renderer, assetmanager),
SampleTriangleDebugRender (renderer, assetmanager)
{
}
RenderPhysX3Debug::~RenderPhysX3Debug()
{
}
void RenderPhysX3Debug::update(const PxRenderBuffer& debugRenderable)
{
// Points
const PxU32 numPoints = debugRenderable.getNbPoints();
if(numPoints)
{
const PxDebugPoint* PX_RESTRICT points = debugRenderable.getPoints();
checkResizePoint(numPoints);
for(PxU32 i=0; i<numPoints; i++)
{
const PxDebugPoint& point = points[i];
addPoint(point.pos, RendererColor(point.color));
}
}
// Lines
const PxU32 numLines = debugRenderable.getNbLines();
if(numLines)
{
const PxDebugLine* PX_RESTRICT lines = debugRenderable.getLines();
checkResizeLine(numLines * 2);
for(PxU32 i=0; i<numLines; i++)
{
const PxDebugLine& line = lines[i];
addLine(line.pos0, line.pos1, RendererColor(line.color0));
}
}
// Triangles
const PxU32 numTriangles = debugRenderable.getNbTriangles();
if(numTriangles)
{
const PxDebugTriangle* PX_RESTRICT triangles = debugRenderable.getTriangles();
checkResizeTriangle(numTriangles * 3);
for(PxU32 i=0; i<numTriangles; i++)
{
const PxDebugTriangle& triangle = triangles[i];
addTriangle(triangle.pos0, triangle.pos1, triangle.pos2, RendererColor(triangle.color0));
}
}
}
void RenderPhysX3Debug::update(const PxRenderBuffer& debugRenderable, const Camera& camera)
{
// Points
const PxU32 numPoints = debugRenderable.getNbPoints();
if(numPoints)
{
const PxDebugPoint* PX_RESTRICT points = debugRenderable.getPoints();
checkResizePoint(numPoints);
for(PxU32 i=0; i<numPoints; i++)
{
const PxDebugPoint& point = points[i];
addPoint(point.pos, RendererColor(point.color));
}
}
// Lines
const PxU32 numLines = debugRenderable.getNbLines();
if(numLines)
{
const PxDebugLine* PX_RESTRICT lines = debugRenderable.getLines();
checkResizeLine(numLines * 2);
PxU32 nbVisible = 0;
for(PxU32 i=0; i<numLines; i++)
{
const PxDebugLine& line = lines[i];
PxBounds3 b;
b.minimum.x = PxMin(line.pos0.x, line.pos1.x);
b.minimum.y = PxMin(line.pos0.y, line.pos1.y);
b.minimum.z = PxMin(line.pos0.z, line.pos1.z);
b.maximum.x = PxMax(line.pos0.x, line.pos1.x);
b.maximum.y = PxMax(line.pos0.y, line.pos1.y);
b.maximum.z = PxMax(line.pos0.z, line.pos1.z);
if(camera.cull(b)==PLANEAABB_EXCLUSION)
continue;
addLine(line.pos0, line.pos1, RendererColor(line.color0));
nbVisible++;
}
shdfnd::printFormatted("%f\n", float(nbVisible)/float(numLines));
}
// Triangles
const PxU32 numTriangles = debugRenderable.getNbTriangles();
if(numTriangles)
{
const PxDebugTriangle* PX_RESTRICT triangles = debugRenderable.getTriangles();
checkResizeTriangle(numTriangles * 3);
for(PxU32 i=0; i<numTriangles; i++)
{
const PxDebugTriangle& triangle = triangles[i];
addTriangle(triangle.pos0, triangle.pos1, triangle.pos2, RendererColor(triangle.color0));
}
}
}
void RenderPhysX3Debug::queueForRender()
{
queueForRenderPoint();
queueForRenderLine();
queueForRenderTriangle();
}
void RenderPhysX3Debug::clear()
{
clearPoint();
clearLine();
clearTriangle();
}
///////////////////////////////////////////////////////////////////////////////
#define NB_CIRCLE_PTS 20
void RenderPhysX3Debug::addBox(const PxVec3* pts, const RendererColor& color, PxU32 renderFlags)
{
if(renderFlags & RENDER_DEBUG_WIREFRAME)
{
const PxU8 indices[] = {
0, 1, 1, 2, 2, 3, 3, 0,
7, 6, 6, 5, 5, 4, 4, 7,
1, 5, 6, 2,
3, 7, 4, 0
};
for(PxU32 i=0;i<12;i++)
addLine(pts[indices[i*2]], pts[indices[i*2+1]], color);
}
if(renderFlags & RENDER_DEBUG_SOLID)
{
const PxU8 indices[] = {
0,2,1, 0,3,2,
1,6,5, 1,2,6,
5,7,4, 5,6,7,
4,3,0, 4,7,3,
3,6,2, 3,7,6,
5,0,1, 5,4,0
};
for(PxU32 i=0;i<12;i++)
addTriangle(pts[indices[i*3+0]], pts[indices[i*3+1]], pts[indices[i*3+2]], color);
}
}
void RenderPhysX3Debug::addCircle(PxU32 nbPts, const PxVec3* pts, const RendererColor& color, const PxVec3& offset)
{
for(PxU32 i=0;i<nbPts;i++)
{
const PxU32 j = (i+1) % nbPts;
addLine(pts[i]+offset, pts[j]+offset, color);
}
}
void RenderPhysX3Debug::addAABB(const PxBounds3& box, const RendererColor& color, PxU32 renderFlags)
{
const PxVec3& min = box.minimum;
const PxVec3& max = box.maximum;
// 7+------+6 0 = ---
// /| /| 1 = +--
// / | / | 2 = ++-
// / 4+---/--+5 3 = -+-
// 3+------+2 / y z 4 = --+
// | / | / | / 5 = +-+
// |/ |/ |/ 6 = +++
// 0+------+1 *---x 7 = -++
// Generate 8 corners of the bbox
PxVec3 pts[8];
pts[0] = PxVec3(min.x, min.y, min.z);
pts[1] = PxVec3(max.x, min.y, min.z);
pts[2] = PxVec3(max.x, max.y, min.z);
pts[3] = PxVec3(min.x, max.y, min.z);
pts[4] = PxVec3(min.x, min.y, max.z);
pts[5] = PxVec3(max.x, min.y, max.z);
pts[6] = PxVec3(max.x, max.y, max.z);
pts[7] = PxVec3(min.x, max.y, max.z);
addBox(pts, color, renderFlags);
}
void RenderPhysX3Debug::addBox(const PxBoxGeometry& bg, const PxTransform& tr, const RendererColor& color, PxU32 renderFlags)
{
addOBB(tr.p, bg.halfExtents, PxMat33(tr.q), color, renderFlags);
}
void RenderPhysX3Debug::addOBB(const PxVec3& boxCenter, const PxVec3& boxExtents, const PxMat33& boxRot, const RendererColor& color, PxU32 renderFlags)
{
PxVec3 Axis0 = boxRot.column0;
PxVec3 Axis1 = boxRot.column1;
PxVec3 Axis2 = boxRot.column2;
// "Rotated extents"
Axis0 *= boxExtents.x;
Axis1 *= boxExtents.y;
Axis2 *= boxExtents.z;
// 7+------+6 0 = ---
// /| /| 1 = +--
// / | / | 2 = ++-
// / 4+---/--+5 3 = -+-
// 3+------+2 / y z 4 = --+
// | / | / | / 5 = +-+
// |/ |/ |/ 6 = +++
// 0+------+1 *---x 7 = -++
// Original code: 24 vector ops
/* pts[0] = mCenter - Axis0 - Axis1 - Axis2;
pts[1] = mCenter + Axis0 - Axis1 - Axis2;
pts[2] = mCenter + Axis0 + Axis1 - Axis2;
pts[3] = mCenter - Axis0 + Axis1 - Axis2;
pts[4] = mCenter - Axis0 - Axis1 + Axis2;
pts[5] = mCenter + Axis0 - Axis1 + Axis2;
pts[6] = mCenter + Axis0 + Axis1 + Axis2;
pts[7] = mCenter - Axis0 + Axis1 + Axis2;*/
// Rewritten: 12 vector ops
PxVec3 pts[8];
pts[0] = pts[3] = pts[4] = pts[7] = boxCenter - Axis0;
pts[1] = pts[2] = pts[5] = pts[6] = boxCenter + Axis0;
PxVec3 Tmp = Axis1 + Axis2;
pts[0] -= Tmp;
pts[1] -= Tmp;
pts[6] += Tmp;
pts[7] += Tmp;
Tmp = Axis1 - Axis2;
pts[2] += Tmp;
pts[3] += Tmp;
pts[4] -= Tmp;
pts[5] -= Tmp;
addBox(pts, color, renderFlags);
}
enum Orientation
{
ORIENTATION_XY,
ORIENTATION_XZ,
ORIENTATION_YZ,
ORIENTATION_FORCE_DWORD = 0x7fffffff
};
static bool generatePolygon(PxU32 nbVerts, PxVec3* verts, Orientation orientation, float amplitude, float phase, const PxTransform* transform=NULL)
{
if(!nbVerts || !verts)
return false;
const float step = PxTwoPi/float(nbVerts);
for(PxU32 i=0;i<nbVerts;i++)
{
const float angle = phase + float(i) * step;
const float y = sinf(angle) * amplitude;
const float x = cosf(angle) * amplitude;
if(orientation==ORIENTATION_XY) { verts[i] = PxVec3(x, y, 0.0f); }
else if(orientation==ORIENTATION_XZ) { verts[i] = PxVec3(x, 0.0f, y); }
else if(orientation==ORIENTATION_YZ) { verts[i] = PxVec3(0.0f, x, y); }
if(transform)
verts[i] = transform->transform(verts[i]);
}
return true;
}
// PT: this comes from RendererCapsuleShape.cpp. Maybe we could grab the data from there instead of duplicating. But it protects us from external changes.
static const PxVec3 gCapsuleVertices[] =
{
PxVec3(0.0000f, -2.0000f, -0.0000f),
PxVec3(0.3827f, -1.9239f, -0.0000f),
PxVec3(0.2706f, -1.9239f, 0.2706f),
PxVec3(-0.0000f, -1.9239f, 0.3827f),
PxVec3(-0.2706f, -1.9239f, 0.2706f),
PxVec3(-0.3827f, -1.9239f, -0.0000f),
PxVec3(-0.2706f, -1.9239f, -0.2706f),
PxVec3(0.0000f, -1.9239f, -0.3827f),
PxVec3(0.2706f, -1.9239f, -0.2706f),
PxVec3(0.7071f, -1.7071f, -0.0000f),
PxVec3(0.5000f, -1.7071f, 0.5000f),
PxVec3(-0.0000f, -1.7071f, 0.7071f),
PxVec3(-0.5000f, -1.7071f, 0.5000f),
PxVec3(-0.7071f, -1.7071f, -0.0000f),
PxVec3(-0.5000f, -1.7071f, -0.5000f),
PxVec3(0.0000f, -1.7071f, -0.7071f),
PxVec3(0.5000f, -1.7071f, -0.5000f),
PxVec3(0.9239f, -1.3827f, -0.0000f),
PxVec3(0.6533f, -1.3827f, 0.6533f),
PxVec3(-0.0000f, -1.3827f, 0.9239f),
PxVec3(-0.6533f, -1.3827f, 0.6533f),
PxVec3(-0.9239f, -1.3827f, -0.0000f),
PxVec3(-0.6533f, -1.3827f, -0.6533f),
PxVec3(0.0000f, -1.3827f, -0.9239f),
PxVec3(0.6533f, -1.3827f, -0.6533f),
PxVec3(1.0000f, -1.0000f, -0.0000f),
PxVec3(0.7071f, -1.0000f, 0.7071f),
PxVec3(-0.0000f, -1.0000f, 1.0000f),
PxVec3(-0.7071f, -1.0000f, 0.7071f),
PxVec3(-1.0000f, -1.0000f, -0.0000f),
PxVec3(-0.7071f, -1.0000f, -0.7071f),
PxVec3(0.0000f, -1.0000f, -1.0000f),
PxVec3(0.7071f, -1.0000f, -0.7071f),
PxVec3(1.0000f, 1.0000f, 0.0000f),
PxVec3(0.7071f, 1.0000f, 0.7071f),
PxVec3(-0.0000f, 1.0000f, 1.0000f),
PxVec3(-0.7071f, 1.0000f, 0.7071f),
PxVec3(-1.0000f, 1.0000f, -0.0000f),
PxVec3(-0.7071f, 1.0000f, -0.7071f),
PxVec3(0.0000f, 1.0000f, -1.0000f),
PxVec3(0.7071f, 1.0000f, -0.7071f),
PxVec3(0.9239f, 1.3827f, 0.0000f),
PxVec3(0.6533f, 1.3827f, 0.6533f),
PxVec3(-0.0000f, 1.3827f, 0.9239f),
PxVec3(-0.6533f, 1.3827f, 0.6533f),
PxVec3(-0.9239f, 1.3827f, -0.0000f),
PxVec3(-0.6533f, 1.3827f, -0.6533f),
PxVec3(0.0000f, 1.3827f, -0.9239f),
PxVec3(0.6533f, 1.3827f, -0.6533f),
PxVec3(0.7071f, 1.7071f, 0.0000f),
PxVec3(0.5000f, 1.7071f, 0.5000f),
PxVec3(-0.0000f, 1.7071f, 0.7071f),
PxVec3(-0.5000f, 1.7071f, 0.5000f),
PxVec3(-0.7071f, 1.7071f, 0.0000f),
PxVec3(-0.5000f, 1.7071f, -0.5000f),
PxVec3(0.0000f, 1.7071f, -0.7071f),
PxVec3(0.5000f, 1.7071f, -0.5000f),
PxVec3(0.3827f, 1.9239f, 0.0000f),
PxVec3(0.2706f, 1.9239f, 0.2706f),
PxVec3(-0.0000f, 1.9239f, 0.3827f),
PxVec3(-0.2706f, 1.9239f, 0.2706f),
PxVec3(-0.3827f, 1.9239f, 0.0000f),
PxVec3(-0.2706f, 1.9239f, -0.2706f),
PxVec3(0.0000f, 1.9239f, -0.3827f),
PxVec3(0.2706f, 1.9239f, -0.2706f),
PxVec3(0.0000f, 2.0000f, 0.0000f),
};
static const PxU8 gCapsuleIndices[] =
{
1, 0, 2, 2, 0, 3, 3, 0, 4, 4, 0, 5, 5, 0, 6, 6, 0, 7, 7, 0, 8,
8, 0, 1, 9, 1, 10, 10, 1, 2, 10, 2, 11, 11, 2, 3, 11, 3, 12,
12, 3, 4, 12, 4, 13, 13, 4, 5, 13, 5, 14, 14, 5, 6, 14, 6, 15,
15, 6, 7, 15, 7, 16, 16, 7, 8, 16, 8, 9, 9, 8, 1, 17, 9, 18,
18, 9, 10, 18, 10, 19, 19, 10, 11, 19, 11, 20, 20, 11, 12, 20, 12, 21,
21, 12, 13, 21, 13, 22, 22, 13, 14, 22, 14, 23, 23, 14, 15, 23, 15, 24,
24, 15, 16, 24, 16, 17, 17, 16, 9, 25, 17, 26, 26, 17, 18, 26, 18, 27,
27, 18, 19, 27, 19, 28, 28, 19, 20, 28, 20, 29, 29, 20, 21, 29, 21, 30,
30, 21, 22, 30, 22, 31, 31, 22, 23, 31, 23, 32, 32, 23, 24, 32, 24, 25,
25, 24, 17, 33, 25, 34, 34, 25, 26, 34, 26, 35, 35, 26, 27, 35, 27, 36,
36, 27, 28, 36, 28, 37, 37, 28, 29, 37, 29, 38, 38, 29, 30, 38, 30, 39,
39, 30, 31, 39, 31, 40, 40, 31, 32, 40, 32, 33, 33, 32, 25, 41, 33, 42,
42, 33, 34, 42, 34, 43, 43, 34, 35, 43, 35, 44, 44, 35, 36, 44, 36, 45,
45, 36, 37, 45, 37, 46, 46, 37, 38, 46, 38, 47, 47, 38, 39, 47, 39, 48,
48, 39, 40, 48, 40, 41, 41, 40, 33, 49, 41, 50, 50, 41, 42, 50, 42, 51,
51, 42, 43, 51, 43, 52, 52, 43, 44, 52, 44, 53, 53, 44, 45, 53, 45, 54,
54, 45, 46, 54, 46, 55, 55, 46, 47, 55, 47, 56, 56, 47, 48, 56, 48, 49,
49, 48, 41, 57, 49, 58, 58, 49, 50, 58, 50, 59, 59, 50, 51, 59, 51, 60,
60, 51, 52, 60, 52, 61, 61, 52, 53, 61, 53, 62, 62, 53, 54, 62, 54, 63,
63, 54, 55, 63, 55, 64, 64, 55, 56, 64, 56, 57, 57, 56, 49, 65, 57, 58,
65, 58, 59, 65, 59, 60, 65, 60, 61, 65, 61, 62, 65, 62, 63, 65, 63, 64,
65, 64, 57,
};
static const PxU32 gNumCapsuleIndices = PX_ARRAY_SIZE(gCapsuleIndices);
static PX_FORCE_INLINE void fixCapsuleVertex(PxVec3& p, PxF32 radius, PxF32 halfHeight)
{
const PxF32 sign = p.y > 0 ? 1.0f : -1.0f;
p.y -= sign;
p *= radius;
p.y += halfHeight*sign;
}
void RenderPhysX3Debug::addSphere(const PxSphereGeometry& sg, const PxTransform& tr, const RendererColor& color, PxU32 renderFlags)
{
addSphere(tr.p, sg.radius, color, renderFlags);
}
void RenderPhysX3Debug::addSphere(const PxVec3& sphereCenter, float sphereRadius, const RendererColor& color, PxU32 renderFlags)
{
const PxU32 nbVerts = NB_CIRCLE_PTS;
PxVec3 pts[NB_CIRCLE_PTS];
if(renderFlags & RENDER_DEBUG_WIREFRAME)
{
generatePolygon(nbVerts, pts, ORIENTATION_XY, sphereRadius, 0.0f);
addCircle(nbVerts, pts, color, sphereCenter);
generatePolygon(nbVerts, pts, ORIENTATION_XZ, sphereRadius, 0.0f);
addCircle(nbVerts, pts, color, sphereCenter);
generatePolygon(nbVerts, pts, ORIENTATION_YZ, sphereRadius, 0.0f);
addCircle(nbVerts, pts, color, sphereCenter);
}
if(renderFlags & RENDER_DEBUG_SOLID)
{
const PxF32 halfHeight = 0.0f;
for(PxU32 i=0;i<gNumCapsuleIndices/3;i++)
{
const PxU32 i0 = gCapsuleIndices[i*3+0];
const PxU32 i1 = gCapsuleIndices[i*3+1];
const PxU32 i2 = gCapsuleIndices[i*3+2];
PxVec3 v0 = gCapsuleVertices[i0];
PxVec3 v1 = gCapsuleVertices[i1];
PxVec3 v2 = gCapsuleVertices[i2];
fixCapsuleVertex(v0, sphereRadius, halfHeight);
fixCapsuleVertex(v1, sphereRadius, halfHeight);
fixCapsuleVertex(v2, sphereRadius, halfHeight);
addTriangle(v0+sphereCenter, v1+sphereCenter, v2+sphereCenter, color);
}
}
}
#define MAX_TEMP_VERTEX_BUFFER 400
// creaet triangle strip of spheres
static bool generateSphere(PxU32 nbSeg, PxU32& nbVerts, PxVec3* verts, PxVec3* normals)
{
PxVec3 tempVertexBuffer[MAX_TEMP_VERTEX_BUFFER];
PxVec3 tempNormalBuffer[MAX_TEMP_VERTEX_BUFFER];
int halfSeg = nbSeg / 2;
int nSeg = halfSeg * 2;
if (((nSeg+1) * (nSeg+1)) > MAX_TEMP_VERTEX_BUFFER)
return false;
const float stepTheta = PxTwoPi / float(nSeg);
const float stepPhi = PxPi / float(nSeg);
// compute sphere vertices on the temporary buffer
nbVerts = 0;
for (int i = 0; i <= nSeg; i++)
{
const float theta = float(i) * stepTheta;
const float cosi = cos(theta);
const float sini = sin(theta);
for (int j = -halfSeg; j <= halfSeg; j++)
{
const float phi = float(j) * stepPhi;
const float sinj = sin( phi);
const float cosj = cos( phi);
const float y = cosj * cosi;
const float x = sinj;
const float z = cosj * sini;
tempVertexBuffer[nbVerts] = PxVec3(x,y,z);
tempNormalBuffer[nbVerts] = PxVec3(x,y,z).getNormalized();
nbVerts++;
}
}
nbVerts = 0;
// now create triangle soup data
for (int i = 0; i < nSeg; i++)
{
for (int j = 0; j < nSeg; j++)
{
// add one triangle
verts[nbVerts] = tempVertexBuffer[ (nSeg+1) * i + j];
normals[nbVerts] = tempNormalBuffer[ (nSeg+1) * i + j];
nbVerts++;
verts[nbVerts] = tempVertexBuffer[ (nSeg+1) * i + j+1];
normals[nbVerts] = tempNormalBuffer[ (nSeg+1) * i + j+1];
nbVerts++;
verts[nbVerts] = tempVertexBuffer[ (nSeg+1) * (i+1) + j+1];
normals[nbVerts] = tempNormalBuffer[ (nSeg+1) * (i+1) + j+1];
nbVerts++;
// add another triangle
verts[nbVerts] = tempVertexBuffer[ (nSeg+1) * i + j];
normals[nbVerts] = tempNormalBuffer[ (nSeg+1) * i + j];
nbVerts++;
verts[nbVerts] = tempVertexBuffer[ (nSeg+1) * (i+1) + j+1];
normals[nbVerts] = tempNormalBuffer[ (nSeg+1) * (i+1) + j+1];
nbVerts++;
verts[nbVerts] = tempVertexBuffer[ (nSeg+1) * (i+1) + j];
normals[nbVerts] = tempNormalBuffer[ (nSeg+1) * (i+1) + j];
nbVerts++;
}
}
return true;
}
void RenderPhysX3Debug::addSphereExt(const PxVec3& sphereCenter, float sphereRadius, const RendererColor& color, PxU32 renderFlags)
{
if(renderFlags & RENDER_DEBUG_WIREFRAME)
{
const PxU32 nbVerts = NB_CIRCLE_PTS;
PxVec3 pts[NB_CIRCLE_PTS];
generatePolygon(nbVerts, pts, ORIENTATION_XY, sphereRadius, 0.0f);
addCircle(nbVerts, pts, color, sphereCenter);
generatePolygon(nbVerts, pts, ORIENTATION_XZ, sphereRadius, 0.0f);
addCircle(nbVerts, pts, color, sphereCenter);
generatePolygon(nbVerts, pts, ORIENTATION_YZ, sphereRadius, 0.0f);
addCircle(nbVerts, pts, color, sphereCenter);
}
if(renderFlags & RENDER_DEBUG_SOLID)
{
static bool initDone = false;
static PxU32 nbVerts;
static PxVec3 verts[MAX_TEMP_VERTEX_BUFFER*6];
static PxVec3 normals[MAX_TEMP_VERTEX_BUFFER*6];
if (!initDone)
{
generateSphere(16, nbVerts, verts, normals);
initDone = true;
}
PxU32 i = 0;
while ( i < nbVerts )
{
addTriangle( sphereCenter + sphereRadius * verts[i], sphereCenter + sphereRadius * verts[i+1], sphereCenter + sphereRadius * verts[i+2],
normals[i], normals[i+1], normals[i+2], color);
i += 3;
}
}
}
#undef MAX_TEMP_VERTEX_BUFFFER
static inline PxU32 minArgument(const PxVec3 &v)
{
PxU32 j = 0;
if ( v[j] > v[1]) j = 1;
if ( v[j] > v[2]) j = 2;
return j;
}
static inline PxVec3 abs(const PxVec3 &v)
{
return PxVec3( PxAbs(v.x), PxAbs(v.y), PxAbs(v.z));
}
void RenderPhysX3Debug::addConeExt(float r0, float r1, const PxVec3& p0, const PxVec3& p1 , const RendererColor& color, PxU32 renderFlags)
{
PxVec3 axis = p1 - p0;
PxReal length = axis.magnitude();
PxReal rdiff = r0 - r1;
PxReal sinAngle = rdiff / length;
PxReal x0 = r0 * sinAngle;
PxReal x1 = r1 * sinAngle;
PxVec3 center = 0.5f * (p0 + p1);
if (length < fabs(rdiff))
return;
PxReal r0p = sqrt(r0 * r0 - x0 * x0);
PxReal r1p = sqrt(r1 * r1 - x1 * x1);
if (length == 0.0f)
axis = PxVec3(1,0,0);
else
axis.normalize();
PxVec3 axis1(0.0f);
axis1[minArgument(abs(axis))] = 1.0f;
axis1 = axis1.cross(axis);
axis1.normalize();
PxVec3 axis2 = axis.cross(axis1);
axis2.normalize();
PxMat44 m;
m.column0 = PxVec4(axis, 0.0f);
m.column1 = PxVec4(axis1, 0.0f);
m.column2 = PxVec4(axis2, 0.0f);
m.column3 = PxVec4(center, 1.0f);
PxTransform tr(m);
#define NUM_CONE_VERTS 72
const PxU32 nbVerts = NUM_CONE_VERTS;
PxVec3 pts0[NUM_CONE_VERTS] ;
PxVec3 pts1[NUM_CONE_VERTS];
PxVec3 normals[NUM_CONE_VERTS] ;
const float step = PxTwoPi / float(nbVerts);
for (PxU32 i = 0; i < nbVerts; i++)
{
const float angle = float(i) * step;
const float x = cosf(angle);
const float y = sinf(angle);
PxVec3 p = PxVec3(0.0f, x, y);
pts0[i] = tr.transform(r0p * p + PxVec3(-0.5f * length + x0,0,0));
pts1[i] = tr.transform(r1p * p + PxVec3(0.5f * length + x1, 0, 0));
normals[i] = tr.q.rotate(p.getNormalized());
normals[i] = x0 * axis + r0p * normals[i];
normals[i].normalize();
}
#undef NUM_CONE_VERTS
if(renderFlags & RENDER_DEBUG_WIREFRAME)
{
for(PxU32 i=0;i<nbVerts;i++)
{
addLine(pts1[i], pts0[i], color);
}
}
if(renderFlags & RENDER_DEBUG_SOLID)
{
for(PxU32 i=0;i<nbVerts;i++)
{
const PxU32 j = (i+1) % nbVerts;
addTriangle(pts0[i], pts1[j], pts0[j], normals[i], normals[j], normals[j], color);
addTriangle(pts0[i], pts1[i], pts1[j], normals[i], normals[i], normals[j], color);
}
}
}
void RenderPhysX3Debug::addCone(float radius, float height, const PxTransform& tr, const RendererColor& color, PxU32 renderFlags)
{
const PxU32 nbVerts = NB_CIRCLE_PTS;
PxVec3 pts[NB_CIRCLE_PTS];
generatePolygon(nbVerts, pts, ORIENTATION_XZ, radius, 0.0f, &tr);
const PxVec3 tip = tr.transform(PxVec3(0.0f, height, 0.0f));
if(renderFlags & RENDER_DEBUG_WIREFRAME)
{
addCircle(nbVerts, pts, color, PxVec3(0));
for(PxU32 i=0;i<nbVerts;i++)
{
addLine(tip, pts[i], color); // side of the cone
addLine(tr.p, pts[i], color); // base disk of the cone
}
}
if(renderFlags & RENDER_DEBUG_SOLID)
{
for(PxU32 i=0;i<nbVerts;i++)
{
const PxU32 j = (i+1) % nbVerts;
addTriangle(tip, pts[i], pts[j], color);
addTriangle(tr.p, pts[i], pts[j], color);
}
}
}
void RenderPhysX3Debug::addCylinder(float radius, float height, const PxTransform& tr, const RendererColor& color, PxU32 renderFlags)
{
const PxU32 nbVerts = NB_CIRCLE_PTS;
PxVec3 pts[NB_CIRCLE_PTS];
generatePolygon(nbVerts, pts, ORIENTATION_XZ, radius, 0.0f, &tr);
PxTransform tr2 = tr;
tr2.p = tr.transform(PxVec3(0.0f, height, 0.0f));
PxVec3 pts2[NB_CIRCLE_PTS];
generatePolygon(nbVerts, pts2, ORIENTATION_XZ, radius, 0.0f, &tr2);
if(renderFlags & RENDER_DEBUG_WIREFRAME)
{
for(PxU32 i=0;i<nbVerts;i++)
{
const PxU32 j = (i+1) % nbVerts;
addLine(pts[i], pts[j], color); // circle
addLine(pts2[i], pts2[j], color); // circle
}
for(PxU32 i=0;i<nbVerts;i++)
{
addLine(pts[i], pts2[i], color); // side
addLine(tr.p, pts[i], color); // disk
addLine(tr2.p, pts2[i], color); // disk
}
}
if(renderFlags & RENDER_DEBUG_SOLID)
{
for(PxU32 i=0;i<nbVerts;i++)
{
const PxU32 j = (i+1) % nbVerts;
addTriangle(tr.p, pts[i], pts[j], color);
addTriangle(tr2.p, pts2[i], pts2[j], color);
addTriangle(pts[i], pts[j], pts2[j], color);
addTriangle(pts[i], pts2[j], pts2[i], color);
}
}
}
void RenderPhysX3Debug::addStar(const PxVec3& p, const float size, const RendererColor& color )
{
const PxVec3 up(0.f, size, 0.f);
const PxVec3 right(size, 0.f, 0.f);
const PxVec3 forwards(0.f, 0.f, size);
addLine(p + up, p - up, color);
addLine(p + right, p - right, color);
addLine(p + forwards, p - forwards, color);
}
void RenderPhysX3Debug::addCapsule(const PxCapsuleGeometry& cg, const PxTransform& tr, const RendererColor& color, PxU32 renderFlags)
{
PxTransform pose = PxTransform(PxVec3(0.f), PxQuat(PxPi/2, PxVec3(0,0,1)));
pose = tr * pose;
PxVec3 p0(0, -cg.halfHeight, 0);
PxVec3 p1(0, cg.halfHeight, 0);
p0 = pose.transform(p0);
p1 = pose.transform(p1);
pose.p = p0;
/*PxTransform pose = PxTransform(PxVec3(0.f), PxQuat(PxPi/2, PxVec3(0,0,1)));
pose = tr * pose;*/
//const PxReal height = cg.halfHeight;
//const PxVec3 p0 = tr.p - PxVec3(0, height, 0);
//const PxVec3 p1 = tr.p + PxVec3(0, height, 0);
addCapsule(p0, p1, cg.radius, 2*cg.halfHeight, pose, color, renderFlags);
}
void RenderPhysX3Debug::addCapsule(const PxVec3& p0, const PxVec3& p1, const float radius, const float height, const PxTransform& tr, const RendererColor& color, PxU32 renderFlags)
{
addSphere(p0, radius, color, renderFlags);
addSphere(p1, radius, color, renderFlags);
addCylinder(radius, height, tr, color, renderFlags);
}
void RenderPhysX3Debug::addRectangle(float width, float length, const PxTransform& tr, const RendererColor& color)
{
PxMat33 m33 = PxMat33(tr.q);
PxVec3 Axis1 = m33.column1;
PxVec3 Axis2 = m33.column2;
Axis1 *= length;
Axis2 *= width;
PxVec3 pts[4];
pts[0] = tr.p + Axis1 + Axis2 ;
pts[1] = tr.p - Axis1 + Axis2 ;
pts[2] = tr.p - Axis1 - Axis2 ;
pts[3] = tr.p + Axis1 - Axis2 ;
addTriangle(pts[0], pts[1], pts[2], color);
addTriangle(pts[0], pts[2], pts[3], color);
}
void RenderPhysX3Debug::addGeometry(const PxGeometry& geom, const PxTransform& tr, const RendererColor& color, PxU32 renderFlags)
{
switch(geom.getType())
{
case PxGeometryType::eBOX:
{
addBox(static_cast<const PxBoxGeometry&>(geom), tr, color, renderFlags);
}
break;
case PxGeometryType::eSPHERE:
{
addSphere(static_cast<const PxSphereGeometry&>(geom), tr, color, renderFlags);
}
break;
case PxGeometryType::eCAPSULE:
{
addCapsule(static_cast<const PxCapsuleGeometry&>(geom), tr, color, renderFlags);
}
break;
case PxGeometryType::eCONVEXMESH:
{
addConvex(static_cast<const PxConvexMeshGeometry&>(geom), tr, color, renderFlags);
}
break;
case PxGeometryType::ePLANE:
case PxGeometryType::eTRIANGLEMESH:
case PxGeometryType::eHEIGHTFIELD:
default:
{
PX_ASSERT(!"Not supported!");
break;
}
}
}
void RenderPhysX3Debug::addConvex(const PxConvexMeshGeometry& cg, const PxTransform& tr, const RendererColor& color, PxU32 renderFlags)
{
const PxConvexMesh& mesh = *cg.convexMesh;
const PxMat33 rot = PxMat33(tr.q) * cg.scale.toMat33();
// PT: you can't use PxTransform with a non-uniform scaling
const PxMat44 globalPose(rot, tr.p);
const PxU32 polygonCount = mesh.getNbPolygons();
const PxU8* indexBuffer = mesh.getIndexBuffer();
const PxVec3* vertexBuffer = mesh.getVertices();
if(renderFlags & RENDER_DEBUG_WIREFRAME)
{
for(PxU32 i=0; i<polygonCount; i++)
{
PxHullPolygon data;
mesh.getPolygonData(i, data);
const PxU32 vertexCount = data.mNbVerts;
PxU32 i0 = indexBuffer[vertexCount-1];
PxU32 i1 = *indexBuffer++;
addLine(globalPose.transform(vertexBuffer[i0]), globalPose.transform(vertexBuffer[i1]), color);
for(PxU32 j=1; j<vertexCount; j++)
{
i0 = indexBuffer[-1];
i1 = *indexBuffer++;
addLine(globalPose.transform(vertexBuffer[i0]), globalPose.transform(vertexBuffer[i1]), color);
}
}
}
if(renderFlags & RENDER_DEBUG_SOLID)
{
for(PxU32 i=0; i<polygonCount; i++)
{
PxHullPolygon data;
mesh.getPolygonData(i, data);
const PxU32 vertexCount = data.mNbVerts;
const PxVec3& v0 = vertexBuffer[indexBuffer[0]];
for(PxU32 j=0; j<vertexCount-2; j++)
{
const PxVec3& v1 = vertexBuffer[indexBuffer[j+1]];
const PxVec3& v2 = vertexBuffer[indexBuffer[j+2]];
addTriangle(globalPose.transform(v0), globalPose.transform(v1), globalPose.transform(v2), color);
}
indexBuffer += vertexCount;
}
}
}
void RenderPhysX3Debug::addArrow(const PxVec3& posA, const PxVec3& posB, const RendererColor& color)
{
const PxVec3 t0 = (posB - posA).getNormalized();
const PxVec3 a = PxAbs(t0.x)<0.707f ? PxVec3(1,0,0): PxVec3(0,1,0);
const PxVec3 t1 = t0.cross(a).getNormalized();
const PxVec3 t2 = t0.cross(t1).getNormalized();
addLine(posA, posB, color);
addLine(posB, posB - t0*0.15f + t1 * 0.15f, color);
addLine(posB, posB - t0*0.15f - t1 * 0.15f, color);
addLine(posB, posB - t0*0.15f + t2 * 0.15f, color);
addLine(posB, posB - t0*0.15f - t2 * 0.15f, color);
}

View File

@ -0,0 +1,100 @@
//
// 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 RENDER_PHYSX3_DEBUG_H
#define RENDER_PHYSX3_DEBUG_H
#include <SamplePointDebugRender.h>
#include <SampleLineDebugRender.h>
#include <SampleTriangleDebugRender.h>
#include "SampleAllocator.h"
enum RenderPhysX3DebugFlag
{
RENDER_DEBUG_WIREFRAME = (1<<0),
RENDER_DEBUG_SOLID = (1<<1),
RENDER_DEBUG_DEFAULT = RENDER_DEBUG_SOLID//RENDER_DEBUG_WIREFRAME//|RENDER_DEBUG_SOLID
};
namespace physx
{
class PxRenderBuffer;
class PxConvexMeshGeometry;
class PxCapsuleGeometry;
class PxSphereGeometry;
class PxBoxGeometry;
class PxGeometry;
}
class Camera;
class RenderPhysX3Debug : public SampleFramework::SamplePointDebugRender
, public SampleFramework::SampleLineDebugRender
, public SampleFramework::SampleTriangleDebugRender
, public SampleAllocateable
{
public:
RenderPhysX3Debug(SampleRenderer::Renderer& renderer, SampleFramework::SampleAssetManager& assetmanager);
virtual ~RenderPhysX3Debug();
void addAABB(const PxBounds3& box, const SampleRenderer::RendererColor& color, PxU32 renderFlags = RENDER_DEBUG_DEFAULT);
void addOBB(const PxVec3& boxCenter, const PxVec3& boxExtents, const PxMat33& boxRot, const SampleRenderer::RendererColor& color, PxU32 renderFlags = RENDER_DEBUG_DEFAULT);
void addSphere(const PxVec3& sphereCenter, float sphereRadius, const SampleRenderer::RendererColor& color, PxU32 renderFlags = RENDER_DEBUG_DEFAULT);
void addBox(const PxBoxGeometry& bg, const PxTransform& tr, const SampleRenderer::RendererColor& color, PxU32 renderFlags = RENDER_DEBUG_DEFAULT);
void addSphere(const PxSphereGeometry& sg, const PxTransform& tr, const SampleRenderer::RendererColor& color, PxU32 renderFlags = RENDER_DEBUG_DEFAULT);
void addCone(float radius, float height, const PxTransform& tr, const SampleRenderer::RendererColor& color, PxU32 renderFlags = RENDER_DEBUG_DEFAULT);
void addSphereExt(const PxVec3& sphereCenter, float sphereRadius, const SampleRenderer::RendererColor& color, PxU32 renderFlags = RENDER_DEBUG_DEFAULT);
void addConeExt(float radius0, float radius1, const PxVec3& p0, const PxVec3& p1 , const SampleRenderer::RendererColor& color, PxU32 renderFlags = RENDER_DEBUG_DEFAULT);
void addCylinder(float radius, float height, const PxTransform& tr, const SampleRenderer::RendererColor& color, PxU32 renderFlags = RENDER_DEBUG_DEFAULT);
void addStar(const PxVec3& p, const float size, const SampleRenderer::RendererColor& color );
void addCapsule(const PxVec3& p0, const PxVec3& p1, const float radius, const float height, const PxTransform& tr, const SampleRenderer::RendererColor& color, PxU32 renderFlags = RENDER_DEBUG_DEFAULT);
void addCapsule(const PxCapsuleGeometry& cg, const PxTransform& tr, const SampleRenderer::RendererColor& color, PxU32 renderFlags = RENDER_DEBUG_DEFAULT);
void addGeometry(const PxGeometry& geom, const PxTransform& tr, const SampleRenderer::RendererColor& color, PxU32 renderFlags = RENDER_DEBUG_DEFAULT);
void addRectangle(float width, float length, const PxTransform& tr, const SampleRenderer::RendererColor& color);
void addConvex(const PxConvexMeshGeometry& cg, const PxTransform& tr, const SampleRenderer::RendererColor& color, PxU32 renderFlags = RENDER_DEBUG_DEFAULT);
void addArrow(const PxVec3& posA, const PxVec3& posB, const SampleRenderer::RendererColor& color);
void update(const PxRenderBuffer& debugRenderable);
void update(const PxRenderBuffer& debugRenderable, const Camera& camera);
void queueForRender();
void clear();
private:
void addBox(const PxVec3* pts, const SampleRenderer::RendererColor& color, PxU32 renderFlags);
void addCircle(PxU32 nbPts, const PxVec3* pts, const SampleRenderer::RendererColor& color, const PxVec3& offset);
};
#endif

View File

@ -0,0 +1,48 @@
//
// 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 "RenderSphereActor.h"
#include "RendererCapsuleShape.h"
using namespace physx;
using namespace SampleRenderer;
RenderSphereActor::RenderSphereActor(Renderer& renderer, PxReal radius)
{
RendererShape* rs = new RendererCapsuleShape(renderer, 0.0f, radius);
setRenderShape(rs);
}
RenderSphereActor::RenderSphereActor(const RenderSphereActor& src) : RenderBaseActor(src)
{
}
RenderSphereActor::~RenderSphereActor()
{
}

View File

@ -0,0 +1,44 @@
//
// 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 RENDER_SPHERE_ACTOR_H
#define RENDER_SPHERE_ACTOR_H
#include "RenderBaseActor.h"
#include "foundation/PxSimpleTypes.h"
class RenderSphereActor : public RenderBaseActor
{
public:
RenderSphereActor(SampleRenderer::Renderer& renderer, PxReal radius);
RenderSphereActor(const RenderSphereActor&);
virtual ~RenderSphereActor();
};
#endif

View File

@ -0,0 +1,103 @@
//
// 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 "SamplePreprocessor.h"
#include "RendererMemoryMacros.h"
#include "RenderTexture.h"
#include "Renderer.h"
#include "RendererTexture2DDesc.h"
using namespace physx;
using namespace SampleRenderer;
RenderTexture::RenderTexture(Renderer& renderer, PxU32 id, PxU32 width, PxU32 height, const void* data) :
mID (id),
mTexture (NULL),
mOwnsTexture (true)
{
RendererTexture2DDesc tdesc;
tdesc.format = RendererTexture2D::FORMAT_B8G8R8A8;
tdesc.width = width;
tdesc.height = height;
tdesc.numLevels = 1;
/*
tdesc.filter;
tdesc.addressingU;
tdesc.addressingV;
tdesc.renderTarget;
*/
PX_ASSERT(tdesc.isValid());
mTexture = renderer.createTexture2D(tdesc);
PX_ASSERT(mTexture);
const PxU32 componentCount = 4;
if(mTexture)
{
PxU32 pitch = 0;
void* buffer = mTexture->lockLevel(0, pitch);
PX_ASSERT(buffer);
if(buffer)
{
PxU8* levelDst = (PxU8*)buffer;
const PxU8* levelSrc = (PxU8*)data;
const PxU32 levelWidth = mTexture->getWidthInBlocks();
const PxU32 levelHeight = mTexture->getHeightInBlocks();
const PxU32 rowSrcSize = levelWidth * mTexture->getBlockSize();
PX_UNUSED(rowSrcSize);
PX_ASSERT(rowSrcSize <= pitch); // the pitch can't be less than the source row size.
for(PxU32 row=0; row<levelHeight; row++)
{
// copy per pixel to handle RBG case, based on component count
for(PxU32 col=0; col<levelWidth; col++)
{
*levelDst++ = levelSrc[0];
*levelDst++ = levelSrc[1];
*levelDst++ = levelSrc[2];
*levelDst++ = 0xFF; //alpha
levelSrc += componentCount;
}
}
}
mTexture->unlockLevel(0);
}
}
RenderTexture::RenderTexture(Renderer& renderer, PxU32 id, RendererTexture2D* texture) :
mID (id),
mTexture (texture),
mOwnsTexture (false)
{
}
RenderTexture::~RenderTexture()
{
if(mOwnsTexture)
SAFE_RELEASE(mTexture);
}

View File

@ -0,0 +1,55 @@
//
// 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 RENDER_TEXTURE_H
#define RENDER_TEXTURE_H
#include "RenderBaseObject.h"
#include "common/PxPhysXCommonConfig.h"
#include "foundation/PxVec3.h"
#include <RendererTexture2D.h>
namespace SampleRenderer
{
class Renderer;
}
class RenderTexture : public RenderBaseObject
{
public:
RenderTexture(SampleRenderer::Renderer& renderer, PxU32 id, PxU32 width, PxU32 height, const void* data);
RenderTexture(SampleRenderer::Renderer& renderer, PxU32 id, SampleRenderer::RendererTexture2D* texture);
virtual ~RenderTexture();
PxU32 mID;
SampleRenderer::RendererTexture2D* mTexture;
bool mOwnsTexture;
};
#endif

View File

@ -0,0 +1,332 @@
//
// 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 <stdio.h>
#include <assert.h>
#include "SampleAllocator.h"
#include "RendererMemoryMacros.h"
#include "foundation/PxAssert.h"
#include "foundation/PxErrorCallback.h"
#include "PsString.h"
PxErrorCallback& getSampleErrorCallback();
#if defined(WIN32)
// on win32 we only have 8-byte alignment guaranteed, but the CRT provides special aligned allocation
// fns
#include <malloc.h>
#include <crtdbg.h>
static void* platformAlignedAlloc(size_t size)
{
return _aligned_malloc(size, 16);
}
static void platformAlignedFree(void* ptr)
{
_aligned_free(ptr);
}
#elif PX_LINUX_FAMILY
static void* platformAlignedAlloc(size_t size)
{
return ::memalign(16, size);
}
static void platformAlignedFree(void* ptr)
{
::free(ptr);
}
#else
// on Win64 we get 16-byte alignment by default
static void* platformAlignedAlloc(size_t size)
{
void *ptr = ::malloc(size);
PX_ASSERT((reinterpret_cast<size_t>(ptr) & 15)==0);
return ptr;
}
static void platformAlignedFree(void* ptr)
{
::free(ptr);
}
#endif
#define DEBUG_IDENTIFIER 0xBeefBabe
#define DEBUG_DEALLOCATED 0xDeadDead
#define INVALID_ID 0xffffffff
#define MEMBLOCKSTART 64
#if PX_DEBUG || PX_PROFILE
static void print(const char* buffer)
{
shdfnd::printFormatted("%s", buffer);
#if PX_WINDOWS
if(buffer) { _RPT0(_CRT_WARN, buffer); }
#endif
}
#endif
#if PX_DEBUG || PX_PROFILE
struct DebugBlock
{
const char* mFilename;
#if !PX_P64_FAMILY
PxU32 mPad0;
#endif
const char* mHandle;
#if !PX_P64_FAMILY
PxU32 mPadHandle;
#endif
PxU32 mCheckValue;
PxU32 mSize;
PxU32 mSlotIndex;
PxU32 mLine;
};
PX_COMPILE_TIME_ASSERT(!(sizeof(DebugBlock)&15));
#endif
PxSampleAllocator::PxSampleAllocator() :
mMemBlockList (NULL),
mMemBlockListSize (0),
mFirstFree (INVALID_ID),
mMemBlockUsed (0),
mNbAllocatedBytes (0),
mHighWaterMark (0),
mTotalNbAllocs (0),
mNbAllocs (0)
{
#if PX_DEBUG || PX_PROFILE
// Initialize the Memory blocks list (DEBUG mode only)
mMemBlockList = (void**)::malloc(MEMBLOCKSTART*sizeof(void*));
memset(mMemBlockList, 0, MEMBLOCKSTART*sizeof(void*));
mMemBlockListSize = MEMBLOCKSTART;
#endif
}
PxSampleAllocator::~PxSampleAllocator()
{
#if PX_DEBUG || PX_PROFILE
char buffer[4096];
if(mNbAllocatedBytes)
{
sprintf(buffer, "Memory leak detected: %d bytes non released\n", mNbAllocatedBytes);
print(buffer);
}
if(mNbAllocs)
{
sprintf(buffer, "Remaining allocs: %d\n", mNbAllocs);
print(buffer);
}
sprintf(buffer, "Total nb alloc: %d\n", mTotalNbAllocs);
print(buffer);
sprintf(buffer, "High water mark: %d Kb\n", mHighWaterMark/1024);
print(buffer);
// Scanning for memory leaks
if(mMemBlockList && mNbAllocs)
{
PxU32 NbLeaks = 0;
sprintf(buffer, "\n\n SampleAllocator: Memory leaks detected :\n\n");
print(buffer);
for(PxU32 i=0; i<mMemBlockUsed; i++)
{
if(size_t(mMemBlockList[i])&1)
continue;
const DebugBlock* DB = (const DebugBlock*)mMemBlockList[i];
sprintf(buffer, " Address 0x%p, %d bytes, allocated in: %s(%d):\n\n", (void*)(DB+1), DB->mSize, DB->mFilename, DB->mLine);
print(buffer);
NbLeaks++;
}
sprintf(buffer, "\n Dump complete (%d leaks)\n\n", NbLeaks);
print(buffer);
}
// Free the Memory Block list
if(mMemBlockList) ::free(mMemBlockList);
mMemBlockList = NULL;
#endif
}
void* PxSampleAllocator::allocate(size_t size, const char* typeName, const char* filename, int line)
{
if(!size)
return NULL;
#if PX_DEBUG || PX_PROFILE
Ps::MutexT<Ps::RawAllocator>::ScopedLock lock(mMutex);
// Allocate one debug block in front of each real allocation
const size_t neededSize = size + sizeof(DebugBlock);
void* ptr = platformAlignedAlloc(neededSize);
if (NULL != ptr)
{
// Fill debug block
DebugBlock* DB = (DebugBlock*)ptr;
DB->mCheckValue = DEBUG_IDENTIFIER;
DB->mSize = PxU32(size);
DB->mLine = line;
DB->mSlotIndex = INVALID_ID;
DB->mFilename = filename;
DB->mHandle = typeName ? typeName : "";
// Update global stats
mTotalNbAllocs++;
mNbAllocs++;
mNbAllocatedBytes += PxU32(size);
if(mNbAllocatedBytes>mHighWaterMark)
mHighWaterMark = mNbAllocatedBytes;
// Insert the allocated block in the debug memory block list
if(mMemBlockList)
{
if(mFirstFree!=INVALID_ID)
{
// Recycle old location
PxU32 NextFree = (PxU32)(size_t)(mMemBlockList[mFirstFree]);
if(NextFree!=INVALID_ID)
NextFree>>=1;
mMemBlockList[mFirstFree] = ptr;
DB->mSlotIndex = mFirstFree;
mFirstFree = NextFree;
}
else
{
if(mMemBlockUsed==mMemBlockListSize)
{
// Allocate a bigger block
void** tps = (void**)::malloc((mMemBlockListSize+MEMBLOCKSTART)*sizeof(void*));
// Copy already used part
memcpy(tps, mMemBlockList, mMemBlockListSize*sizeof(void*));
// Initialize remaining part
void* Next = tps + mMemBlockListSize;
memset(Next, 0, MEMBLOCKSTART*sizeof(void*));
// Free previous memory, setup new pointer
::free(mMemBlockList);
mMemBlockList = tps;
// Setup new size
mMemBlockListSize += MEMBLOCKSTART;
}
mMemBlockList[mMemBlockUsed] = ptr;
DB->mSlotIndex = mMemBlockUsed++;
}
}
return ((PxU8*)ptr) + sizeof(DebugBlock);
}
#else
void* ptr = platformAlignedAlloc(size);
if (NULL != ptr)
return ptr;
#endif
getSampleErrorCallback().reportError(PxErrorCode::eOUT_OF_MEMORY, "NULL ptr returned\n", __FILE__, __LINE__);
return NULL;
}
void PxSampleAllocator::deallocate(void* memory)
{
if(!memory)
return;
#if PX_DEBUG || PX_PROFILE
Ps::MutexT<Ps::RawAllocator>::ScopedLock lock(mMutex);
DebugBlock* DB = ((DebugBlock*)memory)-1;
// Check we allocated it
if(DB->mCheckValue!=DEBUG_IDENTIFIER)
{
shdfnd::printFormatted("Error: free unknown memory!!\n");
// ### should we really continue??
return;
}
// Update global stats
mNbAllocatedBytes -= DB->mSize;
mNbAllocs--;
// Remove the block from the Memory block list
if(mMemBlockList)
{
PxU32 FreeSlot = DB->mSlotIndex;
assert(mMemBlockList[FreeSlot]==DB);
PxU32 NextFree = mFirstFree;
if(NextFree!=INVALID_ID)
{
NextFree<<=1;
NextFree|=1;
}
mMemBlockList[FreeSlot] = (void*)size_t(NextFree);
mFirstFree = FreeSlot;
}
// ### should be useless since we'll release the memory just afterwards
DB->mCheckValue = DEBUG_DEALLOCATED;
DB->mSize = 0;
DB->mHandle = 0;
DB->mFilename = NULL;
DB->mSlotIndex = INVALID_ID;
DB->mLine = INVALID_ID;
platformAlignedFree(DB);
#else
platformAlignedFree(memory);
#endif
}
static PxSampleAllocator* gAllocator = NULL;
void initSampleAllocator()
{
PX_ASSERT(!gAllocator);
gAllocator = new PxSampleAllocator;
}
void releaseSampleAllocator()
{
DELETESINGLE(gAllocator);
}
PxSampleAllocator* getSampleAllocator()
{
PX_ASSERT(gAllocator);
return gAllocator;
}

View File

@ -0,0 +1,87 @@
//
// 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_ALLOCATOR_H
#define SAMPLE_ALLOCATOR_H
#include "foundation/PxAllocatorCallback.h"
#include "common/PxPhysXCommonConfig.h"
#include "PsMutex.h"
#include "PxTkNamespaceMangle.h"
using namespace physx;
class PxSampleAllocator : public PxAllocatorCallback
{
public:
PxSampleAllocator();
~PxSampleAllocator();
virtual void* allocate(size_t size, const char* typeName, const char* filename, int line);
void* allocate(size_t size, const char* filename, int line) { return allocate(size, NULL, filename, line); }
virtual void deallocate(void* ptr);
protected:
Ps::MutexT<Ps::RawAllocator> mMutex;
void** mMemBlockList;
PxU32 mMemBlockListSize;
PxU32 mFirstFree;
PxU32 mMemBlockUsed;
public:
PxI32 mNbAllocatedBytes;
PxI32 mHighWaterMark;
PxI32 mTotalNbAllocs;
PxI32 mNbAllocs;
};
void initSampleAllocator();
void releaseSampleAllocator();
PxSampleAllocator* getSampleAllocator();
class SampleAllocateable
{
public:
PX_FORCE_INLINE void* operator new (size_t, void* ptr) { return ptr; }
PX_FORCE_INLINE void* operator new (size_t size, const char* handle, const char * filename, int line) { return getSampleAllocator()->allocate(size, handle, filename, line); }
PX_FORCE_INLINE void* operator new[] (size_t size, const char* handle, const char * filename, int line) { return getSampleAllocator()->allocate(size, handle, filename, line); }
PX_FORCE_INLINE void operator delete (void* p) { getSampleAllocator()->deallocate(p); }
PX_FORCE_INLINE void operator delete (void* p, PxU32, const char*, int) { getSampleAllocator()->deallocate(p); }
PX_FORCE_INLINE void operator delete (void* p, const char*, const char *, int) { getSampleAllocator()->deallocate(p); }
PX_FORCE_INLINE void operator delete[] (void* p) { getSampleAllocator()->deallocate(p); }
PX_FORCE_INLINE void operator delete[] (void* p, PxU32, const char*, int) { getSampleAllocator()->deallocate(p); }
PX_FORCE_INLINE void operator delete[] (void* p, const char*, const char *, int) { getSampleAllocator()->deallocate(p); }
};
#define SAMPLE_ALLOC(x) getSampleAllocator()->allocate(x, 0, __FILE__, __LINE__)
#define SAMPLE_FREE(x) if(x) { getSampleAllocator()->deallocate(x); x = NULL; }
#define SAMPLE_NEW(x) new(#x, __FILE__, __LINE__) x
#endif

View File

@ -0,0 +1,47 @@
//
// 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_ALLOCATOR_SDK_CLASSES_H
#define SAMPLE_ALLOCATOR_SDK_CLASSES_H
#include "SampleAllocator.h"
#include "foundation/PxVec3.h"
#include "PsSync.h"
#include "geometry/PxBoxGeometry.h"
#include "RendererColor.h"
#include "vehicle/PxVehicleSDK.h"
// PT: this is used to allocate SDK classes through the SampleAllocator
class PxVec3Alloc : public PxVec3, public SampleAllocateable { public: };
class PsSyncAlloc : public Ps::Sync, public SampleAllocateable { public: };
class PxBoxGeometryAlloc : public PxBoxGeometry, public SampleAllocateable { public: };
class RendererColorAlloc : public SampleRenderer::RendererColor, public SampleAllocateable { public: };
#endif

View File

@ -0,0 +1,51 @@
//
// 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_ARRAY
#define SAMPLE_ARRAY
#include "PsArray.h"
#include "PsInlineArray.h"
#include "PsHashMap.h"
#include "PsAllocator.h"
#include "Test.h"
template<typename T>
class SampleArray : public Ps::Array<T, Ps::RawAllocator>
{
public:
PX_INLINE explicit SampleArray() : Ps::Array<T, Ps::RawAllocator>() {}
PX_INLINE explicit SampleArray(PxU32 size, const T& a = T()) : Ps::Array<T, Ps::RawAllocator>(size, a) {}
};
template<typename T, PxU32 N>
class SampleInlineArray : public Ps::InlineArray<T, N, Ps::RawAllocator> {};
#endif

View File

@ -0,0 +1,93 @@
//
// 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_BASE_INPUT_EVENT_IDS_H
#define SAMPLE_BASE_INPUT_EVENT_IDS_H
#include <SampleFrameworkInputEventIds.h>
// InputEvents used by SampleBase
enum SampleBaseInputEventIds
{
SAMPLE_BASE_FIRST = NUM_SAMPLE_FRAMEWORK_INPUT_EVENT_IDS,
PICKUP ,
SPAWN_DEBUG_OBJECT ,
PAUSE_SAMPLE ,
STEP_ONE_FRAME ,
TOGGLE_VISUALIZATION ,
DECREASE_DEBUG_RENDER_SCALE ,
INCREASE_DEBUG_RENDER_SCALE ,
HIDE_GRAPHICS ,
WIREFRAME ,
TOGGLE_PVD_CONNECTION ,
SHOW_HELP ,
SHOW_DESCRIPTION ,
SHOW_EXTENDED_HELP ,
VARIABLE_TIMESTEP,
DELETE_PICKED,
QUIT,
MENU_VISUALIZATIONS,
MENU_SAMPLES,
MENU_ESCAPE,
MENU_UP,
MENU_DOWN,
MENU_LEFT,
MENU_RIGHT,
MENU_SELECT,
MENU_QUICK_UP,
MENU_QUICK_DOWN,
MENU_QUICK_LEFT,
MENU_QUICK_RIGHT,
MOUSE_LOOK_BUTTON,
CONSOLE_OPEN,
CONSOLE_ESCAPE,
CONSOLE_BACKSPACE,
CONSOLE_ENTER,
CONSOLE_SCROLL_UP,
CONSOLE_SCROLL_DOWN,
CONSOLE_LIST_COMMAND_UP,
CONSOLE_LIST_COMMAND_DOWN,
NEXT_PAGE,
PREVIOUS_PAGE,
RUN_NEXT_SAMPLE,
RUN_PREVIOUS_SAMPLE,
PROFILE_ONLY_PVD,
NUM_SAMPLE_BASE_INPUT_EVENT_IDS,
};
#endif

View File

@ -0,0 +1,481 @@
//
// 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 "SampleCamera.h"
#include "SampleUtils.h"
#include "RenderPhysX3Debug.h"
#include "RendererColor.h"
using namespace SampleRenderer;
// PT: the base camera code should be the same for all cameras, regardless of how
// the camera is controlled. For example this should deal with VFC, etc.
Camera::Camera() :
mProjMatrix (degtorad(45.0f), 1.0f, 1.0f, 100.0f),
mFOV (0.0f),
mNearPlane (0.0f),
mFarPlane (0.0f),
mDirtyProj (true),
mDirtyView (true)
{
mViewMatrix = PxTransform(PxIdentity);
mPos = PxVec3(0);
mRot = PxVec3(0);
mDrawDebugData = false;
mFreezeFrustum = false;
mPerformVFC = true;
}
Camera::~Camera()
{
}
// PT: TODO: copied from SampleApplication. Refactor.
static PxMat33 EulerToMat33(const PxVec3 &e)
{
float c1 = cosf(e.z);
float s1 = sinf(e.z);
float c2 = cosf(e.y);
float s2 = sinf(e.y);
float c3 = cosf(e.x);
float s3 = sinf(e.x);
PxMat33 m(PxVec3(c1*c2, -s1*c2, s2),
PxVec3((s1*c3)+(c1*s2*s3), (c1*c3)-(s1*s2*s3),-c2*s3),
PxVec3((s1*s3)-(c1*s2*c3), (c1*s3)+(s1*s2*c3), c2*c3));
return m;
}
void Camera::updateInternals()
{
if(mDirtyProj)
{
mDirtyProj = false;
mProjMatrix = RendererProjection(degtorad(mFOV), mViewport.computeRatio(), mNearPlane, mFarPlane);
}
if(mDirtyView)
{
mDirtyView = false;
mViewMatrix.q = PxQuat(EulerToMat33(mRot));
mViewMatrix.p = mPos;
}
}
PxVec3 Camera::getViewDir() const
{
const PxTransform& camPose = getViewMatrix();
PxVec3 forward = PxMat33(camPose.q)[2];
return -forward;
}
void Camera::lookAt(const PxVec3& position, const PxVec3& target)
{
PxVec3 dir, right, up;
Ps::computeBasis(position, target, dir, right, up);
PxTransform view;
view.p = position;
view.q = PxQuat(PxMat33(-right, up, -dir));
setView(view);
}
enum FrustumPlaneIndex
{
FRUSTUM_PLANE_LEFT = 0, //!< Left clipping plane
FRUSTUM_PLANE_RIGHT = 1, //!< Right clipping plane
FRUSTUM_PLANE_TOP = 2, //!< Top clipping plane
FRUSTUM_PLANE_BOTTOM = 3, //!< Bottom clipping plane
FRUSTUM_PLANE_NEAR = 4, //!< Near clipping plane
FRUSTUM_PLANE_FAR = 5, //!< Far clipping plane (must be last for infinite far clip)
FRUSTUM_PLANE_FORCE_DWORD = 0x7fffffff
};
static PxMat44 convertViewMatrix(const PxTransform& eye)
{
PxTransform viewMatrix = eye.getInverse();
PxMat44 mat44 = PxMat44(viewMatrix).getTranspose();
float m[16];
memcpy(m, mat44.front(), sizeof m);
PxMat44 view44;
view44.column0.x = m[0];
view44.column0.y = m[1];
view44.column0.z = m[2];
view44.column0.w = m[3];
view44.column1.x = m[4];
view44.column1.y = m[5];
view44.column1.z = m[6];
view44.column1.w = m[7];
view44.column2.x = m[8];
view44.column2.y = m[9];
view44.column2.z = m[10];
view44.column2.w = m[11];
view44.column3.x = m[12];
view44.column3.y = m[13];
view44.column3.z = m[14];
view44.column3.w = m[15];
PxMat44 tmpmat = view44.getTranspose(); view44 = tmpmat;
return view44;
}
static PxMat44 convertProjMatrix(const RendererProjection& proj)
{
float renderProjMatrix[16];
proj.getColumnMajor44(renderProjMatrix);
PxMat44 proj44;
proj44.column0.x = renderProjMatrix[0];
proj44.column0.y = renderProjMatrix[1];
proj44.column0.z = renderProjMatrix[2];
proj44.column0.w = renderProjMatrix[3];
proj44.column1.x = renderProjMatrix[4];
proj44.column1.y = renderProjMatrix[5];
proj44.column1.z = renderProjMatrix[6];
proj44.column1.w = renderProjMatrix[7];
proj44.column2.x = renderProjMatrix[8];
proj44.column2.y = renderProjMatrix[9];
proj44.column2.z = renderProjMatrix[10];
proj44.column2.w = renderProjMatrix[11];
proj44.column3.x = renderProjMatrix[12];
proj44.column3.y = renderProjMatrix[13];
proj44.column3.z = renderProjMatrix[14];
proj44.column3.w = renderProjMatrix[15];
//PxMat44 tmpmat = proj44.getTranspose(); proj44 = tmpmat;
return proj44;
}
void Camera::BuildFrustum()
{
if(mFreezeFrustum)
return;
// PT: a better way is to extract the planes from the view-proj matrix but it has some subtle differences with D3D/GL.
// Building the frustum explicitly is just easier here (although not as efficient)
const PxReal ratio = mViewport.computeRatio();
const PxReal Tan = tanf(degtorad(0.5f * mFOV)) / ratio;
const PxReal nearCoeff = mNearPlane * Tan;
const PxReal farCoeff = mFarPlane * Tan;
const PxReal rightCoeff = ratio;
const PxReal upCoeff = 1.0f;
const PxTransform& view = getViewMatrix();
PxMat33 mat33(view.q);
PxVec3 right = mat33[0];
PxVec3 up = mat33[1];
PxVec3 forward =-mat33[2];
mFrustum[0] = mPos + forward*mNearPlane - right*nearCoeff*rightCoeff + up*nearCoeff*upCoeff;
mFrustum[1] = mPos + forward*mNearPlane - right*nearCoeff*rightCoeff - up*nearCoeff*upCoeff;
mFrustum[2] = mPos + forward*mNearPlane + right*nearCoeff*rightCoeff - up*nearCoeff*upCoeff;
mFrustum[3] = mPos + forward*mNearPlane + right*nearCoeff*rightCoeff + up*nearCoeff*upCoeff;
mFrustum[4] = mPos + forward*mFarPlane - right*farCoeff*rightCoeff + up*farCoeff*upCoeff;
mFrustum[5] = mPos + forward*mFarPlane - right*farCoeff*rightCoeff - up*farCoeff*upCoeff;
mFrustum[6] = mPos + forward*mFarPlane + right*farCoeff*rightCoeff - up*farCoeff*upCoeff;
mFrustum[7] = mPos + forward*mFarPlane + right*farCoeff*rightCoeff + up*farCoeff*upCoeff;
if(1)
{
mPlanes[0] = PxPlane(mFrustum[4], mFrustum[1], mFrustum[5]);
mPlanes[1] = PxPlane(mFrustum[6], mFrustum[3], mFrustum[7]);
mPlanes[2] = PxPlane(mFrustum[4], mFrustum[7], mFrustum[3]);
mPlanes[3] = PxPlane(mFrustum[1], mFrustum[6], mFrustum[5]);
mPlanes[4] = PxPlane(mFrustum[0], mFrustum[2], mFrustum[1]);
mPlanes[5] = PxPlane(mFrustum[5], mFrustum[7], mFrustum[4]);
{
for(int i=0;i<6;i++)
{
mPlanes[i].n = -mPlanes[i].n;
mPlanes[i].d = -mPlanes[i].d;
}
}
}
if(0)
{
//
const PxVec3 axisX(1.0f, 0.0f, 0.0f);
const PxVec3 axisY(0.0f, 1.0f, 0.0f);
const PxVec3 axisZ(0.0f, 0.0f, 1.0f);
PxQuat RotX(degtorad(0.5f * mFOV), axisX);
PxQuat RotY(degtorad(0.5f * mFOV), axisY);
PxQuat RotZ(degtorad(0.5f * mFOV), axisZ);
PxVec3 tmp1 = RotY.rotate(-axisX);
PxVec3 tmp11 = view.q.rotate(tmp1); // Plane0
mPlanes[0].n = tmp11;
mPlanes[0].d = - mPos.dot(mPlanes[0].n);
//
RotY = PxQuat(-degtorad(0.5f * mFOV), axisY);
PxVec3 tmpy = RotY.rotate(axisX);
PxVec3 tmpyy = view.q.rotate(tmpy); // Plane1
mPlanes[1].n = tmpyy;
mPlanes[1].d = - mPos.dot(mPlanes[1].n);
//
RotX = PxQuat(degtorad(0.5f * mFOV)/ratio, axisX);
PxVec3 tmpx = RotX.rotate(axisY);
PxVec3 tmpxx = view.q.rotate(tmpx); // Plane2?
mPlanes[2].n = tmpxx;
mPlanes[2].d = - mPos.dot(mPlanes[2].n);
//
RotX = PxQuat(-degtorad(0.5f * mFOV)/ratio, axisX);
tmpx = RotX.rotate(axisY);
tmpxx = view.q.rotate(tmpx); // -Plane3?
mPlanes[3].n = -tmpxx;
mPlanes[3].d = - mPos.dot(mPlanes[3].n);
//
mPlanes[4].n = -forward;
mPlanes[4].d = - (mPos.dot(mPlanes[4].n) + forward.dot(mPlanes[4].n)*mNearPlane);
mPlanes[5].n = forward;
mPlanes[5].d = - (mPos.dot(mPlanes[5].n) + forward.dot(mPlanes[5].n)*mFarPlane);
}
if(0)
{
PxMat44 proj44 = convertProjMatrix(mProjMatrix);
PxMat44 view44 = convertViewMatrix(view);
// PxMat44 combo44 = view44 * proj44;
PxMat44 combo44 = proj44 * view44;
PxReal combo[4][4];
PxReal* dst = &combo[0][0];
memcpy(dst, &combo44, sizeof(PxReal)*16);
// D3D:
// -w' < x' < w'
// -w' < y' < w'
// 0 < z' < w'
//
// GL:
// -w' < x' < w'
// -w' < y' < w'
// -w' < z' < w'
// Left clipping plane
mPlanes[FRUSTUM_PLANE_LEFT].n.x = -(combo[0][3] + combo[0][0]);
mPlanes[FRUSTUM_PLANE_LEFT].n.y = -(combo[1][3] + combo[1][0]);
mPlanes[FRUSTUM_PLANE_LEFT].n.z = -(combo[2][3] + combo[2][0]);
mPlanes[FRUSTUM_PLANE_LEFT].d = -(combo[3][3] + combo[3][0]);
// Right clipping plane
mPlanes[FRUSTUM_PLANE_RIGHT].n.x = -(combo[0][3] - combo[0][0]);
mPlanes[FRUSTUM_PLANE_RIGHT].n.y = -(combo[1][3] - combo[1][0]);
mPlanes[FRUSTUM_PLANE_RIGHT].n.z = -(combo[2][3] - combo[2][0]);
mPlanes[FRUSTUM_PLANE_RIGHT].d = -(combo[3][3] - combo[3][0]);
// Top clipping plane
mPlanes[FRUSTUM_PLANE_TOP].n.x = -(combo[0][3] - combo[0][1]);
mPlanes[FRUSTUM_PLANE_TOP].n.y = -(combo[1][3] - combo[1][1]);
mPlanes[FRUSTUM_PLANE_TOP].n.z = -(combo[2][3] - combo[2][1]);
mPlanes[FRUSTUM_PLANE_TOP].d = -(combo[3][3] - combo[3][1]);
// Bottom clipping plane
mPlanes[FRUSTUM_PLANE_BOTTOM].n.x = -(combo[0][3] + combo[0][1]);
mPlanes[FRUSTUM_PLANE_BOTTOM].n.y = -(combo[1][3] + combo[1][1]);
mPlanes[FRUSTUM_PLANE_BOTTOM].n.z = -(combo[2][3] + combo[2][1]);
mPlanes[FRUSTUM_PLANE_BOTTOM].d = -(combo[3][3] + combo[3][1]);
// Near clipping plane
if(1)
{
// OpenGL path
mPlanes[FRUSTUM_PLANE_NEAR].n.x = -(combo[0][3] + combo[0][2]);
mPlanes[FRUSTUM_PLANE_NEAR].n.y = -(combo[1][3] + combo[1][2]);
mPlanes[FRUSTUM_PLANE_NEAR].n.z = -(combo[2][3] + combo[2][2]);
mPlanes[FRUSTUM_PLANE_NEAR].d = -(combo[3][3] + combo[3][2]);
}
else
{
// D3D path
mPlanes[FRUSTUM_PLANE_NEAR].n.x = - combo[0][2];
mPlanes[FRUSTUM_PLANE_NEAR].n.y = - combo[1][2];
mPlanes[FRUSTUM_PLANE_NEAR].n.z = - combo[2][2];
mPlanes[FRUSTUM_PLANE_NEAR].d = - combo[3][2];
}
// Far clipping plane (must be last for infinite far clip)
mPlanes[FRUSTUM_PLANE_FAR].n.x = -(combo[0][3] - combo[0][2]);
mPlanes[FRUSTUM_PLANE_FAR].n.y = -(combo[1][3] - combo[1][2]);
mPlanes[FRUSTUM_PLANE_FAR].n.z = -(combo[2][3] - combo[2][2]);
mPlanes[FRUSTUM_PLANE_FAR].d = -(combo[3][3] - combo[3][2]);
// Normalize if needed
for(PxU32 i=0;i<6;i++)
{
// mPlanes[i].normalize();
mPlanes[i].n.normalize();
// mPlanes[i].normal = -mPlanes[i].normal;
// mPlanes[i].d = -mPlanes[i].d;
mPlanes[i].d *= 0.5f;
}
}
}
// Following code from Umbra/dPVS.
//------------------------------------------------------------------------
//
// Function: DPVS::intersectAABBFrustum()
//
// Description: Determines whether an AABB intersects a frustum
//
// Parameters: a = reference to AABB (defined by minimum & maximum vectors)
// p = array of pre-normalized clipping planes
// outClipMask = output clip mask (if function returns 'true')
// inClipMask = input clip mask (indicates which planes are active)
//
// Returns: true if AABB intersects the frustum, false otherwise
//
// Intersection of AABB and a frustum. The frustum may
// contain 0-32 planes (active planes are defined by inClipMask).
// If AABB intersects the frustum, an output clip mask is returned
// as well (indicating which planes are crossed by the AABB). This
// information can be used to optimize testing of child nodes or
// objects inside the nodes (pass value as 'inClipMask' next time).
//
// This is a variant of the classic "fast" AABB/frustum
// intersection tester. AABBs that are not culled away by any single
// plane are classified as "intersecting" even though the AABB may
// actually be outside the convex volume formed by the planes.
//------------------------------------------------------------------------
static PX_FORCE_INLINE bool planesAABBOverlap(const PxBounds3& a, const PxPlane* p, PxU32& out_clip_mask, PxU32 in_clip_mask)
{
//------------------------------------------------------------------------
// Convert the AABB from (minimum,maximum) form into (center,half-diagonal).
// Note that we could get rid of these six subtractions and three
// multiplications if the AABB was originally expressed in (center,
// half-diagonal) form.
//------------------------------------------------------------------------
PxVec3 m = a.getCenter(); // get center of AABB ((minimum+maximum)*0.5f)
PxVec3 d = a.maximum; d-=m; // get positive half-diagonal (maximum - center)
//------------------------------------------------------------------------
// Evaluate through all active frustum planes. We determine the relation
// between the AABB and a plane by using the concept of "near" and "far"
// vertices originally described by Zhang (and later by Moeller). Our
// variant here uses 3 fabs ops, 6 muls, 7 adds and two floating point
// comparisons per plane. The routine early-exits if the AABB is found
// to be outside any of the planes. The loop also constructs a new output
// clip mask. Most FPUs have a native single-cycle fabsf() operation.
//------------------------------------------------------------------------
PxU32 Mask = 1; // current mask index (1,2,4,8,..)
PxU32 TmpOutClipMask = 0; // initialize output clip mask into empty.
while(Mask<=in_clip_mask) // keep looping while we have active planes left...
{
if(in_clip_mask & Mask) // if clip plane is active, process it..
{
const float NP = d.x*PxAbs(p->n.x) + d.y*PxAbs(p->n.y) + d.z*PxAbs(p->n.z);
const float MP = m.x*p->n.x + m.y*p->n.y + m.z*p->n.z + p->d;
if(NP < MP) // near vertex behind the clip plane...
return false; // .. so there is no intersection..
if((-NP) < MP) // near and far vertices on different sides of plane..
TmpOutClipMask |= Mask; // .. so update the clip mask...
}
Mask+=Mask; // mk = (1<<plane)
p++; // advance to next plane
}
out_clip_mask = TmpOutClipMask; // copy output value (temp used to resolve aliasing!)
return true; // indicate that AABB intersects frustum
}
PlaneAABBCode Camera::cull(const PxBounds3& aabb) const
{
const PxU32 nbFrustumPlanes = 6; // PT: can sometimes be 5 with infinite far clip plane
const PxU32 frustumPlanesMask = (1<<nbFrustumPlanes)-1;
PxU32 outClipMask;
if(!planesAABBOverlap(aabb, mPlanes, outClipMask, frustumPlanesMask))
return PLANEAABB_EXCLUSION;
if(outClipMask)
return PLANEAABB_INTERSECT;
return PLANEAABB_INCLUSION;
}
void Camera::drawDebug(RenderPhysX3Debug* debug)
{
if(mDrawDebugData)
{
/* for(PxU32 i=0;i<8;i++)
{
debug->addLine(mFrustum[i], mFrustum[i]+PxVec3(1,0,0), RendererColor(255,0,0));
debug->addLine(mFrustum[i], mFrustum[i]+PxVec3(0,1,0), RendererColor(0, 255,0));
debug->addLine(mFrustum[i], mFrustum[i]+PxVec3(0,0,1), RendererColor(0, 0, 255));
}*/
const RendererColor lineColor(255, 255, 0);
debug->addLine(mFrustum[0], mFrustum[1], lineColor);
debug->addLine(mFrustum[1], mFrustum[2], lineColor);
debug->addLine(mFrustum[2], mFrustum[3], lineColor);
debug->addLine(mFrustum[3], mFrustum[0], lineColor);
debug->addLine(mFrustum[4], mFrustum[5], lineColor);
debug->addLine(mFrustum[5], mFrustum[6], lineColor);
debug->addLine(mFrustum[6], mFrustum[7], lineColor);
debug->addLine(mFrustum[7], mFrustum[4], lineColor);
debug->addLine(mFrustum[0], mFrustum[4], lineColor);
debug->addLine(mFrustum[3], mFrustum[7], lineColor);
debug->addLine(mFrustum[1], mFrustum[5], lineColor);
debug->addLine(mFrustum[6], mFrustum[2], lineColor);
}
}

View File

@ -0,0 +1,157 @@
//
// 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_CAMERA_H
#define SAMPLE_CAMERA_H
#include "SampleAllocator.h"
#include "RendererProjection.h"
#include "foundation/PxPlane.h"
class RenderPhysX3Debug;
struct Viewport : public SampleAllocateable
{
Viewport() : mClientWidth(0), mClientHeight(0), mWindowWidth(0), mWindowHeight(0) {}
PxU32 mClientWidth;
PxU32 mClientHeight;
PxU32 mWindowWidth;
PxU32 mWindowHeight;
PX_FORCE_INLINE PxReal computeRatio() const { return PxReal(mWindowWidth)/PxReal(mWindowHeight); }
};
enum PlaneAABBCode
{
PLANEAABB_EXCLUSION,
PLANEAABB_INTERSECT,
PLANEAABB_INCLUSION
};
class Camera : public SampleAllocateable
{
public:
Camera();
~Camera();
///////////////////////////////////////////////////////////////////////////////
// Projection part
PX_FORCE_INLINE PxReal getFOV() const { return mFOV; }
PX_FORCE_INLINE PxReal getNearPlane() const { return mNearPlane; }
PX_FORCE_INLINE PxReal getFarPlane() const { return mFarPlane; }
PX_FORCE_INLINE PxU32 getScreenWidth() const { return mViewport.mClientWidth; }
PX_FORCE_INLINE PxU32 getScreenHeight() const { return mViewport.mClientHeight; }
PX_FORCE_INLINE void setFOV(PxReal fov) { mFOV = fov; mDirtyProj = true; }
PX_FORCE_INLINE void setNearPlane(PxReal d) { mNearPlane = d; mDirtyProj = true; }
PX_FORCE_INLINE void setFarPlane(PxReal d) { mFarPlane = d; mDirtyProj = true; }
PX_FORCE_INLINE void setScreenSize(PxU32 clientWidth, PxU32 clientHeight, PxU32 windowWidth, PxU32 windowHeight)
{
mViewport.mClientWidth = clientWidth;
mViewport.mClientHeight = clientHeight;
mViewport.mWindowWidth = windowWidth;
mViewport.mWindowHeight = windowHeight;
mDirtyProj = true;
}
PX_FORCE_INLINE const SampleRenderer::RendererProjection&
getProjMatrix() const
{
if(mDirtyProj)
const_cast<Camera*>(this)->updateInternals();
return mProjMatrix;
}
///////////////////////////////////////////////////////////////////////////////
// View part
PX_FORCE_INLINE const PxVec3& getPos() const { return mPos; }
PX_FORCE_INLINE const PxVec3& getRot() const { return mRot; }
PX_FORCE_INLINE void setPos(const PxVec3& pos) { mPos = pos; mDirtyView = true; }
PX_FORCE_INLINE void setRot(const PxVec3& rot) { mRot = rot; mDirtyView = true; }
PX_FORCE_INLINE void setView(const PxTransform& view) { mViewMatrix = view; mPos = view.p; mDirtyView = false; }
PX_FORCE_INLINE const PxTransform& getViewMatrix() const
{
if(mDirtyView)
const_cast<Camera*>(this)->updateInternals();
return mViewMatrix;
}
PxVec3 getViewDir() const;
void lookAt(const PxVec3& position, const PxVec3& target);
///////////////////////////////////////////////////////////////////////////////
PX_FORCE_INLINE const PxVec3* getFrustumVerts() const { return mFrustum; }
///////////////////////////////////////////////////////////////////////////////
// Culling
PlaneAABBCode cull(const PxBounds3& aabb) const;
bool mDrawDebugData;
bool mFreezeFrustum;
bool mPerformVFC;
///////////////////////////////////////////////////////////////////////////////
void drawDebug(RenderPhysX3Debug*);
private:
mutable SampleRenderer::RendererProjection
mProjMatrix;
mutable PxTransform mViewMatrix;
PxVec3 mPos;
PxVec3 mRot;
Viewport mViewport;
PxReal mFOV;
PxReal mNearPlane;
PxReal mFarPlane;
PxVec3 mFrustum[8]; //!< Frustum's vertices
PxPlane mPlanes[6]; //!< Frustum's planes
bool mDirtyProj;
bool mDirtyView;
void updateInternals();
public:
void BuildFrustum();
};
#endif

View File

@ -0,0 +1,274 @@
//
// 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 "SamplePreprocessor.h"
#include "SampleCameraController.h"
#include "SampleCamera.h"
#include "SampleApplication.h"
#include "SamplePlatform.h"
#include "PsUtilities.h"
#include "SampleBaseInputEventIds.h"
#include <SampleFrameworkInputEventIds.h>
#include "SampleUserInputDefines.h"
#include <SampleUserInputIds.h>
using namespace physx;
using namespace SampleRenderer;
using namespace SampleFramework;
// PT: this replicates the default SampleApplication behaviour, but with a much better design. We
// want to be able to isolate & replace the camera controlling code easily.
static const float g_smoothCamBaseVel = 6.0f;
static const float g_smoothCamPosLerp = 0.4f;
static const float g_smoothCamFastMul = 4.0f;
static const float g_smoothCamRotSpeed = 0.005f;
static const float g_smoothCamRotLerp = 0.4f;
static PxReal gGamepadYawInc = 0.0f;
static PxReal gGamepadPitchInc = 0.0f;
static PxReal gGamepadForwardInc = 0.0f;
static PxReal gGamepadLateralInc = 0.0f;
static PxVec3 QuatToEuler(const PxQuat& q)
{
PxVec3 dir = -PxMat33(q)[2];
PxReal r = PxSqrt(dir.x * dir.x + dir.z * dir.z);
PxVec3 rot(0.0f, PxHalfPi, 0.0f);
if (r != 0.0f)
{
rot.x = -PxAtan(dir.y / r);
rot.y = PxAsin(dir.x / r);
if (dir.z > 0.0f)
rot.y = PxPi - rot.y;
}
return rot;
}
///////////////////////////////////////////////////////////////////////////////
DefaultCameraController::DefaultCameraController() :
mMouseButtonDown (false),
mKeyFWDown (false),
mKeyBKDown (false),
mKeyRTDown (false),
mKeyLTDown (false),
mKeyUpDown (false),
mKeyDownDown (false),
mKeyShiftDown (false),
mCameraSpeed (0.f),
mCameraSpeedMultiplier (1.f),
mMouseLookOnMB (true),
mMouseSensitivity (1.f)
{
mTargetEyePos = PxVec3(0);
mTargetEyeRot = PxVec3(0);
mEyePos = PxVec3(0);
mEyeRot = PxVec3(0);
}
DefaultCameraController::~DefaultCameraController()
{
}
///////////////////////////////////////////////////////////////////////////////
void DefaultCameraController::init(const PxVec3& pos, const PxVec3& rot)
{
mTargetEyePos = mEyePos = pos;
mTargetEyeRot = mEyeRot = rot;
}
void DefaultCameraController::init(const PxTransform& pose)
{
init(pose.p, QuatToEuler(pose.q));
}
void DefaultCameraController::onPointerInputEvent(const InputEvent& ie, physx::PxU32 x, physx::PxU32 y, physx::PxReal dx, physx::PxReal dy, bool val)
{
switch (ie.m_Id)
{
case CAMERA_MOUSE_LOOK:
{
if (!mMouseLookOnMB || mMouseButtonDown)
onMouseDelta(static_cast<physx::PxI32>(dx), static_cast<physx::PxI32>(dy));
}
break;
case MOUSE_LOOK_BUTTON:
{
mMouseButtonDown = val;
}
break;
}
}
void DefaultCameraController::onMouseDelta(PxI32 dx, PxI32 dy)
{
mTargetEyeRot.x -= dy * mMouseSensitivity * g_smoothCamRotSpeed;
mTargetEyeRot.y += dx * mMouseSensitivity * g_smoothCamRotSpeed;
}
void DefaultCameraController::collectInputEvents(std::vector<const 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_UP, SCAN_CODE_UP, SCAN_CODE_UP, SCAN_CODE_UP );
DIGITAL_INPUT_EVENT_DEF(CAMERA_MOVE_DOWN, SCAN_CODE_DOWN, SCAN_CODE_DOWN, SCAN_CODE_DOWN );
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 );
DIGITAL_INPUT_EVENT_DEF(CAMERA_SPEED_INCREASE, WKEY_ADD, OSXKEY_ADD, LINUXKEY_ADD );
DIGITAL_INPUT_EVENT_DEF(CAMERA_SPEED_DECREASE, WKEY_SUBTRACT, OSXKEY_SUBTRACT, LINUXKEY_SUBTRACT );
//digital mouse events
DIGITAL_INPUT_EVENT_DEF(MOUSE_LOOK_BUTTON, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_LEFT, LINUXKEY_UNKNOWN );
//digital gamepad events
DIGITAL_INPUT_EVENT_DEF(CAMERA_SPEED_INCREASE, GAMEPAD_LEFT_STICK, OSXKEY_UNKNOWN, LINUXKEY_UNKNOWN );
DIGITAL_INPUT_EVENT_DEF(CAMERA_SPEED_DECREASE, GAMEPAD_RIGHT_STICK, OSXKEY_UNKNOWN, LINUXKEY_UNKNOWN );
//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 DefaultCameraController::onDigitalInputEvent(const SampleFramework::InputEvent& ie, bool val)
{
if(val)
{
if(ie.m_Id == CAMERA_MOVE_FORWARD) mKeyFWDown = true;
else if(ie.m_Id == CAMERA_MOVE_UP) mKeyUpDown = true;
else if(ie.m_Id == CAMERA_MOVE_BACKWARD) mKeyBKDown = true;
else if(ie.m_Id == CAMERA_MOVE_LEFT) mKeyLTDown = true;
else if(ie.m_Id == CAMERA_MOVE_RIGHT) mKeyRTDown = true;
else if(ie.m_Id == CAMERA_SHIFT_SPEED) mKeyShiftDown = true;
else if(ie.m_Id == CAMERA_MOVE_DOWN) mKeyDownDown = true;
else if(ie.m_Id == CAMERA_SPEED_DECREASE) mCameraSpeedMultiplier *= 0.5f;
else if(ie.m_Id == CAMERA_SPEED_INCREASE) mCameraSpeedMultiplier *= 2.0f;
}
else
{
if(ie.m_Id == CAMERA_MOVE_FORWARD) mKeyFWDown = false;
else if(ie.m_Id == CAMERA_MOVE_UP) mKeyUpDown = false;
else if(ie.m_Id == CAMERA_MOVE_BACKWARD) mKeyBKDown = false;
else if(ie.m_Id == CAMERA_MOVE_LEFT) mKeyLTDown = false;
else if(ie.m_Id == CAMERA_MOVE_RIGHT) mKeyRTDown = false;
else if(ie.m_Id == CAMERA_SHIFT_SPEED) mKeyShiftDown = false;
else if(ie.m_Id == CAMERA_MOVE_DOWN) mKeyDownDown = false;
}
}
static PX_FORCE_INLINE PxReal remapAxisValue(PxReal absolutePosition)
{
return absolutePosition * absolutePosition * absolutePosition * 5.0f;
}
void DefaultCameraController::onAnalogInputEvent(const SampleFramework::InputEvent& ie, float val)
{
if(ie.m_Id == CAMERA_GAMEPAD_ROTATE_LEFT_RIGHT)
{
gGamepadYawInc = remapAxisValue(val);
}
else if(ie.m_Id == CAMERA_GAMEPAD_ROTATE_UP_DOWN)
{
gGamepadPitchInc = - remapAxisValue(val);
}
else if(ie.m_Id == CAMERA_GAMEPAD_MOVE_LEFT_RIGHT)
{
gGamepadLateralInc = - val;
}
else if(ie.m_Id == CAMERA_GAMEPAD_MOVE_FORWARD_BACK)
{
gGamepadForwardInc = val;
}
}
///////////////////////////////////////////////////////////////////////////////
// PT: TODO: refactor this
static PxMat33 EulerToMat33(const PxVec3 &e)
{
float c1 = cosf(e.z);
float s1 = sinf(e.z);
float c2 = cosf(e.y);
float s2 = sinf(e.y);
float c3 = cosf(e.x);
float s3 = sinf(e.x);
PxMat33 m(PxVec3(c1*c2, -s1*c2, s2),
PxVec3((s1*c3)+(c1*s2*s3), (c1*c3)-(s1*s2*s3),-c2*s3),
PxVec3((s1*s3)-(c1*s2*c3), (c1*s3)+(s1*s2*c3), c2*c3));
return m;
}
void DefaultCameraController::update(Camera& camera, PxReal dtime)
{
// PT: copied from SampleApplication::onMouseMove
const float eyeCap = 1.5f;
mTargetEyeRot.x += gGamepadPitchInc * dtime;
mTargetEyeRot.y += gGamepadYawInc * dtime;
if(mTargetEyeRot.x > eyeCap) mTargetEyeRot.x = eyeCap;
if(mTargetEyeRot.x < -eyeCap) mTargetEyeRot.x = -eyeCap;
mEyeRot += (mTargetEyeRot - mEyeRot) * g_smoothCamRotLerp;
const PxMat33 tmp = EulerToMat33(mEyeRot);
const PxVec3 forward = -tmp[2];
const PxVec3 right = -tmp[0];
const PxReal padEyeSpeed = mCameraSpeed == 0.f ? g_smoothCamBaseVel * mCameraSpeedMultiplier * dtime * g_smoothCamFastMul : mCameraSpeed;
mTargetEyePos += forward * padEyeSpeed * gGamepadForwardInc;
mTargetEyePos += right * padEyeSpeed * gGamepadLateralInc;
const PxReal keyEyeSpeed = mCameraSpeed == 0.f ? g_smoothCamBaseVel * mCameraSpeedMultiplier * dtime * (mKeyShiftDown ? g_smoothCamFastMul : 1.0f) : mCameraSpeed;
if(mKeyFWDown) mTargetEyePos -= tmp[2] * keyEyeSpeed;
if(mKeyBKDown) mTargetEyePos += tmp[2] * keyEyeSpeed;
if(mKeyLTDown) mTargetEyePos -= tmp[0] * keyEyeSpeed;
if(mKeyRTDown) mTargetEyePos += tmp[0] * keyEyeSpeed;
if(mKeyUpDown) mTargetEyePos += tmp[1] * keyEyeSpeed;
if(mKeyDownDown) mTargetEyePos -= tmp[1] * keyEyeSpeed;
mEyePos += (mTargetEyePos - mEyePos) * g_smoothCamPosLerp;
camera.setPos(mEyePos);
camera.setRot(mEyeRot);
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,103 @@
//
// 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_CAMERA_CONTROLLER_H
#define SAMPLE_CAMERA_CONTROLLER_H
#include "SampleAllocator.h"
#include "RendererWindow.h"
#include <SampleUserInput.h>
#include "foundation/PxVec3.h"
namespace SampleFramework {
class SamplePlatform;
}
class Camera;
class CameraController : public SampleAllocateable
{
public:
virtual ~CameraController() {}
virtual void onPointerInputEvent(const SampleFramework::InputEvent& ie, physx::PxU32 x, physx::PxU32 y, physx::PxReal dx, physx::PxReal dy, bool val) {}
virtual void onAnalogInputEvent(const SampleFramework::InputEvent& , float val) {}
virtual void onDigitalInputEvent(const SampleFramework::InputEvent& , bool val) {}
virtual void update(Camera& camera, PxReal dtime) {}
virtual void collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents) {}
virtual PxReal getCameraSpeed() { return 0; }
};
class DefaultCameraController : public CameraController
{
public:
DefaultCameraController();
virtual ~DefaultCameraController();
void init(const PxVec3& pos, const PxVec3& rot);
void init(const PxTransform& pose);
void setCameraSpeed(const PxReal speed) { mCameraSpeed = speed; }
PxReal getCameraSpeed() { return mCameraSpeed; }
void setMouseLookOnMouseButton(bool mouseLookOnMB) { mMouseLookOnMB = mouseLookOnMB; }
void setMouseSensitivity(PxReal mouseSensitivity) { mMouseSensitivity = mouseSensitivity; }
// Implements CameraController
void onMouseDelta(PxI32 dx, PxI32 dy);
virtual void onAnalogInputEvent(const SampleFramework::InputEvent& , float val);
virtual void onDigitalInputEvent(const SampleFramework::InputEvent& , bool val);
virtual void onPointerInputEvent(const SampleFramework::InputEvent& ie, physx::PxU32 x, physx::PxU32 y, physx::PxReal dx, physx::PxReal dy, bool val);
virtual void collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents);
virtual void update(Camera& camera, PxReal dtime);
protected:
PxVec3 mTargetEyePos;
PxVec3 mTargetEyeRot;
PxVec3 mEyePos;
PxVec3 mEyeRot;
bool mMouseButtonDown;
bool mKeyFWDown;
bool mKeyBKDown;
bool mKeyRTDown;
bool mKeyLTDown;
bool mKeyUpDown;
bool mKeyDownDown;
bool mKeyShiftDown;
PxReal mCameraSpeed;
PxReal mCameraSpeedMultiplier;
bool mMouseLookOnMB;
PxReal mMouseSensitivity;
};
#endif

View File

@ -0,0 +1,578 @@
//
// 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 <stdio.h>
#include "SampleCharacterHelpers.h"
#include "AcclaimLoader.h"
#include "PsMathUtils.h"
#include "SampleAllocatorSDKClasses.h"
#include "SampleArray.h"
///////////////////////////////////////////////////////////////////////////////
static Acclaim::Bone* getBoneFromName(Acclaim::ASFData &data, const char *name)
{
// use a simple linear search -> probably we could use hash map if performance is an issue
for (PxU32 i = 0; i < data.mNbBones; i++)
{
if (strcmp(name, data.mBones[i].mName) == 0)
return &data.mBones[i];
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////
inline PxQuat EulerAngleToQuat(const PxVec3 &rot)
{
PxQuat qx(Ps::degToRad(rot.x), PxVec3(1.0f, 0.0f, 0.0f));
PxQuat qy(Ps::degToRad(rot.y), PxVec3(0.0f, 1.0f, 0.0f));
PxQuat qz(Ps::degToRad(rot.z), PxVec3(0.0f, 0.0f, 1.0f));
return qz * qy * qx;
}
///////////////////////////////////////////////////////////////////////////////
static PxTransform computeBoneTransform(PxTransform &rootTransform, Acclaim::Bone &bone, PxVec3* boneFrameData)
{
using namespace Acclaim;
//PxTransform rootTransform(PxVec3(0.0f), PxQuat(PxIdentity));
PxTransform parentTransform = (bone.mParent) ?
computeBoneTransform(rootTransform, *bone.mParent, boneFrameData) : rootTransform;
PxQuat qWorld = EulerAngleToQuat(bone.mAxis);
PxVec3 offset = bone.mLength * bone.mDirection;
PxQuat qDelta = PxQuat(PxIdentity);
PxVec3 boneData = boneFrameData[bone.mID-1];
if (bone.mDOF & BoneDOFFlag::eRX)
qDelta = PxQuat(Ps::degToRad(boneData.x), PxVec3(1.0f, 0.0f, 0.0f)) * qDelta;
if (bone.mDOF & BoneDOFFlag::eRY)
qDelta = PxQuat(Ps::degToRad(boneData.y), PxVec3(0.0f, 1.0f, 0.0f)) * qDelta;
if (bone.mDOF & BoneDOFFlag::eRZ)
qDelta = PxQuat(Ps::degToRad(boneData.z), PxVec3(0.0f, 0.0f, 1.0f)) * qDelta;
PxQuat boneOrientation = qWorld * qDelta * qWorld.getConjugate();
PxTransform boneTransform(boneOrientation.rotate(offset), boneOrientation);
return parentTransform.transform(boneTransform);
}
///////////////////////////////////////////////////////////////////////////////
static PxTransform computeBoneTransformRest(Acclaim::Bone &bone)
{
using namespace Acclaim;
PxTransform parentTransform = (bone.mParent) ?
computeBoneTransformRest(*bone.mParent) : PxTransform(PxVec3(0.0f), PxQuat(PxIdentity));
PxVec3 offset = bone.mLength * bone.mDirection;
PxTransform boneTransform(offset, PxQuat(PxIdentity));
return parentTransform.transform(boneTransform);
}
///////////////////////////////////////////////////////////////////////////////
Character::Character() :
mCurrentMotion(NULL),
mTargetMotion(NULL),
mBlendCounter(0),
mCharacterScale(1.0f),
mASFData(NULL),
mCharacterPose(PxVec3(0.0f), PxQuat(PxIdentity)),
mFrameTime(0.0f)
{
}
///////////////////////////////////////////////////////////////////////////////
int Character::addMotion(const char* amcFileName, PxU32 start, PxU32 end)
{
Acclaim::AMCData AMCData;
if (Acclaim::readAMCData(amcFileName, *mASFData, AMCData) == false)
{
AMCData.release();
return -1;
}
if (AMCData.mNbFrames == 0)
{
AMCData.release();
return -1;
}
if (end >= AMCData.mNbFrames)
end = AMCData.mNbFrames - 1;
Motion* motion = SAMPLE_NEW(Motion)();
if (buildMotion(AMCData, *motion, start, end) == false)
{
SAMPLE_FREE(motion);
AMCData.release();
return -1;
}
mMotions.pushBack(motion);
mCurrentMotion = motion;
// set the frame counter to 0
mFrameTime = 0.0f;
AMCData.release();
return mMotions.size() - 1;
}
///////////////////////////////////////////////////////////////////////////////
bool Character::buildMotion(Acclaim::AMCData &amcData, Motion &motion, PxU32 start, PxU32 end)
{
using namespace Acclaim;
if (mASFData == NULL)
return false;
motion.mNbFrames = end - start + 1;
motion.mMotionData = SAMPLE_NEW(MotionData)[motion.mNbFrames];
// compute bounds of all the motion data on normalized frame
PxBounds3 bounds = PxBounds3::empty();
for (PxU32 i = start; i < end; i++)
{
Acclaim::FrameData &frameData = amcData.mFrameData[i];
PxTransform rootTransform(PxVec3(0.0f), EulerAngleToQuat(frameData.mRootOrientation));
for (PxU32 j = 0; j < mASFData->mNbBones; j++)
{
PxTransform t = computeBoneTransform(rootTransform, mASFData->mBones[j], frameData.mBoneFrameData);
bounds.include(t.p);
}
}
Acclaim::FrameData& firstFrame = amcData.mFrameData[0];
Acclaim::FrameData& lastFrame = amcData.mFrameData[amcData.mNbFrames-1];
// compute direction vector
motion.mDistance = mCharacterScale * (lastFrame.mRootPosition - firstFrame.mRootPosition).magnitude();
PxVec3 firstPosition = firstFrame.mRootPosition;
PX_UNUSED(firstPosition);
PxVec3 firstAngles = firstFrame.mRootOrientation;
PxQuat firstOrientation = EulerAngleToQuat(PxVec3(0, firstAngles.y, 0));
for (PxU32 i = 0; i < motion.mNbFrames; i++)
{
Acclaim::FrameData& frameData = amcData.mFrameData[i+start];
MotionData &motionData = motion.mMotionData[i];
// normalize y-rot by computing inverse quat from first frame
// this makes all the motion aligned in the same (+ z) direction.
PxQuat currentOrientation = EulerAngleToQuat(frameData.mRootOrientation);
PxQuat qdel = firstOrientation.getConjugate() * currentOrientation;
PxTransform rootTransform(PxVec3(0.0f), qdel);
for (PxU32 j = 0; j < mNbBones; j++)
{
PxTransform boneTransform = computeBoneTransform(rootTransform, mASFData->mBones[j], frameData.mBoneFrameData);
motionData.mBoneTransform[j] = boneTransform;
}
//PxReal y = mCharacterScale * (frameData.mRootPosition.y - firstPosition.y) - bounds.minimum.y;
motionData.mRootTransform = PxTransform(PxVec3(0.0f, -bounds.minimum.y, 0.0f), PxQuat(PxIdentity));
}
// now make the motion cyclic by linear interpolating root position and joint angles
const PxU32 windowSize = 10;
for (PxU32 i = 0; i <= windowSize; i++)
{
PxU32 j = motion.mNbFrames - 1 - windowSize + i;
PxReal t = PxReal(i) / PxReal(windowSize);
MotionData& motion_i = motion.mMotionData[0];
MotionData& motion_j = motion.mMotionData[j];
// lerp root translation
PxVec3 blendedRootPos = (1.0f - t) * motion_j.mRootTransform.p + t * motion_i.mRootTransform.p;
for (PxU32 k = 0; k < mNbBones; k++)
{
PxVec3 pj = motion_j.mRootTransform.p + motion_j.mBoneTransform[k].p;
PxVec3 pi = motion_i.mRootTransform.p + motion_i.mBoneTransform[k].p;
PxVec3 p = (1.0f - t) * pj + t * pi;
motion_j.mBoneTransform[k].p = p - blendedRootPos;
}
motion_j.mRootTransform.p = blendedRootPos;
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
// we apply pose blending if there is transition from one motion to another
bool
Character::computeFramePose()
{
PxU32 frameNo = PxU32(mFrameTime);
if (frameNo >= mCurrentMotion->mNbFrames)
return false;
MotionData& motionData = mCurrentMotion->mMotionData[frameNo];
// compute blended motion when a target motion is set
if (mTargetMotion)
{
// first pose from target motion data
MotionData& targetData = mTargetMotion->mMotionData[0];
PxReal t = PxReal(mBlendCounter) / 10.0f;
for (PxU32 i = 0; i < mNbBones; i++)
{
mCurrentBoneTransform[i].p = t * motionData.mBoneTransform[i].p +
(1.0f - t) * targetData.mBoneTransform[i].p;
mCurrentBoneTransform[i].q = motionData.mBoneTransform[i].q;
}
mCurrentRootTransform.p = t * motionData.mRootTransform.p +
(1.0f - t) * targetData.mRootTransform.p;
mCurrentRootTransform.q = targetData.mRootTransform.q;
}
else
{
for (PxU32 i = 0; i < mNbBones; i++)
mCurrentBoneTransform[i] = motionData.mBoneTransform[i];
mCurrentRootTransform = motionData.mRootTransform;
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool Character::create(const char *asfFileName, PxReal scale)
{
mCharacterScale = scale;
if (readSetup(asfFileName) == false)
return false;
return true;
}
//////////////////////////////////////////////////////////////////////////////
bool Character::faceToward(const PxVec3& targetDir, PxReal angleLimitPerFrame)
{
PxVec3 oldDir = mCharacterPose.q.rotate(PxVec3(0,0,1));
PxVec3 up(0,1,0);
PxVec3 newDir = PxVec3(targetDir.x, 0, targetDir.z).getNormalized();
PxVec3 right = -1.0f * oldDir.cross(up);
PxReal cos = newDir.dot(oldDir);
PxReal sin = newDir.dot(right);
PxReal angle = atan2(sin, cos);
PxReal limit = angleLimitPerFrame * (PxPi / 180.0f);
if (angle > limit) angle = limit;
else if (angle < -limit) angle = -limit;
PxQuat qdel(angle, up);
mCharacterPose.q = qdel * mCharacterPose.q;
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool
Character::getFramePose(PxTransform &rootTransform, SampleArray<PxVec3> &positions, SampleArray<PxU32> &indexBuffers)
{
if (mCurrentMotion == NULL)
return false;
PxU32 frameNo = PxU32(mFrameTime);
if (frameNo >= mCurrentMotion->mNbFrames)
return false;
positions.resize(mNbBones+1);
// copy precomputed bone position in local space
positions[0] = PxVec3(0.0f); // root position
for (PxU32 i = 0; i < mNbBones; i++)
positions[i+1] = mCurrentBoneTransform[i].p;
// copy capsule index data
indexBuffers.resize(mASFData->mNbBones * 2);
for (PxU32 i = 0; i < mASFData->mNbBones; i++)
{
Acclaim::Bone& bone = mASFData->mBones[i];
indexBuffers[i*2] = bone.mID;
indexBuffers[i*2+1] = (bone.mParent) ? bone.mParent->mID : 0;
}
// compute root transform
rootTransform = mCharacterPose.transform(mCurrentRootTransform);
return true;
}
//////////////////////////////////////////////////////////////////////////////
bool Character::move(PxReal speed, bool jump, bool active )
{
if (mCurrentMotion == NULL)
return false;
if (mBlendCounter > 0)
mBlendCounter--;
if (mTargetMotion && (mBlendCounter == 0))
{
mBlendCounter = 0;
mCurrentMotion = mTargetMotion;
mFrameTime = 0.0f;
mTargetMotion = NULL;
}
PxU32 nbFrames = mCurrentMotion->mNbFrames;
PxReal distance = mCurrentMotion->mDistance;
PxReal frameDelta = 0.0f;
const PxReal angleLimitPerFrame = 3.0f;
if (jump)
{
frameDelta = 1.0f;
}
else if (active && (mBlendCounter == 0))
{
// compute target orientation
PxVec3 dir = mTargetPosition - mCharacterPose.p;
dir.y = 0.0f;
PxReal curDistance = dir.magnitude();
if (curDistance > 0.01f)
faceToward(dir, angleLimitPerFrame);
frameDelta = speed * PxReal(nbFrames) * (curDistance / distance);
}
else
{
frameDelta = 0;
}
mCharacterPose.p = mTargetPosition;
mFrameTime += frameDelta;
PxU32 frameNo = PxU32(mFrameTime);
if (frameNo >= nbFrames)
{
if (jump)
mFrameTime = PxReal(nbFrames) - 1.0f;
else
mFrameTime = 0.0f;
}
// compute pose of all the bones at current frame (results are used by both getFramePose and Skin)
computeFramePose();
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool Character::readSetup(const char* asfFileName)
{
if (mASFData) mASFData->release();
mASFData = new Acclaim::ASFData;
if (Acclaim::readASFData(asfFileName, *mASFData) == false)
{
delete mASFData;
mASFData = NULL;
return false;
}
mNbBones = mASFData->mNbBones;
// scale bone length
for (PxU32 i = 0; i < mASFData->mNbBones; i++)
{
Acclaim::Bone& bone = mASFData->mBones[i];
bone.mLength *= mCharacterScale;
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
void Character::release()
{
for (PxU32 i = 0; i < mMotions.size(); i++)
{
if (mMotions[i])
mMotions[i]->release();
}
if (mASFData) mASFData->release();
}
///////////////////////////////////////////////////////////////////////////////
void Character::resetMotion(PxReal firstFrame)
{
mFrameTime = firstFrame;
}
///////////////////////////////////////////////////////////////////////////////
bool Character::setGlobalPose(const PxTransform &transform)
{
mCharacterPose.p = transform.p;
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool Character::setGoalPosition(const PxVec3 pos)
{
mGoalPosition = pos;
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool Character::setMotion(PxU32 id, bool init)
{
if (id >= mMotions.size())
return false;
if (init)
{
mCurrentMotion = mMotions[id];
mTargetMotion = NULL;
computeFramePose();
return true;
}
if (mCurrentMotion == NULL)
{
mCurrentMotion = mMotions[id];
return true;
}
if (mCurrentMotion == mMotions[id])
return true;
if (mTargetMotion == mMotions[id])
return true;
mTargetMotion = mMotions[id];
mBlendCounter = 10;
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool Character::setTargetPosition(const PxVec3 pos)
{
mTargetPosition = pos;
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool Character::setForward(void)
{
PxVec3 p = mCharacterPose.p;
PxVec3 dir = mGoalPosition - p;
dir.normalize();
dir = mCharacterPose.q.rotate(dir);
PxU32 nbFrames = mCurrentMotion->mNbFrames;
PxReal distance = mCurrentMotion->mDistance;
PxReal frameDelta = distance / PxReal(nbFrames);
mTargetPosition = p + frameDelta * dir;
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool
Skin::bindToCharacter(Character &character, SampleArray<PxVec4> &positions)
{
// currently we just bind everything to the 'thorax' (between neck and clavicles).
// Modify this if you need to do more elaborate skin binding
mBindPos.resize(positions.size());
Acclaim::Bone* bone = getBoneFromName(*character.mASFData, "thorax");
if (bone == NULL)
return false;
PxTransform boneTransform = computeBoneTransformRest(*bone);
PxTransform boneTransformInv = boneTransform.getInverse();
mBoneID = bone->mID - 1;
for (PxU32 i = 0; i < positions.size(); i++)
{
mBindPos[i] = boneTransformInv.transform(
reinterpret_cast<const PxVec3&>(positions[i]));
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool
Skin::computeNewPositions(Character &character, SampleArray<PxVec3> &particlePositions)
{
if (character.mCurrentMotion == NULL)
return false;
PxTransform t = character.mCurrentBoneTransform[mBoneID];
particlePositions.resize(mBindPos.size());
for (PxU32 i = 0; i < mBindPos.size(); i++)
particlePositions[i] = t.transform(mBindPos[i]);
return true;
}

View File

@ -0,0 +1,152 @@
//
// 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_CHARACTER_HELPERS_H
#define SAMPLE_CHARACTER_HELPERS_H
#include "foundation/PxBounds3.h"
#include "foundation/PxFlags.h"
#include "foundation/PxTransform.h"
#include "SampleAllocator.h"
#include "SampleArray.h"
#include "AcclaimLoader.h"
class Character;
///////////////////////////////////////////////////////////////////////////////
class Skin
{
public:
bool bindToCharacter(Character& character, SampleArray<PxVec4> &positions);
bool computeNewPositions(Character& characeter, SampleArray<PxVec3> &positions);
protected:
SampleArray<PxVec3> mBindPos;
int mBoneID;
};
///////////////////////////////////////////////////////////////////////////////
// Helper class to read and setup motion clip
// This class provides enough functionality to create a moving stickman character and use it
// for samples and tests.
class Character
{
///////////////////////////////////////////////////////////////////////////////
struct MotionData : public SampleAllocateable
{
PxTransform mRootTransform;
PxTransform mBoneTransform[MAX_BONE_NUMBER];
};
struct Motion : public SampleAllocateable
{
MotionData* mMotionData;
PxU32 mNbFrames;
PxReal mDistance; // distance from first to last frame
public:
void release() { SAMPLE_FREE(mMotionData); delete this; }
};
public:
Character();
virtual ~Character() { release(); }
/// read a motion clip from .amc file, returns a motion handle or -1 if amc file is invalid.
int addMotion(const char* amcFileName, PxU32 start = 0, PxU32 end = 10000);
/// create character from .asf setup
bool create(const char* asfFileName, PxReal scale = 1.0f);
/// orient this character in the given direction
bool faceToward(const PxVec3 &dir, PxReal angleLimitPerFrame = 360.0f);
/// create a pose info enough to create stickman
bool getFramePose(PxTransform &rootTransform, SampleArray<PxVec3> &positions, SampleArray<PxU32> &indexBuffers);
/// set next pose from the motion clip (speed = 1.0 will match original motion clip)
bool move(PxReal speed = 1.0f, bool jump = false, bool active = true);
/// reset motion to first frame
void resetMotion(PxReal firstFrame = 0.0f);
/// move forward
bool setForward();
/// set global pose
bool setGlobalPose(const PxTransform &transform);
/// set goal position
bool setGoalPosition(const PxVec3 pos);
/// select motion
bool setMotion(PxU32 motionhandle, bool init = false);
/// set target position
bool setTargetPosition(const PxVec3 pos);
protected:
/// build internal motion data from raw amc data
bool buildMotion(Acclaim::AMCData&, Motion&, PxU32 start, PxU32 end);
/// compute per-frame pose cache
bool computeFramePose();
/// read a motion clip from .amc file
bool readSetup(const char* asfFileName);
/// release memory
void release();
private:
SampleArray<Motion*> mMotions;
PxTransform mCurrentBoneTransform[MAX_BONE_NUMBER];
PxTransform mCurrentRootTransform;
Motion* mCurrentMotion;
Motion* mTargetMotion;
PxU32 mBlendCounter;
PxReal mCharacterScale;
Acclaim::ASFData* mASFData;
PxU32 mNbBones;
PxVec3 mGoalPosition;
PxVec3 mTargetPosition;
PxTransform mCharacterPose; // transformation of the character itself
PxReal mFrameTime;
friend class Skin;
};
#endif // SAMPLE_CHARACTER_HELPERS

View File

@ -0,0 +1,609 @@
//
// 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 <ctype.h>
#include "SamplePreprocessor.h"
#include "SampleConsole.h"
#include "RendererMemoryMacros.h"
#include "Renderer.h"
#include "PsString.h"
#include "PsUtilities.h"
#include "SampleBaseInputEventIds.h"
#include <SampleUserInputIds.h>
#include "SampleUserInputDefines.h"
using namespace SampleRenderer;
using namespace SampleFramework;
#define NB_LINES 14
// EXIT: a basic command to hide the console
// Usage: exit
void Console::BasicCmdexit(Console* console, const char* text, void* user_data)
{
console->setActive(false);
}
// CLS: a basic command to clear the console
// Usage: cls
void Console::BasicCmdcls(Console* console, const char* text, void* user_data)
{
console->clear();
}
// PROMPT: a basic command to set the prompt
// Usage: prompt [text]
void Console::BasicCmdSetPrompt(Console* console, const char* text, void* user_data)
{
console->setPrompt(text);
}
// CMDLIST: a basic command to display a list of all possible commands
// Usage: cmdlist <= display all possible commands
// cmdlist [command] <= check whether a command exists or not
void Console::BasicCmdcmdlist(Console* console, const char* text, void* user_data)
{
ConsoleCommand* pcmd;
if(!text)
{
for(int i=0;i<256;i++)
{
pcmd = console->mCmds[i];
while(pcmd)
{
console->out(pcmd->fullcmd);
pcmd = pcmd->next;
}
}
}
else
{
int i = text[0];
if( (i >= 'A') && (i<='Z') )
i -= 'A' - 'a';
pcmd = console->mCmds[i];
while(pcmd)
{
if(Ps::strncmp(pcmd->fullcmd, text, strlen(text)) == 0)
console->out(pcmd->fullcmd);
pcmd = pcmd->next;
}
}
}
// CMDHIST: a basic command to display command history
// Usage: cmdhist
void Console::BasicCmdcmdhist(Console* console, const char* text, void* user_data)
{
long index = console->mNewcmd - console->mNumcmdhist;
for(long i=0;i<console->mNumcmdhist;i++)
{
if( index > CONSOLE_MAX_HIST )
index -= CONSOLE_MAX_HIST;
console->out(console->mCmdhist[index] );
index++;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Constructor.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Console::Console(SampleFramework::SamplePlatform* plt) :
mViewBottom (0),
mNewline (0),
mIsActive (false)
{
strcpy(mLastChar, "-");
strcpy(mPrompt, ">");
resetCol();
mNbCmds = 0;
mNewcmd = 0;
mNumcmdhist = 0;
mCurcmd = 0;
mUserData = 0;
for(PxU32 i=0;i<CONSOLE_MAX_COMMAND_NB;i++)
mCmds[i] = NULL;
// Create console
addCmd("exit", BasicCmdexit);
addCmd("cmdlist", BasicCmdcmdlist);
addCmd("cls", BasicCmdcls);
addCmd("cmdhist", BasicCmdcmdhist);
addCmd("prompt", BasicCmdSetPrompt);
clear();
cmdClear();
out("PhysX Samples console");
out("");
out("Type cmdlist to display all possible commands.");
out("Use PageUp / PageDown to scroll the window.");
out("Use arrow keys to recall old commands.");
out("Use ESC to exit.");
out("");
advance();
strcpy(mBuffer[mNewline].mText, mPrompt);
strcat(mBuffer[mNewline].mText, mLastChar);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Destructor.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Console::~Console()
{
destroy();
}
void Console::resetCol()
{
mCol = (PxI32)strlen(mPrompt);
}
void Console::setPrompt(const char* text)
{
if(!text)
return;
const PxU32 Length = (PxU32)strlen(text);
if(Length>255)
return;
strcpy(mPrompt, text);
}
// Advance the console one line
void Console::advance()
{
mNewline--;
if(mNewline<0)
mNewline += CONSOLE_MAX_ROW;
mBuffer[mNewline].mText[0] = '\0';
mViewBottom = mNewline;
}
// Clear the console text buffer
void Console::clear()
{
for(PxU32 i=0;i<CONSOLE_MAX_ROW;i++)
{
for(PxU32 j=0;j<CONSOLE_MAX_COL;j++)
mBuffer[i].mText[j] = '\0';
mBuffer[i].mColor = RendererColor(255,255,255);
}
mNewline = 0;
mViewBottom = 0;
}
// Clear the console text buffer
void Console::cmdClear()
{
for(PxU32 i=0;i<CONSOLE_MAX_HIST;i++)
for(PxU32 j=0;j<CONSOLE_MAX_COL;j++)
mCmdhist[i][j] = '\0';
mNewcmd = 0;
mNumcmdhist = 0;
mCurcmd = 0;
}
// Write a string to the console
void Console::out(const char* string)
{
advance();
if(string)
{
size_t Length = strlen(string);
if(Length>=CONSOLE_MAX_COL-1)
{
PX_ASSERT(0);
strcpy(mBuffer[mNewline].mText, "CONSOLE LINE TOO LONG!");
}
else
strcpy(mBuffer[mNewline].mText, string);
}
}
// Process an instruction
// called after the user hits enter
void Console::process()
{
// Discard prompt
char cmd[1024];
long Index = (long)strlen(mPrompt);
strcpy(cmd, &mBuffer[mNewline].mText[Index]);
// Keep track of command in history buffer
strcpy(mCmdhist[mNewcmd], cmd);
mNewcmd = mNewcmd % CONSOLE_MAX_HIST;
mNewcmd++;
mCurcmd = 0;
mNumcmdhist++;
if(mNumcmdhist>CONSOLE_MAX_HIST) mNumcmdhist = CONSOLE_MAX_HIST;
mBuffer[mNewline].mColor = 0xffeeeeee;
// Extract param and execute command
char* cmdparam;
cmdparam = strchr(cmd, ' ');
if(cmdparam)
{
*cmdparam=0;
cmdparam++;
}
if(!execCmd(cmd, cmdparam))
out("Invalid command");
}
// up and down arrow
// for command history
void Console::cmdHistory()
{
if( mCurcmd != -1 )
{
char buf[256];
long cmdnum;
strcpy(buf, mPrompt);
cmdnum = mNewcmd - mCurcmd;
if( cmdnum < 0 )
cmdnum += CONSOLE_MAX_HIST;
strcat(buf, mCmdhist[cmdnum]);
strcat(buf, mLastChar);
strcpy(mBuffer[mNewline].mText, buf);
mCol = (PxI32)strlen(buf)-1;
}
}
bool Console::findBestCommand(char* best_command, const char* text, PxU32& tabIndex) const
{
if(!text || !best_command)
return false;
const size_t length = strlen(text);
if(length>1023)
return false;
char tmp[1024];
strcpy(tmp, text);
Ps::strlwr(tmp);
const unsigned char i = tmp[0];
ConsoleCommand* FirstCommand = NULL;
ConsoleCommand* BestCommand = NULL;
ConsoleCommand* pcmd = mCmds[i];
PxU32 currentIndex = 0;
while(pcmd && !BestCommand)
{
char tmp2[1024];
strcpy(tmp2, pcmd->fullcmd);
Ps::strlwr(tmp2);
if(Ps::strncmp(tmp, tmp2, length)== 0)
{
if(!currentIndex)
FirstCommand = pcmd;
if(currentIndex>=tabIndex)
BestCommand = pcmd;
currentIndex++;
}
pcmd = pcmd->next;
}
if(BestCommand)
{
tabIndex++;
strcpy(best_command, BestCommand->fullcmd);
return true;
}
tabIndex = 0;
if(currentIndex && FirstCommand)
{
tabIndex++;
strcpy(best_command, FirstCommand->fullcmd);
return true;
}
return false;
}
// Try to execute a command
bool Console::execCmd(const char* cmd, const char* param)
{
if(!cmd)
return false;
int HashIndex = cmd[0];
HashIndex = tolower(HashIndex);
ConsoleCommand* pcmd = mCmds[HashIndex];
while(pcmd)
{
if(Ps::stricmp(cmd, pcmd->fullcmd) == 0)
{
pcmd->function(this, param, mUserData);
return true;
}
else pcmd = pcmd->next;
}
return false;
}
// Destroy the console
void Console::destroy()
{
// clean up command list
for(PxU32 i=0;i<256;i++)
{
if(mCmds[i])
{
ConsoleCommand* pcmd = mCmds[i];
while(pcmd)
{
ConsoleCommand* next = pcmd->next;
DELETESINGLE(pcmd);
pcmd = next;
}
}
}
}
// Add a command
void Console::addCmd(const char* full_cmd, void (*function)(Console*, const char *, void*))
{
if(!full_cmd) return; // Command must be defined
if(!function) return; // Function must be defines
if(strlen(full_cmd)>=CONSOLE_MAX_COMMAND_LENGTH) return;
if(mNbCmds==CONSOLE_MAX_COMMAND_NB) return;
mNbCmds++;
int HashIndex = full_cmd[0];
HashIndex = tolower(HashIndex);
ConsoleCommand* pcmd = mCmds[HashIndex];
if(!pcmd)
{
mCmds[HashIndex] = SAMPLE_NEW(ConsoleCommand);
pcmd = mCmds[HashIndex];
}
else
{
while(pcmd->next)
{
pcmd = pcmd->next;
}
pcmd->next = SAMPLE_NEW(ConsoleCommand);
pcmd = pcmd->next;
}
strcpy(pcmd->fullcmd, full_cmd);
pcmd->function = function;
pcmd->next = NULL;
}
bool Console::render(Renderer* rnd)
{
if(!rnd)
return false;
if(!mIsActive)
return true;
const PxU32 NbLines = NB_LINES;
const PxU32 FntHeight = 14;
PxU32 width, height;
rnd->getWindowSize(width, height);
const RendererColor backColor(3, 3, 39);
ScreenQuad sq;
sq.mX0 = 0.0f;
sq.mY0 = 20.0f/float(height);
sq.mX1 = 1.0f;
sq.mY1 = (20.0f + float((NbLines+2)*FntHeight))/float(height);
sq.mLeftUpColor = backColor;
sq.mRightUpColor = backColor;
sq.mLeftDownColor = backColor;
sq.mRightDownColor = backColor;
sq.mAlpha = 0.8f;
rnd->drawScreenQuad(sq);
PxU32 TextY = 24 + NbLines*FntHeight;
const PxReal scale = 0.4f;
const PxReal shadowOffset = 0.0f;
long temp = mViewBottom;
for(PxU32 i=0;i<NbLines;i++)
{
rnd->print(10, TextY, mBuffer[temp].mText, scale, shadowOffset, mBuffer[temp].mColor);
temp = (temp + 1) % CONSOLE_MAX_ROW;
TextY -= FntHeight; //size should come from renderer
}
return true;
}
// Process a single character
static bool gTabMode = false;
static PxU32 gTabIndex = 0;
static char gTabCmd[1024];
void Console::in(PxU32 wparam)
{
if(!mIsActive)
return;
if ((wparam >= 'a' && wparam <= 'z') || (wparam >= 'A' && wparam <= 'Z') || (wparam >= '0' && wparam <= '9') || wparam == ' ' || wparam == '.' || wparam == '-' || wparam == '_')
{
gTabMode = false;
if(mCol >= CONSOLE_MAX_COL-2) // We need 2 extra characters for the cursor and the final 0
return;
mBuffer[mNewline].mText[mCol++] = (char)wparam; // Append new character
mBuffer[mNewline].mText[mCol] = mLastChar[0]; // Append cursor
mBuffer[mNewline].mText[mCol+1] = '\0';
}
}
void Console::collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents)
{
//digital keyboard events
DIGITAL_INPUT_EVENT_DEF(CONSOLE_OPEN, WKEY_TAB, OSXKEY_TAB, LINUXKEY_TAB );
DIGITAL_INPUT_EVENT_DEF(CONSOLE_ESCAPE, WKEY_ESCAPE, OSXKEY_ESCAPE, LINUXKEY_ESCAPE );
DIGITAL_INPUT_EVENT_DEF(CONSOLE_ENTER, WKEY_RETURN, OSXKEY_RETURN, LINUXKEY_RETURN );
DIGITAL_INPUT_EVENT_DEF(CONSOLE_BACKSPACE, WKEY_BACKSPACE, OSXKEY_BACKSPACE, LINUXKEY_BACKSPACE );
DIGITAL_INPUT_EVENT_DEF(CONSOLE_LIST_COMMAND_UP, WKEY_UP, OSXKEY_UP, LINUXKEY_UP );
DIGITAL_INPUT_EVENT_DEF(CONSOLE_LIST_COMMAND_DOWN, WKEY_DOWN, OSXKEY_DOWN, LINUXKEY_DOWN );
DIGITAL_INPUT_EVENT_DEF(CONSOLE_SCROLL_UP, WKEY_PRIOR, OSXKEY_PRIOR, LINUXKEY_PRIOR );
DIGITAL_INPUT_EVENT_DEF(CONSOLE_SCROLL_DOWN, WKEY_NEXT, OSXKEY_NEXT, LINUXKEY_NEXT );
}
//return true if we processed the key
void Console::onDigitalInputEvent(const SampleFramework::InputEvent& ie, bool val)
{
//if (val)
{
if (!mIsActive)
{
if (ie.m_Id == CONSOLE_OPEN)
{
mIsActive = true;
return;
}
}
else
{
if (!val)
{
switch (ie.m_Id)
{
case CONSOLE_OPEN:
if(!gTabMode)
{
gTabMode = true;
// Discard last character
mBuffer[mNewline].mText[mCol] = '\0';
// Discard prompt
long Index = (long)strlen(mPrompt);
strcpy(gTabCmd, &mBuffer[mNewline].mText[Index]);
}
char BestCmd[1024];
if(findBestCommand(BestCmd, gTabCmd, gTabIndex))
{
strcpy(mBuffer[mNewline].mText, mPrompt);
strcat(mBuffer[mNewline].mText, BestCmd);
strcat(mBuffer[mNewline].mText, mLastChar);
mCol = PxI32(strlen(mPrompt) + strlen(BestCmd));
}
else
{
gTabMode = false;
mBuffer[mNewline].mText[mCol] = mLastChar[0]; // Append cursor
mBuffer[mNewline].mText[mCol+1] = '\0';
}
break;
case CONSOLE_BACKSPACE:
gTabMode = false;
if(mCol>(long)strlen(mPrompt))
{
mBuffer[mNewline].mText[mCol] = '\0';
mBuffer[mNewline].mText[mCol-1] = mLastChar[0];
mCol--;
}
break;
case CONSOLE_ENTER:
gTabMode = false;
mBuffer[mNewline].mText[mCol] = '\0';
process();
advance();
strcpy(mBuffer[mNewline].mText, mPrompt);
strcat(mBuffer[mNewline].mText, mLastChar);
resetCol();
break;
case CONSOLE_ESCAPE:
mIsActive = false;
gTabMode = false;
break;
case CONSOLE_LIST_COMMAND_UP:
mCurcmd++;
if( mCurcmd > mNumcmdhist )
mCurcmd = mNumcmdhist;
cmdHistory();
break;
case CONSOLE_LIST_COMMAND_DOWN:
mCurcmd--;
if( mCurcmd <= 0 )
mCurcmd = 0;
cmdHistory();
break;
case CONSOLE_SCROLL_UP:
mViewBottom++;
if(mViewBottom >= CONSOLE_MAX_ROW) mViewBottom -= CONSOLE_MAX_ROW;
if(mViewBottom == mNewline - NB_LINES) mViewBottom--;
break;
case CONSOLE_SCROLL_DOWN:
mViewBottom--;
if(mViewBottom < 0) mViewBottom += CONSOLE_MAX_ROW;
if(mViewBottom == mNewline-1) mViewBottom = mNewline;
break;
}
}
}
}
}
void Console::onKeyDown(SampleFramework::SampleUserInput::KeyCode keyCode, PxU32 param)
{
//sschirm doesn't compile on snc
//const int keyparam = (int)param;
if (mIsActive)
{
if(param)
in(param);
}
}

View File

@ -0,0 +1,134 @@
//
// 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_CONSOLE_H
#define SAMPLE_CONSOLE_H
#include "common/PxPhysXCommonConfig.h"
#include "RendererColor.h"
#include "RendererWindow.h"
#include "SampleAllocator.h"
#include <SampleUserInput.h>
#include <SamplePlatform.h>
#define CONSOLE_KEY 222
#define CONSOLE_MAX_COL 80
#define CONSOLE_MAX_ROW 200
#define CONSOLE_MAX_HIST 30
namespace SampleRenderer
{
class Renderer;
}
struct ConsoleRow : public SampleAllocateable
{
SampleRenderer::RendererColor mColor;
char mText[CONSOLE_MAX_COL];
};
#define CONSOLE_MAX_COMMAND_LENGTH 48
#define CONSOLE_MAX_COMMAND_NB 256
class Console;
struct ConsoleCommand : public SampleAllocateable
{
char fullcmd[CONSOLE_MAX_COMMAND_LENGTH];
void (*function)(Console* console, const char* text, void* user_data);
struct ConsoleCommand* next;
};
enum ConsoleInputKey
{
CONSOLE_KEY_PRIOR,
CONSOLE_KEY_NEXT,
CONSOLE_KEY_UP,
CONSOLE_KEY_DOWN,
};
class Console : public SampleAllocateable
{
public:
Console(SampleFramework::SamplePlatform* plt);
~Console();
bool render(SampleRenderer::Renderer* rnd);
void onKeyDown(SampleFramework::SampleUserInput::KeyCode keyCode, PxU32 param);
void onDigitalInputEvent(const SampleFramework::InputEvent& ie, bool val);
void collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents);
void out(const char* string);
void addCmd(const char* full_cmd, void (*function)(Console*, const char*, void*));
void clear();
void setPrompt(const char* text);
bool isActive() const { return mIsActive; }
void setActive(bool b) { mIsActive = b; }
void setUserData(void* userData) { mUserData = userData; }
static void BasicCmdexit(Console* console, const char* text, void* user_data);
static void BasicCmdcls(Console* console, const char* text, void* user_data);
static void BasicCmdSetPrompt(Console* console, const char* text, void* user_data);
static void BasicCmdcmdlist(Console* console, const char* text, void* user_data);
static void BasicCmdcmdhist(Console* console, const char* text, void* user_data);
private:
char mCmdhist[CONSOLE_MAX_HIST][CONSOLE_MAX_COL];
long mNewcmd;
long mNumcmdhist;
long mCurcmd;
long mNbCmds;
ConsoleCommand* mCmds[CONSOLE_MAX_COMMAND_NB];
void* mUserData;
ConsoleRow mBuffer[CONSOLE_MAX_ROW];
char mPrompt[256];
char mLastChar[2];
PxI32 mViewBottom;
PxI32 mNewline;
PxI32 mCol;
bool mIsActive;
// Internal methods
void cmdClear();
void advance();
void resetCol();
void process();
void in(PxU32 wparam);
void cmdHistory();
bool execCmd(const char* cmd, const char* param);
void destroy();
bool findBestCommand(char* best_command, const char* text, PxU32& tabIndex) const;
};
#endif

View File

@ -0,0 +1,264 @@
//
// 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 "SampleInputMappingAsset.h"
#include "ODBlock.h"
#include "PxTkFile.h"
using namespace SampleFramework;
static const int MAPPING_VERSION = 4;
SampleInputMappingAsset::SampleInputMappingAsset(SampleFramework::File* file, const char *path, bool empty,PxU32 userInputCS, PxU32 inputEventCS)
: mSettingsBlock(NULL), mMapping(NULL) , mFile(file) , mPath(path), mUserInputCS(userInputCS), mInputEventCS(inputEventCS)
{
mSampleInputData.reserve(128);
PX_ASSERT(file);
mIsOk = true;
if(empty)
{
createNewFile(false);
}
else
{
mMapping = new ODBlock();
if (!mMapping->loadScript(file))
{
shdfnd::printFormatted("ODS parse error: %s in file: %s\n", mMapping->lastError, path);
mIsOk = false;
createNewFile(true);
}
else
{
mSettingsBlock = mMapping->getBlock("InputMapping");
if (!mSettingsBlock)
{
shdfnd::printFormatted("No \"InputEventSettings\" block found!\n");
mIsOk = false;
createNewFile(true);
}
else
{
int versionNumber = 0;
if(!mSettingsBlock->getBlockInt("Version",&versionNumber))
{
mIsOk = false;
createNewFile(true);
}
else
{
if(versionNumber != MAPPING_VERSION)
{
mIsOk = false;
createNewFile(true);
}
else
{
if(!checksumCheck())
{
mIsOk = false;
createNewFile(true);
}
else
{
loadData(mSettingsBlock);
}
}
}
}
}
}
}
bool SampleInputMappingAsset::checksumCheck()
{
PxU32 userInputCS = 0;
if(!mSettingsBlock->getBlockU32("UserInputCS",&userInputCS))
{
return false;
}
PxU32 inputEventCS = 0;
if(!mSettingsBlock->getBlockU32("InputEventCS",&inputEventCS))
{
return false;
}
if(mUserInputCS != userInputCS)
{
return false;
}
if(mInputEventCS != inputEventCS)
{
return false;
}
return true;
}
SampleInputMappingAsset::~SampleInputMappingAsset()
{
if(mFile)
{
fclose(mFile);
}
if(mMapping)
delete mMapping;
}
void SampleInputMappingAsset::loadData(ODBlock* odsSettings)
{
odsSettings->reset();
while (odsSettings->moreSubBlocks())
{
ODBlock* subBlock = odsSettings->nextSubBlock();
subBlock->reset();
SampleInputData inputData;
if (!strcmp(subBlock->ident(), "Map"))
{
if (subBlock->moreTerminals())
{
const char* p = subBlock->nextTerminal();
strcpy(inputData.m_UserInputName, p);
}
if (subBlock->moreTerminals())
{
const char* p = subBlock->nextTerminal();
strcpy(inputData.m_InputEventName, p);
}
mSampleInputData.push_back(inputData);
}
}
}
void SampleInputMappingAsset::addMapping(const char* uiName, const char* ieName)
{
if(!mIsOk)
return;
ODBlock & mapping = *new ODBlock();
mapping.ident("Map");
mSettingsBlock->addStatement(mapping);
ODBlock & userInputBlock = *new ODBlock();
mapping.addStatement(userInputBlock);
userInputBlock.ident(uiName);
ODBlock & inputEventBlock = *new ODBlock();
mapping.addStatement(inputEventBlock);
inputEventBlock.ident(ieName);
}
bool SampleInputMappingAsset::createNewFile(bool rewriteFile)
{
if(rewriteFile)
{
if(mFile)
{
fclose(mFile);
mFile = NULL;
}
PxToolkit::fopen_s(&mFile,mPath , "w");
if(mFile)
mIsOk = true;
}
if(mMapping)
{
delete mMapping;
mMapping = NULL;
}
mMapping = new ODBlock();
mMapping->ident("InputMapping");
mSettingsBlock = mMapping;
ODBlock & version = *new ODBlock();
version.ident("Version");
mSettingsBlock->addStatement(version);
ODBlock & nb = *new ODBlock();
version.addStatement(nb);
char temps[64];
sprintf(temps,"%d",MAPPING_VERSION);
nb.ident(temps);
ODBlock & userInputCSB = *new ODBlock();
userInputCSB.ident("UserInputCS");
mSettingsBlock->addStatement(userInputCSB);
ODBlock &nb2 = *new ODBlock();
userInputCSB.addStatement(nb2);
sprintf(temps,"%d",mUserInputCS);
nb2.ident(temps);
ODBlock & inputEventCSB = *new ODBlock();
inputEventCSB.ident("InputEventCS");
mSettingsBlock->addStatement(inputEventCSB);
ODBlock &nb3 = *new ODBlock();
inputEventCSB.addStatement(nb3);
sprintf(temps,"%d",mInputEventCS);
nb3.ident(temps);
return true;
}
void SampleInputMappingAsset::saveMappings()
{
if(!mIsOk)
return;
if(mFile)
{
fclose(mFile);
mFile = NULL;
}
PxToolkit::fopen_s(&mFile,mPath , "w");
if(mFile)
{
mMapping->saveScript(mFile,false);
fclose(mFile);
}
mFile = NULL;
}
bool SampleInputMappingAsset::isOk(void) const
{
return mIsOk;
}

View File

@ -0,0 +1,66 @@
//
// 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_INPUT_MAPPING_ASSET_H
#define SAMPLE_INPUT_MAPPING_ASSET_H
#include <SampleUserInput.h>
#include <ODBlock.h>
#include "SampleAllocator.h"
class SampleInputMappingAsset : public SampleAllocateable
{
public:
SampleInputMappingAsset(SampleFramework::File* file, const char *path, bool empty,PxU32 userInputCS, PxU32 inputEventCS);
virtual ~SampleInputMappingAsset(void);
virtual bool isOk(void) const;
const SampleFramework::T_SampleInputData& getSampleInputData() const { return mSampleInputData; }
void addMapping(const char* uiName, const char* ieName);
void saveMappings();
private:
void loadData(ODBlock* odsSettings);
bool createNewFile(bool rewriteFile);
bool checksumCheck();
private:
SampleFramework::T_SampleInputData mSampleInputData;
ODBlock* mSettingsBlock;
ODBlock* mMapping;
SampleFramework::File* mFile;
const char* mPath;
bool mIsOk;
PxU32 mUserInputCS;
PxU32 mInputEventCS;
};
#endif

View File

@ -0,0 +1,187 @@
//
// 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 "foundation/PxAssert.h"
#include "RendererConfig.h"
#include "SampleCommandLine.h"
#include "RendererMemoryMacros.h"
#include "SampleAllocator.h"
#include "PhysXSampleApplication.h"
#include "PxTkFile.h"
using namespace SampleFramework;
#if defined(RENDERER_MACOSX)
// MACOSX non-deterministically crashed with one thread ran
// SampleRenderer::createGLView (renderer initialization)
// and the other SampleRenderer::emitEvents (processing ESC key event).
// Apparently connecting the glView to the window interfers with
// OSX event processing for some reason.
#define SEPARATE_EVENT_LOOP 0
#else
#define SEPARATE_EVENT_LOOP 1
#endif
static PhysXSampleApplication* gApp = NULL;
static SampleSetup gSettings;
static SampleCommandLine* gSampleCommandLine = NULL;
void mainInitialize()
{
PX_ASSERT(gSampleCommandLine);
const SampleCommandLine& cmdline = *gSampleCommandLine;
initSampleAllocator();
gApp = SAMPLE_NEW(PhysXSampleApplication)(cmdline);
gApp->customizeSample(gSettings);
if (gApp->isOpen())
gApp->close();
gApp->open(gSettings.mWidth, gSettings.mHeight, gSettings.mName, gSettings.mFullscreen);
#if SEPARATE_EVENT_LOOP
gApp->start(Ps::Thread::getDefaultStackSize());
#else
if(gApp->isOpen()) gApp->onOpen();
#endif
}
void mainTerminate()
{
DELETESINGLE(gApp);
DELETESINGLE(gSampleCommandLine);
releaseSampleAllocator();
}
bool mainContinue()
{
if (gApp->isOpen() && !gApp->isCloseRequested())
{
if(gApp->getInputMutex().trylock())
{
gApp->handleMouseVisualization();
gApp->doInput();
gApp->update();
#if !SEPARATE_EVENT_LOOP
gApp->updateEngine();
#endif
gApp->getInputMutex().unlock();
}
Ps::Thread::sleep(1);
return true;
}
#if SEPARATE_EVENT_LOOP
gApp->signalQuit();
gApp->waitForQuit();
#else
if (gApp->isOpen() || gApp->isCloseRequested())
gApp->close();
#endif
return false;
}
void mainLoop()
{
while(mainContinue());
}
#if defined(RENDERER_WINDOWS)
int main()
{
gSampleCommandLine = new SampleCommandLine(GetCommandLineA());
mainInitialize();
mainLoop();
mainTerminate();
return 0;
}
#elif defined(RENDERER_LINUX)
int main(int argc, const char *const* argv)
{
char* commandString = NULL;
PxU32 commandLen = 0;
const char* specialCommand = "--noXterm";
const char* xtermCommand = "xterm -e ";
bool foundSpecial = false;
for(PxU32 i = 0; i < (PxU32)argc; i++)
{
foundSpecial = foundSpecial || (::strncmp(argv[i], specialCommand, ::strlen(specialCommand)) == 0);
commandLen += ::strlen(argv[i]);
}
// extend command line if not chosen differently
// and start again with terminal as parent
if(!foundSpecial)
{
// increase size by new commands, spaces between commands and string terminator
commandLen += ::strlen(xtermCommand) + ::strlen(specialCommand) + argc + 3;
commandString = (char*)::malloc(commandLen * sizeof(char));
::strcpy(commandString, xtermCommand);
for(PxU32 i = 0; i < (PxU32)argc; i++)
{
::strcat(commandString, argv[i]);
::strcat(commandString, " ");
}
::strcat(commandString, specialCommand);
int ret = ::system(commandString);
::free(commandString);
if(ret < 0)
shdfnd::printFormatted("Failed to run %s! If xterm is missing, try running with this parameter: %s\n", argv[0], specialCommand);
}
else
{
gSampleCommandLine = new SampleCommandLine((unsigned int)(argc), argv);
mainInitialize();
mainLoop();
mainTerminate();
}
return 0;
}
#else
int main(int argc, const char *const* argv)
{
gSampleCommandLine = new SampleCommandLine((unsigned int)argc, argv);
mainInitialize();
mainLoop();
mainTerminate();
return 0;
}
#endif

View File

@ -0,0 +1,107 @@
//
// 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.
// Mouse filter from ICE, refactored a bit
#include "SampleMouseFilter.h"
MouseFilter::MouseFilter() :
mWeightModifier (0.0f),
mHistoryBufferLength (0),
mHistoryBufferX (NULL),
mHistoryBufferY (NULL)
{
}
MouseFilter::MouseFilter(PxU32 length, PxReal weightModifier)
{
mWeightModifier = weightModifier;
mHistoryBufferLength = 0;
mHistoryBufferX = NULL;
mHistoryBufferY = NULL;
SetHistoryBufferLength(length);
}
MouseFilter::~MouseFilter()
{
SAMPLE_FREE(mHistoryBufferX);
SAMPLE_FREE(mHistoryBufferY);
}
bool MouseFilter::SetHistoryBufferLength(PxU32 length)
{
SAMPLE_FREE(mHistoryBufferX);
SAMPLE_FREE(mHistoryBufferY);
mHistoryBufferLength = length;
if(length)
{
mHistoryBufferX = (float*)SAMPLE_ALLOC(sizeof(float)*length);
memset(mHistoryBufferX, 0, length*sizeof(float));
mHistoryBufferY = (float*)SAMPLE_ALLOC(sizeof(float)*length);
memset(mHistoryBufferY, 0, length*sizeof(float));
}
return true;
}
void MouseFilter::Apply(PxReal& deltaMouseX, PxReal& deltaMouseY)
{
// Checkings
if(!mHistoryBufferX || !mHistoryBufferY) return;
// Shift the buffer around. If you want performance from this, be sure
// to use a circular buffer than these slow memmove()s.
memmove(mHistoryBufferX+1, mHistoryBufferX, (mHistoryBufferLength-1)*sizeof(PxReal));
memmove(mHistoryBufferY+1, mHistoryBufferY, (mHistoryBufferLength-1)*sizeof(PxReal));
// Put the current values at the front of the history buffer
*mHistoryBufferX = deltaMouseX;
*mHistoryBufferY = deltaMouseY;
// Filter the mouse
PxReal CurAverageX = 0.0f;
PxReal CurAverageY = 0.0f;
PxReal AverageTot = 0.0f;
PxReal CurrentWeight = 1.0f;
for(PxU32 i=0;i<mHistoryBufferLength;i++)
{
CurAverageX += mHistoryBufferX[i] * CurrentWeight;
CurAverageY += mHistoryBufferY[i] * CurrentWeight;
// Note! Our total is also weighted
AverageTot += 1.0f * CurrentWeight;
// The weight for the next entry in the history buffer
CurrentWeight *= mWeightModifier;
}
// Calculate the final weighted value
deltaMouseX = CurAverageX / AverageTot;
deltaMouseY = CurAverageY / AverageTot;
}

View File

@ -0,0 +1,56 @@
//
// 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_MOUSE_FILTER_H
#define SAMPLE_MOUSE_FILTER_H
#include "SampleAllocator.h"
class MouseFilter : public SampleAllocateable
{
public:
MouseFilter();
MouseFilter(PxU32 length, PxReal weightModifier);
~MouseFilter();
PX_INLINE PxReal GetWeightModifier() const { return mWeightModifier; }
PX_INLINE void SetWeightModifier(PxReal modifier) { mWeightModifier = modifier; }
PX_INLINE PxU32 GetHistoryBufferLength() const { return mHistoryBufferLength; }
bool SetHistoryBufferLength(PxU32 length);
void Apply(PxReal& deltaMouseX, PxReal& deltaMouseY);
private:
PxReal mWeightModifier;
PxU32 mHistoryBufferLength;
PxReal* mHistoryBufferX;
PxReal* mHistoryBufferY;
};
#endif

View File

@ -0,0 +1,34 @@
//
// 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_PREPROCESSOR_H
#define SAMPLE_PREPROCESSOR_H
#endif

View File

@ -0,0 +1,92 @@
//
// 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 "SampleRandomPrecomputed.h"
#include "PhysXSample.h"
#include "SampleAllocator.h"
#include "PxTkStream.h"
using namespace PxToolkit;
#define WRITE_SEQUENCE 0
PX_FORCE_INLINE PxF32 flip(const PxF32* v)
{
const PxU8* b = (const PxU8*)v;
PxF32 f;
PxU8* bf = (PxU8*)&f;
bf[0] = b[3];
bf[1] = b[2];
bf[2] = b[1];
bf[3] = b[0];
return f;
}
SampleRandomPrecomputed::SampleRandomPrecomputed(PhysXSample& app)
: mPrecomputedRandomSequence(NULL),
mPrecomputedRandomSequenceCount(0)
{
mPrecomputedRandomSequence = (PxF32*)SAMPLE_ALLOC(sizeof(PxF32)*(PRECOMPUTED_RANDOM_SEQUENCE_SIZE+1));
#if WRITE_SEQUENCE
char buffer[256];
const char* filename = getSampleOutputDirManager().getFilePath("SampleBaseRandomSequence", buffer, false);
const PxF32 denom = (1.0f / float(RAND_MAX));
for(PxU32 i=0;i<PRECOMPUTED_RANDOM_SEQUENCE_SIZE;i++)
{
mPrecomputedRandomSequence[i] = float(rand()) * denom;
}
mPrecomputedRandomSequence[PRECOMPUTED_RANDOM_SEQUENCE_SIZE]=1.0f;
PxDefaultFileOutputStream stream(filename);
stream.write(mPrecomputedRandomSequence,sizeof(PxF32)*(PRECOMPUTED_RANDOM_SEQUENCE_SIZE+1));
#else
const char* filename = getSampleMediaFilename("SampleBaseRandomSequence");
PxDefaultFileInputData stream(filename);
if(!stream.isValid())
app.fatalError("SampleBaseRandomSequence file not found");
stream.read(mPrecomputedRandomSequence,sizeof(PxF32)*(PRECOMPUTED_RANDOM_SEQUENCE_SIZE+1));
const bool mismatch = (1.0f != mPrecomputedRandomSequence[PRECOMPUTED_RANDOM_SEQUENCE_SIZE]);
if(mismatch)
{
for(PxU32 i=0;i<PRECOMPUTED_RANDOM_SEQUENCE_SIZE;i++)
{
mPrecomputedRandomSequence[i]=flip(&mPrecomputedRandomSequence[i]);
}
}
#endif
}
SampleRandomPrecomputed::~SampleRandomPrecomputed()
{
SAMPLE_FREE(mPrecomputedRandomSequence);
mPrecomputedRandomSequenceCount=0;
}

View File

@ -0,0 +1,64 @@
//
// 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_RANDOM_PRECOMPUTED_H
#define SAMPLE_RANDOM_PRECOMPUTED_H
#include "common/PxPhysXCommonConfig.h"
#include "foundation/PxAssert.h"
using namespace physx;
class PhysXSample;
class SampleRandomPrecomputed
{
public:
SampleRandomPrecomputed(PhysXSample& app);
~SampleRandomPrecomputed();
PxF32 getRandom() const {return mPrecomputedRandomSequence[(mPrecomputedRandomSequenceCount++) % PRECOMPUTED_RANDOM_SEQUENCE_SIZE];}
PxF32 getRandomInRange(const PxF32 a, const PxF32 b)
{
PX_ASSERT(b>a);
return a + (b-a)*getRandom();
}
private:
enum
{
PRECOMPUTED_RANDOM_SEQUENCE_SIZE=65536
};
PxF32* mPrecomputedRandomSequence;
mutable PxU32 mPrecomputedRandomSequenceCount;
};
#endif //SAMPLE_RANDOM_PRECOMPUTED_H

View File

@ -0,0 +1,206 @@
//
// 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 "SampleStepper.h"
#include "PhysXSample.h"
#include "PxScene.h"
bool DebugStepper::advance(PxScene* scene, PxReal dt, void* scratchBlock, PxU32 scratchBlockSize)
{
mTimer.getElapsedSeconds();
{
PxSceneWriteLock writeLock(*scene);
scene->simulate(mStepSize, NULL, scratchBlock, scratchBlockSize);
}
return true;
}
void DebugStepper::wait(PxScene* scene)
{
mSample->onSubstepPreFetchResult();
{
PxSceneWriteLock writeLock(*scene);
scene->fetchResults(true, NULL);
}
mSimulationTime = (PxReal)mTimer.getElapsedSeconds();
mSample->onSubstep(mStepSize);
}
void StepperTask::run()
{
mStepper->substepDone(this);
release();
}
void StepperTaskSimulate::run()
{
mStepper->simulate(mCont);
mStepper->getSample().onSubstepStart(mStepper->getSubStepSize());
}
void MultiThreadStepper::simulate(physx::PxBaseTask* ownerTask)
{
PxSceneWriteLock writeLock(*mScene);
mScene->simulate(mSubStepSize, ownerTask, mScratchBlock, mScratchBlockSize);
}
void MultiThreadStepper::renderDone()
{
if(mFirstCompletionPending)
{
mCompletion0.removeReference();
mFirstCompletionPending = false;
}
}
bool MultiThreadStepper::advance(PxScene* scene, PxReal dt, void* scratchBlock, PxU32 scratchBlockSize)
{
mScratchBlock = scratchBlock;
mScratchBlockSize = scratchBlockSize;
if(!mSync)
mSync = SAMPLE_NEW(PsSyncAlloc);
substepStrategy(dt, mNbSubSteps, mSubStepSize);
if(mNbSubSteps == 0) return false;
mScene = scene;
mSync->reset();
mCurrentSubStep = 1;
mCompletion0.setContinuation(*mScene->getTaskManager(), NULL);
mSimulationTime = 0.0f;
mTimer.getElapsedSeconds();
// take first substep
substep(mCompletion0);
mFirstCompletionPending = true;
return true;
}
void MultiThreadStepper::substepDone(StepperTask* ownerTask)
{
mSample->onSubstepPreFetchResult();
{
#if !PX_PROFILE
PxSceneWriteLock writeLock(*mScene);
#endif
mScene->fetchResults(true);
}
PxReal delta = (PxReal)mTimer.getElapsedSeconds();
mSimulationTime += delta;
mSample->onSubstep(mSubStepSize);
if(mCurrentSubStep>=mNbSubSteps)
{
mSync->set();
}
else
{
StepperTask &s = ownerTask == &mCompletion0 ? mCompletion1 : mCompletion0;
s.setContinuation(*mScene->getTaskManager(), NULL);
mCurrentSubStep++;
mTimer.getElapsedSeconds();
substep(s);
// after the first substep, completions run freely
s.removeReference();
}
}
void MultiThreadStepper::substep(StepperTask& completionTask)
{
// setup any tasks that should run in parallel to simulate()
mSample->onSubstepSetup(mSubStepSize, &completionTask);
// step
{
mSimulateTask.setContinuation(&completionTask);
mSimulateTask.removeReference();
}
// parallel sample tasks are started in mSolveTask (after solve was called which acquires a write lock).
}
void FixedStepper::substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize)
{
if(mAccumulator > mFixedSubStepSize)
mAccumulator = 0.0f;
// don't step less than the step size, just accumulate
mAccumulator += stepSize;
if(mAccumulator < mFixedSubStepSize)
{
substepCount = 0;
return;
}
substepSize = mFixedSubStepSize;
substepCount = PxMin(PxU32(mAccumulator/mFixedSubStepSize), mMaxSubSteps);
mAccumulator -= PxReal(substepCount)*substepSize;
}
void VariableStepper::substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize)
{
if(mAccumulator > mMaxSubStepSize)
mAccumulator = 0.0f;
// don't step less than the min step size, just accumulate
mAccumulator += stepSize;
if(mAccumulator < mMinSubStepSize)
{
substepCount = 0;
return;
}
substepCount = PxMin(PxU32(PxCeil(mAccumulator/mMaxSubStepSize)), mMaxSubSteps);
substepSize = PxMin(mAccumulator/substepCount, mMaxSubStepSize);
mAccumulator -= PxReal(substepCount)*substepSize;
}

View File

@ -0,0 +1,229 @@
//
// 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_STEPPER_H
#define SAMPLE_STEPPER_H
#include "SampleAllocator.h"
#include "SampleAllocatorSDKClasses.h"
#include "RendererMemoryMacros.h"
#include "task/PxTask.h"
#include "PxPhysicsAPI.h"
#include "PsTime.h"
class PhysXSample;
class Stepper: public SampleAllocateable
{
public:
Stepper() : mSample(NULL) {}
virtual ~Stepper() {}
virtual bool advance(PxScene* scene, PxReal dt, void* scratchBlock, PxU32 scratchBlockSize) = 0;
virtual void wait(PxScene* scene) = 0;
virtual void substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize) = 0;
virtual void postRender(const PxReal stepSize) = 0;
virtual void setSubStepper(const PxReal stepSize, const PxU32 maxSteps) {}
virtual void renderDone() {}
virtual void shutdown() {}
PxReal getSimulationTime() const { return mSimulationTime; }
PhysXSample& getSample() { return *mSample; }
const PhysXSample& getSample() const { return *mSample; }
void setSample(PhysXSample* sample) { mSample = sample; }
protected:
PhysXSample* mSample;
Ps::Time mTimer;
PxReal mSimulationTime;
};
class MultiThreadStepper;
class StepperTask : public physx::PxLightCpuTask
{
public:
void setStepper(MultiThreadStepper* stepper) { mStepper = stepper; }
MultiThreadStepper* getStepper() { return mStepper; }
const MultiThreadStepper* getStepper() const { return mStepper; }
const char* getName() const { return "Stepper Task"; }
void run();
protected:
MultiThreadStepper* mStepper;
};
class StepperTaskSimulate : public StepperTask
{
public:
StepperTaskSimulate(){}
void run();
};
class MultiThreadStepper : public Stepper
{
public:
MultiThreadStepper()
: mFirstCompletionPending(false)
, mScene(NULL)
, mSync(NULL)
, mCurrentSubStep(0)
, mNbSubSteps(0)
{
mCompletion0.setStepper(this);
mCompletion1.setStepper(this);
mSimulateTask.setStepper(this);
}
~MultiThreadStepper() {}
virtual bool advance(PxScene* scene, PxReal dt, void* scratchBlock, PxU32 scratchBlockSize);
virtual void substepDone(StepperTask* ownerTask);
virtual void renderDone();
virtual void postRender(const PxReal stepSize){}
// if mNbSubSteps is 0 then the sync will never
// be set so waiting would cause a deadlock
virtual void wait(PxScene* scene) { if(mNbSubSteps && mSync)mSync->wait(); }
virtual void shutdown() { DELETESINGLE(mSync); }
virtual void reset() = 0;
virtual void substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize) = 0;
virtual void simulate(physx::PxBaseTask* ownerTask);
PxReal getSubStepSize() const { return mSubStepSize; }
protected:
void substep(StepperTask& completionTask);
// we need two completion tasks because when multistepping we can't submit completion0 from the
// substepDone function which is running inside completion0
bool mFirstCompletionPending;
StepperTaskSimulate mSimulateTask;
StepperTask mCompletion0, mCompletion1;
PxScene* mScene;
PsSyncAlloc* mSync;
PxU32 mCurrentSubStep;
PxU32 mNbSubSteps;
PxReal mSubStepSize;
void* mScratchBlock;
PxU32 mScratchBlockSize;
};
class DebugStepper : public Stepper
{
public:
DebugStepper(const PxReal stepSize) : mStepSize(stepSize) {}
virtual void substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize)
{
substepCount = 1;
substepSize = mStepSize;
}
virtual bool advance(PxScene* scene, PxReal dt, void* scratchBlock, PxU32 scratchBlockSize);
virtual void postRender(const PxReal stepSize)
{
}
virtual void setSubStepper(const PxReal stepSize, const PxU32 maxSteps)
{
mStepSize = stepSize;
}
virtual void wait(PxScene* scene);
PxReal mStepSize;
};
// The way this should be called is:
// bool stepped = advance(dt)
//
// ... reads from the scene graph for rendering
//
// if(stepped) renderDone()
//
// ... anything that doesn't need access to the physics scene
//
// if(stepped) sFixedStepper.wait()
//
// Note that per-substep callbacks to the sample need to be issued out of here,
// between fetchResults and simulate
class FixedStepper : public MultiThreadStepper
{
public:
FixedStepper(const PxReal subStepSize, const PxU32 maxSubSteps)
: MultiThreadStepper()
, mAccumulator(0)
, mFixedSubStepSize(subStepSize)
, mMaxSubSteps(maxSubSteps)
{
}
virtual void substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize);
virtual void reset() { mAccumulator = 0.0f; }
virtual void setSubStepper(const PxReal stepSize, const PxU32 maxSteps) { mFixedSubStepSize = stepSize; mMaxSubSteps = maxSteps;}
virtual void postRender(const PxReal stepSize)
{
}
PxReal mAccumulator;
PxReal mFixedSubStepSize;
PxU32 mMaxSubSteps;
};
class VariableStepper : public MultiThreadStepper
{
public:
VariableStepper(const PxReal minSubStepSize, const PxReal maxSubStepSize, const PxU32 maxSubSteps)
: MultiThreadStepper()
, mAccumulator(0)
, mMinSubStepSize(minSubStepSize)
, mMaxSubStepSize(maxSubStepSize)
, mMaxSubSteps(maxSubSteps)
{
}
virtual void substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize);
virtual void reset() { mAccumulator = 0.0f; }
private:
VariableStepper& operator=(const VariableStepper&);
PxReal mAccumulator;
const PxReal mMinSubStepSize;
const PxReal mMaxSubStepSize;
const PxU32 mMaxSubSteps;
};
#endif

View File

@ -0,0 +1,61 @@
//
// 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_USER_INPUT_DEFINES_H
#define SAMPLE_UTILS_H
#if defined(RENDERER_WINDOWS)
#define DIGITAL_INPUT_EVENT_DEF(var, winKey, osxKey, linuxKey) {\
const SampleFramework::InputEvent* retVal = SampleFramework::SamplePlatform::platform()->getSampleUserInput()->registerInputEvent(SampleFramework::InputEvent(var, false),winKey, #var); \
if(retVal) inputEvents.push_back(retVal); }
#define ANALOG_INPUT_EVENT_DEF(var, sensitivity, winKey, osxKey, linuxKey) {\
const SampleFramework::InputEvent* retVal = (SampleFramework::SamplePlatform::platform()->getSampleUserInput()->registerInputEvent(SampleFramework::InputEvent(var, true,sensitivity),winKey, #var)); \
if(retVal) inputEvents.push_back(retVal); }
#elif defined (RENDERER_MACOSX)
#define DIGITAL_INPUT_EVENT_DEF(var, winKey, osxKey, linuxKey) {\
const SampleFramework::InputEvent* retVal = (SampleFramework::SamplePlatform::platform()->getSampleUserInput()->registerInputEvent(SampleFramework::InputEvent(var, false),osxKey, #var)); \
if(retVal) inputEvents.push_back(retVal); }
#define ANALOG_INPUT_EVENT_DEF(var, sensitivity, winKey, osxKey, linuxKey) {\
const SampleFramework::InputEvent* retVal = (SampleFramework::SamplePlatform::platform()->getSampleUserInput()->registerInputEvent(SampleFramework::InputEvent(var, true,sensitivity),osxKey, #var)); \
if(retVal) inputEvents.push_back(retVal); }
#elif defined (RENDERER_LINUX)
#define DIGITAL_INPUT_EVENT_DEF(var, winKey, osxKey, linuxKey) {\
const SampleFramework::InputEvent* retVal = (SampleFramework::SamplePlatform::platform()->getSampleUserInput()->registerInputEvent(SampleFramework::InputEvent(var, false),linuxKey, #var)); \
if(retVal) inputEvents.push_back(retVal); }
#define ANALOG_INPUT_EVENT_DEF(var, sensitivity, winKey, osxKey, linuxKey) {\
const SampleFramework::InputEvent* retVal = (SampleFramework::SamplePlatform::platform()->getSampleUserInput()->registerInputEvent(SampleFramework::InputEvent(var, true,sensitivity),linuxKey, #var)); \
if(retVal) inputEvents.push_back(retVal); }
#endif
#endif

View File

@ -0,0 +1,47 @@
//
// 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_UTILS_H
#define SAMPLE_UTILS_H
#include "common/PxPhysXCommonConfig.h"
#include "foundation/PxVec3.h"
#include "PsMathUtils.h"
//Integer representation of a floating-point value.
#define PX_IR(x) ((PxU32&)(x))
// PT: TODO: move those helpers to a shared place, this is also used in the SDK
PX_INLINE PxReal degtorad(PxReal d)
{
return d * PxPi / 180.0f;
}
#endif

View File

@ -0,0 +1,39 @@
//
// 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 "Ps.h"
//! \file top level test include file
/* namespace trickery */
namespace physx
{
// alias shared foundation to something usable
namespace Ps = shdfnd;
}
// we need this until all our code lives in physx namespace
using namespace physx;

View File

@ -0,0 +1,43 @@
//
// 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 "TestGeometryHelpers.h"
#include "geometry/PxBoxGeometry.h"
#include "geometry/PxSphereGeometry.h"
#include "geometry/PxCapsuleGeometry.h"
#include "geometry/PxPlaneGeometry.h"
#include "geometry/PxConvexMeshGeometry.h"
#include "geometry/PxTriangleMeshGeometry.h"
#include "geometry/PxHeightFieldGeometry.h"
bool Test::GeometryHelpers::testForOverlap(const PxShape& s0, const PxGeometry& g1, const PxTransform& globalPose1)
{
return PxGeometryQuery::overlap(g1, globalPose1, s0.getGeometry().any(), PxShapeExt::getGlobalPose(s0, *s0.getActor()));
}

View File

@ -0,0 +1,49 @@
//
// 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 TEST_GEOMETRY_HELPERS_H
#define TEST_GEOMETRY_HELPERS_H
#include "PxShape.h"
#include "extensions/PxShapeExt.h"
#include "geometry/PxGeometryQuery.h"
#include "Test.h"
namespace Test
{
class GeometryHelpers
{
public:
static bool testForOverlap(const PxShape& s0, const PxShape& s1);
static bool testForOverlap(const PxShape& s0, const PxGeometry& g1, const PxTransform& globalPose1);
};
}
#endif

View File

@ -0,0 +1,315 @@
//
// 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 "TestGroup.h"
#include <stdio.h>
#include <string.h>
Test::TestGroup::TestGroup(const char* name, size_t count)
: mTest(NULL)
, mParent(NULL)
{
if (MAX_COUNT == count)
count = strlen(name);
mName = new char[count + 1];
strncpy(mName, name, count);
mName[count] = '\0';
}
Test::TestGroup::TestGroup(TestGroup* group)
: mTest(group->mTest)
, mParent(NULL)
{
mName = new char[strlen(group->getName()) + 1];
strcpy(mName, group->getName());
}
Test::TestGroup::TestGroup(SampleCreator test, const char* name, size_t count)
: mTest(test)
, mParent(NULL)
{
PX_ASSERT(test);
if (MAX_COUNT == count)
count = strlen(name);
mName = new char[count + 1];
strncpy(mName, name, count);
mName[count] = '\0';
}
Test::TestGroup::~TestGroup()
{
if (!isTest())
{
for (PxU32 i = 0; i < mChildren.size(); i++)
delete mChildren[i];
delete[] mName;
}
}
void Test::TestGroup::getPath(SampleArray<TestGroup*>& path)
{
if (getParent())
getParent()->getPath(path);
path.pushBack(this);
}
void Test::TestGroup::getPathName(char* strBuffer, unsigned strBufferMaxLength, bool omitRoot)
{
SampleArray<TestGroup*> path;
getPath(path);
unsigned charCount = 1; //\0
for (unsigned i = omitRoot ? 1 : 0; i < path.size(); ++i)
{
const TestGroup& node = *path[i];
unsigned nodeNameLength = unsigned(strlen(node.getName()));
if (node.getFirstChild())
nodeNameLength += 1;
if (charCount + nodeNameLength < strBufferMaxLength)
{
sprintf(strBuffer + (charCount - 1), "%s%s", node.getName(), node.getFirstChild() ? "/" : "");
charCount += nodeNameLength;
}
}
}
Test::TestGroup* Test::TestGroup::getGroupFromPathName(const char* pathName, bool omitRoot)
{
if (!omitRoot || getParent())
{
if (strstr(pathName, getName()) != pathName)
return NULL;
pathName += strlen(getName());
if (getFirstChild())
{
if (strstr(pathName, "/") != pathName)
return NULL;
pathName += strlen("/");
}
else
{
if (pathName[0] == '\0')
return this;
else
return NULL;
}
}
for (unsigned i = 0; i < mChildren.size(); ++i)
{
TestGroup* group = mChildren[i]->getGroupFromPathName(pathName, omitRoot);
if (group)
return group;
}
return NULL;
}
void Test::TestGroup::addTest(SampleCreator test, const char* name, size_t count)
{
PX_ASSERT(!isTest() && test);
TestGroup* testGroup = new TestGroup(test, name, count);
addGroup(testGroup);
}
void Test::TestGroup::addGroup(TestGroup* group)
{
PX_ASSERT(group && !group->getParent());
mChildren.pushBack(group);
group->mParent = this;
}
Test::TestGroup* Test::TestGroup::deepCopy()
{
TestGroup* groupCopy = new TestGroup(this);
for (unsigned i = 0; i < mChildren.size(); i++)
{
TestGroup* childCopy = mChildren[i]->deepCopy();
groupCopy->addGroup(childCopy);
}
return groupCopy;
}
Test::TestGroup* Test::TestGroup::addPath(SampleArray<TestGroup*>& path)
{
if (path.size() == 0)
return NULL;
TestGroup* current = this;
for (unsigned i = 0; i < path.size(); i++)
{
TestGroup* pathGroup = path[i];
TestGroup* child = current->getChildByName(pathGroup->getName());
if (!child)
{
child = new TestGroup(pathGroup);
current->addGroup(child);
}
current = child;
}
return current;
}
Test::TestGroup* Test::TestGroup::getNextChild(TestGroup& current)
{
int nextIndex = getChildIndex(current) + 1;
if (nextIndex >= int(mChildren.size()))
return NULL;
return mChildren[nextIndex];
}
Test::TestGroup* Test::TestGroup::getPreviousChild(TestGroup& current)
{
int prevIndex = getChildIndex(current) - 1;
if (prevIndex < 0)
return NULL;
return mChildren[prevIndex];
}
Test::TestGroup* Test::TestGroup::getChildByName(const char* name, size_t count)
{
if (MAX_COUNT == count)
count = strlen(name) + 1;
for (unsigned i = 0; i < mChildren.size(); i++)
{
if (strncmp(mChildren[i]->getName(), name, count) == 0)
return mChildren[i];
}
return NULL;
}
Test::TestGroup* Test::TestGroup::getFirstTest()
{
TestGroup* current = getFirstLeaf();
if (!current || current->isTest())
return current;
return getNextTest(current);
}
Test::TestGroup* Test::TestGroup::getLastTest()
{
TestGroup* current = getLastLeaf();
if (!current || current->isTest())
return current;
return getPreviousTest(current);
}
Test::TestGroup* Test::TestGroup::getNextTest(TestGroup* current)
{
current = getNextLeaf(current);
while (current && !current->isTest())
current = getNextLeaf(current);
return current;
}
Test::TestGroup* Test::TestGroup::getPreviousTest(TestGroup* current)
{
current = getPreviousLeaf(current);
while (current && !current->isTest())
current = getPreviousLeaf(current);
return current;
}
unsigned Test::TestGroup::getChildIndex(TestGroup& child)
{
PX_ASSERT(!isTest());
TestGroup** p = mChildren.find(&child);
PX_ASSERT(p != mChildren.end());
return unsigned(p - mChildren.begin());
}
Test::TestGroup* Test::TestGroup::getFirstLeaf()
{
TestGroup* firstChild = getFirstChild();
if (!firstChild)
return this;
return firstChild->getFirstLeaf();
}
Test::TestGroup* Test::TestGroup::getLastLeaf()
{
TestGroup* lastChild = getLastChild();
if (!lastChild)
return this;
return lastChild->getLastLeaf();
}
Test::TestGroup* Test::TestGroup::getNextLeaf(TestGroup* current)
{
PX_ASSERT(current);
if (current == this)
return NULL;
TestGroup* parent = current->getParent();
if (!parent)
return NULL;
TestGroup* nextSibling = parent->getNextChild(*current);
if (nextSibling)
return nextSibling->getFirstLeaf();
else
return getNextLeaf(parent);
}
Test::TestGroup* Test::TestGroup::getPreviousLeaf(TestGroup* current)
{
PX_ASSERT(current);
if (current == this)
return NULL;
TestGroup* parent = current->getParent();
if (!parent)
return NULL;
TestGroup* prevSibling = parent->getPreviousChild(*current);
if (prevSibling)
return prevSibling->getLastLeaf();
else
return getPreviousLeaf(parent);
}

View File

@ -0,0 +1,201 @@
//
// 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 TEST_CATEGORY
#define TEST_CATEGORY
#include "PhysXSampleApplication.h"
#include "SampleArray.h"
namespace Test
{
/**
Group of tests. The groups can be linked to a tree.
If a test is added to a group, a leaf group is automatically created, that
contains the test.
*/
class TestGroup
{
static const size_t MAX_COUNT = ~0;
public:
explicit TestGroup(const char* name, size_t count = MAX_COUNT);
explicit TestGroup(TestGroup* group);
TestGroup(SampleCreator test, const char* name, size_t count = MAX_COUNT);
~TestGroup();
/**
Releases all tests from this node and its descendants.
Destructing a Test groups just releases the groups and not the tests themselves!
*/
// void releaseTests();
/**
Returns the name of the TestGroup. If the test group represents a single
test, the name of the test is returned instead.
*/
const char* getName() const { return mName; }
/**
Prints all the TestGroup names to strBuffer in this format:
"RootName/Name1/Name2/.../ThisName"
With omitRoot the root TestGroup is omitted.
*/
void getPathName(char* strBuffer, unsigned strBufferMaxLength, bool omitRoot);
/**
Adds a child TestGroup to this TestGroup. After this call the group is owned by this.
A TestGroup can't be added multiple times.
*/
void addGroup(TestGroup* group);
/**
Deep copy of all the group data, except the tests themselves. The copy is returned as a root.
*/
TestGroup* deepCopy();
/**
Adds a copy of path to this group avoiding duplicates. Returns the copy of the last element in path.
*/
TestGroup* addPath(SampleArray<TestGroup*>& path);
/**
Fills all TestGroup instances into path starting with this->getRoot() and ending with this.
*/
void getPath(SampleArray<TestGroup*>& path);
/**
Reads a path from pathName and returns the corresponding TestGroup.
The format of the path has to be the same as the one used by getPathName().
If the TestGroup doesn't exist, NULL is returned.
*/
TestGroup* getGroupFromPathName(const char* pathName, bool omitRoot);
/**
Returns whether this TestGroup corresponds to a single test.
*/
bool isTest() const { return mTest != NULL; }
/**
Automatically creates a child TestGroup representing the test passed. A TestInterface instance
shouldn't be added multiple times, since it is owned by this TestGroup after the call.
*/
void addTest(SampleCreator test, const char* name, size_t count = MAX_COUNT);
/**
Returns the TestInterface for a TestGroup corresponding to a single test.
*/
// TestInterface& getTestInterface() { PX_ASSERT(isTest()); return *mTest; }
SampleCreator getCreator() { PX_ASSERT(isTest()); return mTest; }
/**
Returns the parent TestGroup, if this isn't a root.
*/
TestGroup* getParent() const { return mParent; }
/**
Returns the root of this TestGroup.
*/
TestGroup* getRoot() { return mParent ? mParent->getRoot() : this; }
/**
Returns the first direct child of this TestGroup. If this TestGroup doesn't has
any children, NULL is returned.
*/
TestGroup* getFirstChild() const { return mChildren.empty() ? NULL : mChildren.front(); }
/**
Returns the last direct child of this TestGroup. If this TestGroup doesn't has
any children, NULL is returned.
*/
TestGroup* getLastChild() const { return mChildren.empty() ? NULL : mChildren.back(); }
/**
Returns the next direct child of this TestGroup after current. If there is no next child, NULL is returned.
The TestGroup current has to be itself a direct child of this Testgroup.
*/
TestGroup* getNextChild(TestGroup& current);
/**
Returns the previous direct child of this TestGroup after current. If there is no previous child, NULL is returned.
The TestGroup current has to be itself a direct child of this Testgroup.
*/
TestGroup* getPreviousChild(TestGroup& current);
/**
Returns the child with the given name, if exists.
*/
TestGroup* getChildByName(const char* name, size_t count = MAX_COUNT);
/**
Returns the first TestGroup representing a single test (isTest() == true) within
the whole test group tree rooted at this TestGroup. Returns NULL if there isn't such
a TestGroup.
*/
TestGroup* getFirstTest();
/**
Returns the last TestGroup representing a single test (isTest() == true) within
the whole test group tree rooted at this TestGroup. Returns NULL if there isn't such
a TestGroup.
*/
TestGroup* getLastTest();
/**
Returns the next TestGroup representing a single test (isTest() == true) within
the whole test group tree rooted at this TestGroup. The current TestGroup has to be
a descendant of this TestGroup.
*/
TestGroup* getNextTest(TestGroup* current);
/**
Returns the previous TestGroup representing a single test (isTest() == true) within
the whole test group tree rooted at this TestGroup. The current TestGroup has to be
a descendant of this TestGroup.
*/
TestGroup* getPreviousTest(TestGroup* current);
/**
Returns the number of children
*/
PxU32 numChildren() const { return mChildren.size(); }
private:
unsigned getChildIndex(TestGroup& child);
TestGroup* getFirstLeaf();
TestGroup* getLastLeaf();
TestGroup* getNextLeaf(TestGroup* current);
TestGroup* getPreviousLeaf(TestGroup* current);
private:
SampleCreator mTest;
char* mName;
SampleArray<TestGroup*> mChildren;
TestGroup* mParent;
};
};
#endif // TEST_CATEGORY

View File

@ -0,0 +1,108 @@
//
// 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 "TestMotionGenerator.h"
//----------------------------------------------------------------------------//
MotionGenerator::MotionGenerator()
: mLinear(0.0f),
mAngular(0.0f),
mTransform(PxTransform(PxIdentity))
{
}
//----------------------------------------------------------------------------//
MotionGenerator::MotionGenerator(const PxTransform &pose, const PxVec3& linear, const PxVec3& angular)
: mLinear(linear),
mAngular(angular),
mTransform(pose)
{
}
//----------------------------------------------------------------------------//
PxVec3 MotionGenerator::getLinearVelocity( float time )
{
float t = time - (int(time) & ~0xf);
const float scale = 0.25f * PxPi;
if(t > 0 && t < 2)
return -scale * sinf(t * 0.5f * PxPi) * mLinear;
if(t > 8 && t < 10)
return +scale * sinf(t * 0.5f * PxPi) * mLinear;
return PxVec3(0.0f);
}
//----------------------------------------------------------------------------//
PxVec3 MotionGenerator::getAngularVelocity( float time )
{
float t = time - (int(time) & ~0xf);
if(t > 4 && t < 6)
return +PxPi * mAngular;
if(t > 12 && t < 14)
return -PxPi * mAngular;
return PxVec3(0.0f);
}
static PxQuat computeQuatFromAngularVelocity(const PxVec3 &omega)
{
PxReal angle = omega.magnitude();
if (angle < 1e-5f)
{
return PxQuat(PxIdentity);
} else {
PxReal s = sin( 0.5f * angle ) / angle;
PxReal x = omega[0] * s;
PxReal y = omega[1] * s;
PxReal z = omega[2] * s;
PxReal w = cos( 0.5f * angle );
return PxQuat(x,y,z,w);
}
}
//----------------------------------------------------------------------------//
const PxTransform& MotionGenerator::update(float time, float dt)
{
PxVec3 dw = dt * getAngularVelocity(time);
PxQuat dq = computeQuatFromAngularVelocity(dw);
mTransform.q = (dq * mTransform.q).getNormalized();
mTransform.p += dt * getLinearVelocity(time);
return mTransform;
}

View File

@ -0,0 +1,53 @@
//
// 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 TEST_MOTION_GENERATOR
#define TEST_MOTION_GENERATOR
#include "PxPhysicsAPI.h"
#include "Test.h"
struct MotionGenerator
{
public:
MotionGenerator();
MotionGenerator(const PxTransform &pose, const PxVec3& linear, const PxVec3& angular);
public:
const PxTransform& update(float time, float dt);
PxVec3 getLinearVelocity(float time);
PxVec3 getAngularVelocity(float time);
PxVec3 mLinear, mAngular;
PxTransform mTransform;
};
#endif // TEST_MOTION_GENERATOR

View File

@ -0,0 +1,946 @@
//
// 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "wavefront.h"
#include "FrameworkFoundation.h"
#include "PxTkFile.h"
namespace WAVEFRONT
{
/*******************************************************************/
/******************** InParser.h ********************************/
/*******************************************************************/
class InPlaceParserInterface
{
public:
virtual int ParseLine(int lineno,int argc,const char **argv) =0; // return TRUE to continue parsing, return FALSE to abort parsing process
virtual ~InPlaceParserInterface() {}
};
enum SeparatorType
{
ST_DATA, // is data
ST_HARD, // is a hard separator
ST_SOFT, // is a soft separator
ST_EOS // is a comment symbol, and everything past this character should be ignored
};
class InPlaceParser
{
public:
InPlaceParser(void)
{
Init();
}
InPlaceParser(char *data,int len)
{
Init();
SetSourceData(data,len);
}
InPlaceParser(const char *fname)
{
Init();
SetFile(fname);
}
~InPlaceParser(void);
void Init(void)
{
mQuoteChar = 34;
mData = 0;
mLen = 0;
mMyAlloc = false;
for (int i=0; i<256; i++)
{
mHard[i] = ST_DATA;
mHardString[i*2] = i;
mHardString[i*2+1] = 0;
}
mHard[0] = ST_EOS;
mHard[32] = ST_SOFT;
mHard[9] = ST_SOFT;
mHard[13] = ST_SOFT;
mHard[10] = ST_SOFT;
}
void SetFile(const char *fname); // use this file as source data to parse.
void SetSourceData(char *data,int len)
{
mData = data;
mLen = len;
mMyAlloc = false;
}
int Parse(InPlaceParserInterface *callback); // returns true if entire file was parsed, false if it aborted for some reason
int ProcessLine(int lineno,char *line,InPlaceParserInterface *callback);
const char ** GetArglist(char *source,int &count); // convert source string into an arg list, this is a destructive parse.
void SetHardSeparator(char c) // add a hard separator
{
mHard[(unsigned int)c] = ST_HARD;
}
void SetHard(char c) // add a hard separator
{
mHard[(unsigned int)c] = ST_HARD;
}
void SetCommentSymbol(char c) // comment character, treated as 'end of string'
{
mHard[(unsigned int)c] = ST_EOS;
}
void ClearHardSeparator(char c)
{
mHard[(unsigned int)c] = ST_DATA;
}
void DefaultSymbols(void); // set up default symbols for hard seperator and comment symbol of the '#' character.
bool EOS(char c)
{
if ( mHard[(unsigned int)c] == ST_EOS )
{
return true;
}
return false;
}
void SetQuoteChar(char c)
{
mQuoteChar = c;
}
private:
inline char * AddHard(int &argc,const char **argv,char *foo);
inline bool IsHard(char c);
inline char * SkipSpaces(char *foo);
inline bool IsWhiteSpace(char c);
inline bool IsNonSeparator(char c); // non seperator,neither hard nor soft
bool mMyAlloc; // whether or not *I* allocated the buffer and am responsible for deleting it.
char *mData; // ascii data to parse.
int mLen; // length of data
SeparatorType mHard[256];
char mHardString[256*2];
char mQuoteChar;
};
/*******************************************************************/
/******************** InParser.cpp ********************************/
/*******************************************************************/
void InPlaceParser::SetFile(const char* fname)
{
if ( mMyAlloc )
free(mData);
mData = 0;
mLen = 0;
mMyAlloc = false;
SampleFramework::File* fph = NULL;
PxToolkit::fopen_s(&fph, fname, "rb");
if ( fph )
{
fseek(fph,0L,SEEK_END);
mLen = (int)ftell(fph);
fseek(fph,0L,SEEK_SET);
if ( mLen )
{
mData = (char *) malloc(sizeof(char)*(mLen+1));
int ok = int(fread(mData, 1, mLen, fph));
if ( !ok )
{
free(mData);
mData = 0;
}
else
{
mData[mLen] = 0; // zero byte terminate end of file marker.
mMyAlloc = true;
}
}
fclose(fph);
}
}
InPlaceParser::~InPlaceParser(void)
{
if ( mMyAlloc )
free(mData);
}
#define MAXARGS 512
bool InPlaceParser::IsHard(char c)
{
return mHard[(unsigned int)c] == ST_HARD;
}
char * InPlaceParser::AddHard(int &argc,const char **argv,char *foo)
{
while ( IsHard(*foo) )
{
const char *hard = &mHardString[*foo*2];
if ( argc < MAXARGS )
{
argv[argc++] = hard;
}
foo++;
}
return foo;
}
bool InPlaceParser::IsWhiteSpace(char c)
{
return mHard[(unsigned int)c] == ST_SOFT;
}
char * InPlaceParser::SkipSpaces(char *foo)
{
while ( !EOS(*foo) && IsWhiteSpace(*foo) ) foo++;
return foo;
}
bool InPlaceParser::IsNonSeparator(char c)
{
if ( !IsHard(c) && !IsWhiteSpace(c) && c != 0 ) return true;
return false;
}
int InPlaceParser::ProcessLine(int lineno,char *line,InPlaceParserInterface *callback)
{
int ret = 0;
const char *argv[MAXARGS];
int argc = 0;
char *foo = line;
while ( !EOS(*foo) && argc < MAXARGS )
{
foo = SkipSpaces(foo); // skip any leading spaces
if ( EOS(*foo) ) break;
if ( *foo == mQuoteChar ) // if it is an open quote
{
foo++;
if ( argc < MAXARGS )
{
argv[argc++] = foo;
}
while ( !EOS(*foo) && *foo != mQuoteChar ) foo++;
if ( !EOS(*foo) )
{
*foo = 0; // replace close quote with zero byte EOS
foo++;
}
}
else
{
foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces
if ( IsNonSeparator(*foo) ) // add non-hard argument.
{
bool quote = false;
if ( *foo == mQuoteChar )
{
foo++;
quote = true;
}
if ( argc < MAXARGS )
{
argv[argc++] = foo;
}
if ( quote )
{
while (*foo && *foo != mQuoteChar ) foo++;
if ( *foo ) *foo = 32;
}
// continue..until we hit an eos ..
while ( !EOS(*foo) ) // until we hit EOS
{
if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit
{
*foo = 0;
foo++;
break;
}
else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument
{
const char *hard = &mHardString[*foo*2];
*foo = 0;
if ( argc < MAXARGS )
{
argv[argc++] = hard;
}
foo++;
break;
}
foo++;
} // end of while loop...
}
}
}
if ( argc )
{
ret = callback->ParseLine(lineno, argc, argv );
}
return ret;
}
int InPlaceParser::Parse(InPlaceParserInterface *callback) // returns true if entire file was parsed, false if it aborted for some reason
{
assert( callback );
if ( !mData ) return 0;
int ret = 0;
int lineno = 0;
char *foo = mData;
char *begin = foo;
while ( *foo )
{
if ( *foo == 10 || *foo == 13 )
{
lineno++;
*foo = 0;
if ( *begin ) // if there is any data to parse at all...
{
int v = ProcessLine(lineno,begin,callback);
if ( v ) ret = v;
}
foo++;
if ( *foo == 10 ) foo++; // skip line feed, if it is in the carraige-return line-feed format...
begin = foo;
}
else
{
foo++;
}
}
lineno++; // last line.
int v = ProcessLine(lineno,begin,callback);
if ( v ) ret = v;
return ret;
}
void InPlaceParser::DefaultSymbols(void)
{
SetHardSeparator(',');
SetHardSeparator('(');
SetHardSeparator(')');
SetHardSeparator('=');
SetHardSeparator('[');
SetHardSeparator(']');
SetHardSeparator('{');
SetHardSeparator('}');
SetCommentSymbol('#');
}
const char ** InPlaceParser::GetArglist(char *line,int &count) // convert source string into an arg list, this is a destructive parse.
{
const char **ret = 0;
static const char *argv[MAXARGS];
int argc = 0;
char *foo = line;
while ( !EOS(*foo) && argc < MAXARGS )
{
foo = SkipSpaces(foo); // skip any leading spaces
if ( EOS(*foo) ) break;
if ( *foo == mQuoteChar ) // if it is an open quote
{
foo++;
if ( argc < MAXARGS )
{
argv[argc++] = foo;
}
while ( !EOS(*foo) && *foo != mQuoteChar ) foo++;
if ( !EOS(*foo) )
{
*foo = 0; // replace close quote with zero byte EOS
foo++;
}
}
else
{
foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces
if ( IsNonSeparator(*foo) ) // add non-hard argument.
{
bool quote = false;
if ( *foo == mQuoteChar )
{
foo++;
quote = true;
}
if ( argc < MAXARGS )
{
argv[argc++] = foo;
}
if ( quote )
{
while (*foo && *foo != mQuoteChar ) foo++;
if ( *foo ) *foo = 32;
}
// continue..until we hit an eos ..
while ( !EOS(*foo) ) // until we hit EOS
{
if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit
{
*foo = 0;
foo++;
break;
}
else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument
{
const char *hard = &mHardString[*foo*2];
*foo = 0;
if ( argc < MAXARGS )
{
argv[argc++] = hard;
}
foo++;
break;
}
foo++;
} // end of while loop...
}
}
}
count = argc;
if ( argc )
{
ret = argv;
}
return ret;
}
/*******************************************************************/
/******************** Geometry.h ********************************/
/*******************************************************************/
class GeometryVertex
{
public:
float mPos[3];
float mNormal[3];
float mTexel[2];
};
class GeometryInterface
{
public:
virtual void NodeTriangle(const GeometryVertex *v1,const GeometryVertex *v2,const GeometryVertex *v3, bool textured)
{
}
virtual ~GeometryInterface() {}
};
/*******************************************************************/
/******************** Obj.h ********************************/
/*******************************************************************/
class OBJ : public InPlaceParserInterface
{
public:
int LoadMesh(const char *fname,GeometryInterface *callback, bool textured);
int ParseLine(int lineno,int argc,const char **argv); // return TRUE to continue parsing, return FALSE to abort parsing process
OBJ() : mVerts(NULL), mTexels(NULL), mNormals(NULL), mTextured(false), mCallback(NULL) { Clear(); }
~OBJ() { Clear(); }
private:
void Clear();
void GetVertex(GeometryVertex &v,const char *face) const;
float* mVerts;
unsigned mNumVerts; // this is the tripled number of verts
unsigned mMaxVerts;
float* mTexels; // doubled number of texcoords
unsigned mNumTexels;
unsigned mMaxTexels;
float* mNormals; // tripled number of normals
unsigned mNumNormals;
unsigned mMaxNormals;
bool mTextured;
GeometryInterface* mCallback;
};
/*******************************************************************/
/******************** Obj.cpp ********************************/
/*******************************************************************/
int OBJ::LoadMesh(const char *fname, GeometryInterface *iface, bool textured)
{
Clear();
mTextured = textured;
int ret = 0;
mCallback = iface;
InPlaceParser ipp(fname);
ipp.Parse(this);
return ret;
}
void OBJ::Clear()
{
if (mVerts)
delete[] mVerts;
mMaxVerts = 0;
mNumVerts = 0;
if (mTexels)
delete[] mTexels;
mMaxTexels = 0;
mNumTexels = 0;
if (mNormals)
delete[] mNormals;
mMaxNormals = 0;
mNumNormals = 0;
}
void OBJ::GetVertex(GeometryVertex &v,const char *face) const
{
v.mPos[0] = 0;
v.mPos[1] = 0;
v.mPos[2] = 0;
v.mTexel[0] = 0;
v.mTexel[1] = 0;
v.mNormal[0] = 0;
v.mNormal[1] = 1;
v.mNormal[2] = 0;
int index = atoi( face )-1;
const char *texel = strstr(face,"/");
if ( texel )
{
int tindex = atoi( texel+1) - 1;
if ( tindex >=0 && tindex < (int)(mNumTexels/2) )
{
const float *t = &mTexels[tindex*2];
v.mTexel[0] = t[0];
v.mTexel[1] = t[1];
}
const char *normal = strstr(texel+1,"/");
if ( normal )
{
int nindex = atoi( normal+1 ) - 1;
if (nindex >= 0 && nindex < (int)(mNumNormals/3) )
{
const float *n = &mNormals[nindex*3];
v.mNormal[0] = n[0];
v.mNormal[1] = n[1];
v.mNormal[2] = n[2];
}
}
}
if ( index >= 0 && index < (int)(mNumVerts/3) )
{
const float *p = &mVerts[index*3];
v.mPos[0] = p[0];
v.mPos[1] = p[1];
v.mPos[2] = p[2];
} else
assert(0); // "Negative face vertex indices are not supported in wavefront loader.");
}
template<typename T>
void Resize(T*& data, unsigned& capacity, unsigned count, unsigned new_count)
{
if (new_count >= capacity)
{
capacity = new_count*2;
T* tmp = new T[capacity];
memcpy(tmp, data, count*sizeof(T));
delete[] data;
data = tmp;
}
}
int OBJ::ParseLine(int lineno,int argc,const char **argv) // return TRUE to continue parsing, return FALSE to abort parsing process
{
int ret = 0;
if ( argc >= 1 )
{
const char *foo = argv[0];
if ( *foo != '#' )
{
if (strcmp(argv[0], "v") == 0 && argc == 4 )
{
float vx = (float) atof( argv[1] );
float vy = (float) atof( argv[2] );
float vz = (float) atof( argv[3] );
Resize(mVerts, mMaxVerts, mNumVerts, mNumVerts + 3);
mVerts[mNumVerts++] = vx;
mVerts[mNumVerts++] = vy;
mVerts[mNumVerts++] = vz;
}
else if (strcmp(argv[0],"vt") == 0 && (argc == 3 || argc == 4))
{
// ignore 4rd component if present
float tx = (float) atof( argv[1] );
float ty = (float) atof( argv[2] );
Resize(mTexels, mMaxTexels, mNumTexels, mNumTexels + 2);
mTexels[mNumTexels++] = tx;
mTexels[mNumTexels++] = ty;
}
else if (strcmp(argv[0],"vn") == 0 && argc == 4 )
{
float normalx = (float) atof(argv[1]);
float normaly = (float) atof(argv[2]);
float normalz = (float) atof(argv[3]);
Resize(mNormals, mMaxNormals, mNumNormals, mNumNormals + 3);
mNormals[mNumNormals++] = normalx;
mNormals[mNumNormals++] = normaly;
mNormals[mNumNormals++] = normalz;
}
else if (strcmp(argv[0],"f") == 0 && argc >= 4 )
{
GeometryVertex v[32];
int vcount = argc-1;
for (int i=1; i<argc; i++)
{
GetVertex(v[i-1],argv[i] );
}
// need to generate a normal!
#if 0 // not currently implemented
if ( mNormals.empty() )
{
Vector3d<float> p1( v[0].mPos );
Vector3d<float> p2( v[1].mPos );
Vector3d<float> p3( v[2].mPos );
Vector3d<float> n;
n.ComputeNormal(p3,p2,p1);
for (int i=0; i<vcount; i++)
{
v[i].mNormal[0] = n.x;
v[i].mNormal[1] = n.y;
v[i].mNormal[2] = n.z;
}
}
#endif
mCallback->NodeTriangle(&v[0],&v[1],&v[2], mTextured);
if ( vcount >=3 ) // do the fan
{
for (int i=2; i<(vcount-1); i++)
{
mCallback->NodeTriangle(&v[0],&v[i],&v[i+1], mTextured);
}
}
}
}
}
return ret;
}
class BuildMesh : public GeometryInterface
{
public:
BuildMesh() : mVertices(NULL), mTexCoords(NULL), mIndices(NULL) { Clear(); }
~BuildMesh() { Clear(); }
void Clear()
{
if (mVertices)
delete[] mVertices;
mMaxVertices = 0;
mNumVertices = 0;
if (mTexCoords)
delete[] mTexCoords;
mMaxTexCoords = 0;
mNumTexCoords = 0;
if (mIndices)
delete[] mIndices;
mMaxIndices = 0;
mNumIndices = 0;
}
int GetIndex(const float *p, const float *texCoord)
{
int vcount = mNumVertices/3;
if(vcount>0)
{
//New MS STL library checks indices in debug build, so zero causes an assert if it is empty.
const float *v = &mVertices[0];
const float *t = texCoord != NULL ? &mTexCoords[0] : NULL;
for (int i=0; i<vcount; i++)
{
if ( v[0] == p[0] && v[1] == p[1] && v[2] == p[2] )
{
if (texCoord == NULL || (t[0] == texCoord[0] && t[1] == texCoord[1]))
{
return i;
}
}
v+=3;
if (t != NULL)
t += 2;
}
}
Resize(mVertices, mMaxVertices, mNumVertices, mNumVertices + 3);
mVertices[mNumVertices++] = p[0];
mVertices[mNumVertices++] = p[1];
mVertices[mNumVertices++] = p[2];
if (texCoord != NULL)
{
Resize(mTexCoords, mMaxTexCoords, mNumTexCoords, mNumTexCoords + 2);
mTexCoords[mNumTexCoords++] = texCoord[0];
mTexCoords[mNumTexCoords++] = texCoord[1];
}
return vcount;
}
virtual void NodeTriangle(const GeometryVertex *v1,const GeometryVertex *v2,const GeometryVertex *v3, bool textured)
{
Resize(mIndices, mMaxIndices, mNumIndices, mNumIndices + 3);
mIndices[mNumIndices++] = GetIndex(v1->mPos, textured ? v1->mTexel : NULL);
mIndices[mNumIndices++] = GetIndex(v2->mPos, textured ? v2->mTexel : NULL);
mIndices[mNumIndices++] = GetIndex(v3->mPos, textured ? v3->mTexel : NULL);
}
const float* GetVertices() const { return mVertices; }
unsigned GetNumVertices() const { return mNumVertices; }
const float* GetTexCoords(void) const { return mTexCoords; }
unsigned GetNumTexCoords(void) const { return mNumTexCoords; }
const int* GetIndices() const { return mIndices; }
unsigned GetNumIndices() const {return mNumIndices; }
private:
float* mVertices;
unsigned mMaxVertices;
unsigned mNumVertices;
float* mTexCoords;
unsigned mMaxTexCoords;
unsigned mNumTexCoords;
int* mIndices;
unsigned mMaxIndices;
unsigned mNumIndices;
};
};
using namespace WAVEFRONT;
WavefrontObj::WavefrontObj(void)
{
mVertexCount = 0;
mTriCount = 0;
mIndices = 0;
mVertices = NULL;
mTexCoords = NULL;
}
WavefrontObj::~WavefrontObj(void)
{
delete []mIndices;
delete []mVertices;
if (mTexCoords)
delete[] mTexCoords;
}
unsigned int WavefrontObj::loadObj(const char *fname, bool textured) // load a wavefront obj returns number of triangles that were loaded. Data is persists until the class is destructed.
{
unsigned int ret = 0;
delete []mVertices;
mVertices = 0;
delete []mIndices;
mIndices = 0;
mVertexCount = 0;
mTriCount = 0;
BuildMesh bm;
OBJ obj;
obj.LoadMesh(fname, &bm, textured);
if (bm.GetNumVertices())
{
mVertexCount = bm.GetNumVertices()/3;
mVertices = new float[mVertexCount*3];
memcpy(mVertices, bm.GetVertices(), sizeof(float)*mVertexCount*3);
if (textured)
{
mTexCoords = new float[mVertexCount * 2];
memcpy(mTexCoords, bm.GetTexCoords(), sizeof(float) * mVertexCount * 2);
}
mTriCount = bm.GetNumIndices()/3;
mIndices = new int[mTriCount*3];
memcpy(mIndices, bm.GetIndices(), sizeof(int)*mTriCount*3);
ret = mTriCount;
}
return ret;
}
bool LoadWavefrontBinary(const char* filename, WavefrontObj& wfo)
{
SampleFramework::File* fp = NULL;
PxToolkit::fopen_s(&fp, filename, "rb");
if(!fp) return false;
size_t numRead = fread(&wfo.mVertexCount, 1, sizeof(int), fp);
if(numRead != sizeof(int)) { fclose(fp); return false; }
wfo.mVertices = new float[wfo.mVertexCount*3];
numRead = fread(wfo.mVertices, 1, sizeof(float)*wfo.mVertexCount*3, fp);
if(numRead != sizeof(float)*wfo.mVertexCount*3) { fclose(fp); return false; }
numRead = fread(&wfo.mTriCount, 1, sizeof(int), fp);
if(numRead != sizeof(int)) { fclose(fp); return false; }
wfo.mIndices = new int[wfo.mTriCount*3];
numRead = fread(wfo.mIndices, 1, sizeof(int)*wfo.mTriCount*3, fp);
if(numRead != sizeof(int)*wfo.mTriCount*3) { fclose(fp); return false; }
// NB: mTexCoords not supported
fclose(fp);
return true;
}
bool SaveWavefrontBinary(const char* filename, const WavefrontObj& wfo)
{
SampleFramework::File* fp = NULL;
PxToolkit::fopen_s(&fp, filename, "wb");
if(!fp) return false;
fwrite(&wfo.mVertexCount, 1, sizeof(int), fp);
fwrite(wfo.mVertices, 1, wfo.mVertexCount*3*sizeof(float), fp);
fwrite(&wfo.mTriCount, 1, sizeof(int), fp);
fwrite(wfo.mIndices, 1, wfo.mTriCount*3*sizeof(int), fp);
// NB: mTexCoords not supported
fclose(fp);
return true;
}

View File

@ -0,0 +1,52 @@
//
// 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 WAVEFRONT_OBJ_H
#define WAVEFRONT_OBJ_H
class WavefrontObj
{
public:
WavefrontObj(void);
~WavefrontObj(void);
unsigned int loadObj(const char *fname, bool textured); // load a wavefront obj returns number of triangles that were loaded. Data is persists until the class is destructed.
int mVertexCount;
int mTriCount;
int* mIndices;
float* mVertices;
float* mTexCoords;
};
bool LoadWavefrontBinary(const char* filename, WavefrontObj& wfo);
bool SaveWavefrontBinary(const char* filename, const WavefrontObj& wfo);
#endif