Init
This commit is contained in:
683
physx/samples/samplebase/AcclaimLoader.cpp
Normal file
683
physx/samples/samplebase/AcclaimLoader.cpp
Normal 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;
|
||||
}
|
||||
|
||||
132
physx/samples/samplebase/AcclaimLoader.h
Normal file
132
physx/samples/samplebase/AcclaimLoader.h
Normal 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
|
||||
49
physx/samples/samplebase/Dummy.cpp
Normal file
49
physx/samples/samplebase/Dummy.cpp
Normal 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"
|
||||
162
physx/samples/samplebase/InputEventBuffer.cpp
Normal file
162
physx/samples/samplebase/InputEventBuffer.cpp
Normal 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);
|
||||
}
|
||||
228
physx/samples/samplebase/InputEventBuffer.h
Normal file
228
physx/samples/samplebase/InputEventBuffer.h
Normal 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
|
||||
2595
physx/samples/samplebase/PhysXSample.cpp
Normal file
2595
physx/samples/samplebase/PhysXSample.cpp
Normal file
File diff suppressed because it is too large
Load Diff
344
physx/samples/samplebase/PhysXSample.h
Normal file
344
physx/samples/samplebase/PhysXSample.h
Normal 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
|
||||
1481
physx/samples/samplebase/PhysXSampleApplication.cpp
Normal file
1481
physx/samples/samplebase/PhysXSampleApplication.cpp
Normal file
File diff suppressed because it is too large
Load Diff
362
physx/samples/samplebase/PhysXSampleApplication.h
Normal file
362
physx/samples/samplebase/PhysXSampleApplication.h
Normal 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
|
||||
289
physx/samples/samplebase/Picking.cpp
Normal file
289
physx/samples/samplebase/Picking.cpp
Normal 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);
|
||||
}
|
||||
121
physx/samples/samplebase/Picking.h
Normal file
121
physx/samples/samplebase/Picking.h
Normal 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
|
||||
415
physx/samples/samplebase/RawLoader.cpp
Normal file
415
physx/samples/samplebase/RawLoader.cpp
Normal 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;
|
||||
}
|
||||
120
physx/samples/samplebase/RawLoader.h
Normal file
120
physx/samples/samplebase/RawLoader.h
Normal 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
|
||||
252
physx/samples/samplebase/RaycastCCD.cpp
Normal file
252
physx/samples/samplebase/RaycastCCD.cpp
Normal 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;
|
||||
}
|
||||
46
physx/samples/samplebase/RaycastCCD.h
Normal file
46
physx/samples/samplebase/RaycastCCD.h
Normal 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
|
||||
279
physx/samples/samplebase/RenderBaseActor.cpp
Normal file
279
physx/samples/samplebase/RenderBaseActor.cpp
Normal 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);
|
||||
}*/
|
||||
}
|
||||
126
physx/samples/samplebase/RenderBaseActor.h
Normal file
126
physx/samples/samplebase/RenderBaseActor.h
Normal 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
|
||||
52
physx/samples/samplebase/RenderBaseObject.cpp
Normal file
52
physx/samples/samplebase/RenderBaseObject.cpp
Normal 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;
|
||||
}
|
||||
49
physx/samples/samplebase/RenderBaseObject.h
Normal file
49
physx/samples/samplebase/RenderBaseObject.h
Normal 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
|
||||
48
physx/samples/samplebase/RenderBoxActor.cpp
Normal file
48
physx/samples/samplebase/RenderBoxActor.cpp
Normal 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()
|
||||
{
|
||||
}
|
||||
49
physx/samples/samplebase/RenderBoxActor.h
Normal file
49
physx/samples/samplebase/RenderBoxActor.h
Normal 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
|
||||
58
physx/samples/samplebase/RenderCapsuleActor.cpp
Normal file
58
physx/samples/samplebase/RenderCapsuleActor.cpp
Normal 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()
|
||||
{
|
||||
}
|
||||
53
physx/samples/samplebase/RenderCapsuleActor.h
Normal file
53
physx/samples/samplebase/RenderCapsuleActor.h
Normal 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
|
||||
50
physx/samples/samplebase/RenderGridActor.cpp
Normal file
50
physx/samples/samplebase/RenderGridActor.cpp
Normal 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)
|
||||
{
|
||||
}
|
||||
49
physx/samples/samplebase/RenderGridActor.h
Normal file
49
physx/samples/samplebase/RenderGridActor.h
Normal 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
|
||||
184
physx/samples/samplebase/RenderMaterial.cpp
Normal file
184
physx/samples/samplebase/RenderMaterial.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
78
physx/samples/samplebase/RenderMaterial.h
Normal file
78
physx/samples/samplebase/RenderMaterial.h
Normal 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
|
||||
68
physx/samples/samplebase/RenderMeshActor.cpp
Normal file
68
physx/samples/samplebase/RenderMeshActor.cpp
Normal 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()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
54
physx/samples/samplebase/RenderMeshActor.h
Normal file
54
physx/samples/samplebase/RenderMeshActor.h
Normal 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
|
||||
923
physx/samples/samplebase/RenderPhysX3Debug.cpp
Normal file
923
physx/samples/samplebase/RenderPhysX3Debug.cpp
Normal 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);
|
||||
}
|
||||
100
physx/samples/samplebase/RenderPhysX3Debug.h
Normal file
100
physx/samples/samplebase/RenderPhysX3Debug.h
Normal 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
|
||||
48
physx/samples/samplebase/RenderSphereActor.cpp
Normal file
48
physx/samples/samplebase/RenderSphereActor.cpp
Normal 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()
|
||||
{
|
||||
}
|
||||
44
physx/samples/samplebase/RenderSphereActor.h
Normal file
44
physx/samples/samplebase/RenderSphereActor.h
Normal 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
|
||||
103
physx/samples/samplebase/RenderTexture.cpp
Normal file
103
physx/samples/samplebase/RenderTexture.cpp
Normal 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);
|
||||
}
|
||||
55
physx/samples/samplebase/RenderTexture.h
Normal file
55
physx/samples/samplebase/RenderTexture.h
Normal 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
|
||||
332
physx/samples/samplebase/SampleAllocator.cpp
Normal file
332
physx/samples/samplebase/SampleAllocator.cpp
Normal 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;
|
||||
}
|
||||
87
physx/samples/samplebase/SampleAllocator.h
Normal file
87
physx/samples/samplebase/SampleAllocator.h
Normal 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
|
||||
47
physx/samples/samplebase/SampleAllocatorSDKClasses.h
Normal file
47
physx/samples/samplebase/SampleAllocatorSDKClasses.h
Normal 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
|
||||
51
physx/samples/samplebase/SampleArray.h
Normal file
51
physx/samples/samplebase/SampleArray.h
Normal 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
|
||||
93
physx/samples/samplebase/SampleBaseInputEventIds.h
Normal file
93
physx/samples/samplebase/SampleBaseInputEventIds.h
Normal 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
|
||||
481
physx/samples/samplebase/SampleCamera.cpp
Normal file
481
physx/samples/samplebase/SampleCamera.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
157
physx/samples/samplebase/SampleCamera.h
Normal file
157
physx/samples/samplebase/SampleCamera.h
Normal 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
|
||||
274
physx/samples/samplebase/SampleCameraController.cpp
Normal file
274
physx/samples/samplebase/SampleCameraController.cpp
Normal 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);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
103
physx/samples/samplebase/SampleCameraController.h
Normal file
103
physx/samples/samplebase/SampleCameraController.h
Normal 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
|
||||
578
physx/samples/samplebase/SampleCharacterHelpers.cpp
Normal file
578
physx/samples/samplebase/SampleCharacterHelpers.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
152
physx/samples/samplebase/SampleCharacterHelpers.h
Normal file
152
physx/samples/samplebase/SampleCharacterHelpers.h
Normal 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
|
||||
609
physx/samples/samplebase/SampleConsole.cpp
Normal file
609
physx/samples/samplebase/SampleConsole.cpp
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
134
physx/samples/samplebase/SampleConsole.h
Normal file
134
physx/samples/samplebase/SampleConsole.h
Normal 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
|
||||
264
physx/samples/samplebase/SampleInputMappingAsset.cpp
Normal file
264
physx/samples/samplebase/SampleInputMappingAsset.cpp
Normal 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;
|
||||
}
|
||||
66
physx/samples/samplebase/SampleInputMappingAsset.h
Normal file
66
physx/samples/samplebase/SampleInputMappingAsset.h
Normal 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
|
||||
187
physx/samples/samplebase/SampleMain.cpp
Normal file
187
physx/samples/samplebase/SampleMain.cpp
Normal 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
|
||||
107
physx/samples/samplebase/SampleMouseFilter.cpp
Normal file
107
physx/samples/samplebase/SampleMouseFilter.cpp
Normal 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;
|
||||
}
|
||||
56
physx/samples/samplebase/SampleMouseFilter.h
Normal file
56
physx/samples/samplebase/SampleMouseFilter.h
Normal 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
|
||||
34
physx/samples/samplebase/SamplePreprocessor.h
Normal file
34
physx/samples/samplebase/SamplePreprocessor.h
Normal 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
|
||||
92
physx/samples/samplebase/SampleRandomPrecomputed.cpp
Normal file
92
physx/samples/samplebase/SampleRandomPrecomputed.cpp
Normal 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;
|
||||
}
|
||||
64
physx/samples/samplebase/SampleRandomPrecomputed.h
Normal file
64
physx/samples/samplebase/SampleRandomPrecomputed.h
Normal 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
|
||||
206
physx/samples/samplebase/SampleStepper.cpp
Normal file
206
physx/samples/samplebase/SampleStepper.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
229
physx/samples/samplebase/SampleStepper.h
Normal file
229
physx/samples/samplebase/SampleStepper.h
Normal 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
|
||||
61
physx/samples/samplebase/SampleUserInputDefines.h
Normal file
61
physx/samples/samplebase/SampleUserInputDefines.h
Normal 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
|
||||
47
physx/samples/samplebase/SampleUtils.h
Normal file
47
physx/samples/samplebase/SampleUtils.h
Normal 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
|
||||
39
physx/samples/samplebase/Test.h
Normal file
39
physx/samples/samplebase/Test.h
Normal 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;
|
||||
43
physx/samples/samplebase/TestGeometryHelpers.cpp
Normal file
43
physx/samples/samplebase/TestGeometryHelpers.cpp
Normal 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()));
|
||||
}
|
||||
49
physx/samples/samplebase/TestGeometryHelpers.h
Normal file
49
physx/samples/samplebase/TestGeometryHelpers.h
Normal 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
|
||||
315
physx/samples/samplebase/TestGroup.cpp
Normal file
315
physx/samples/samplebase/TestGroup.cpp
Normal 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);
|
||||
}
|
||||
|
||||
201
physx/samples/samplebase/TestGroup.h
Normal file
201
physx/samples/samplebase/TestGroup.h
Normal 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
|
||||
108
physx/samples/samplebase/TestMotionGenerator.cpp
Normal file
108
physx/samples/samplebase/TestMotionGenerator.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
53
physx/samples/samplebase/TestMotionGenerator.h
Normal file
53
physx/samples/samplebase/TestMotionGenerator.h
Normal 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
|
||||
946
physx/samples/samplebase/wavefront.cpp
Normal file
946
physx/samples/samplebase/wavefront.cpp
Normal 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;
|
||||
}
|
||||
52
physx/samples/samplebase/wavefront.h
Normal file
52
physx/samples/samplebase/wavefront.h
Normal 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
|
||||
Reference in New Issue
Block a user