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

View File

@ -0,0 +1,491 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
//
// Implementation of different antialiasing methods.
// - typical MSAA
// - CSAA
// - Hardware AA mixed with FBO for supersampling pass
// - simple downsampling
// - downsampling with 1 or 2 kernel filters
//
// AABox is the class that will handle everything related to supersampling through
// an offscreen surface defined thanks to FBO
//
//--------------------------------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <map>
#include <GL/glew.h>
#include <windows.h>
#include "GL/glut.h"
#include <Cg/CgGL.h>
#include "AABox.h"
AABox::AABox(std::string path) :
bValid(false),
vpx(0), vpy(0), vpw(0), vph(0),
posx(0), posy(0),
cgContext(NULL),
cgEffect(NULL),
cgPassDownSample(NULL), path(path), oldFbo(0)
{
for(int i=0; i<4; i++) cgTechnique[i] = NULL;
}
AABox::~AABox()
{
}
void AABox::Destroy()
{
if(depth_rb)
glDeleteRenderbuffersEXT(1, &depth_rb);
if(color_rb)
glDeleteRenderbuffersEXT(1, &color_rb);
if(textureID)
glDeleteTextures(1, &textureID);
if(textureDepthID)
glDeleteTextures(1, &textureDepthID);
if(fb)
glDeleteFramebuffersEXT(1, &fb);
if(fbms)
glDeleteFramebuffersEXT(1, &fbms);
if(cgEffect)
cgDestroyEffect(cgEffect);
if(cgContext)
cgDestroyContext(cgContext);
depth_rb=0;
color_rb=0;
textureID=0;
textureDepthID=0;
fb=0;
fbms=0;
cgEffect=0;
cgContext=0;
}
/*-------------------------------------------------------------------------
-------------------------------------------------------------------------*/
void CheckFramebufferStatus()
{
GLenum status;
status = (GLenum) glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
printf("Unsupported framebuffer format\n");
fprintf(stderr, "Unsupported framebuffer format");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
printf("Framebuffer incomplete, missing attachment\n");
fprintf(stderr, "Framebuffer incomplete, missing attachment");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
printf("Framebuffer incomplete, attached images must have same dimensions\n");
fprintf(stderr, "Framebuffer incomplete, attached images must have same dimensions");
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
printf("Framebuffer incomplete, attached images must have same format\n");
fprintf(stderr, "Framebuffer incomplete, attached images must have same format");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
printf("Framebuffer incomplete, missing draw buffer\n");
fprintf(stderr, "Framebuffer incomplete, missing draw buffer");
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
printf("Framebuffer incomplete, missing read buffer\n");
fprintf(stderr, "Framebuffer incomplete, missing read buffer");
break;
default:
printf("Error %x\n", status);
break;
}
}
bool AABox::initRT(int depthSamples, int coverageSamples)
{
bool multisample = depthSamples > 0;
bool csaa = coverageSamples > depthSamples;
bool ret = true;
int query;
//
// init the texture that will also be the buffer to render to
//
glGenTextures(1, &textureID);
glBindTexture( GL_TEXTURE_2D, textureID);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA16F, bufw, bufh, 0,
GL_RGBA, GL_FLOAT, NULL);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glGenFramebuffersEXT(1, &fb);
//
// Handle multisample FBO's first
//
if (multisample)
{
//multisample : so we need to resolve from the MS FBO down to a FBO at non MS resolution
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureID, 0);
glGenTextures(1, &textureDepthID);
glBindTexture(GL_TEXTURE_2D, textureDepthID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, bufw, bufh, 0,
GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, textureDepthID, 0);
CheckFramebufferStatus();
//now handle the FBO in MS resolution
glGenFramebuffersEXT(1, &fbms);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbms);
// initialize color renderbuffer
glGenRenderbuffersEXT(1, &color_rb);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, color_rb);
if (csaa & bCSAA)
{
glRenderbufferStorageMultisampleCoverageNV( GL_RENDERBUFFER_EXT, coverageSamples, depthSamples, GL_RGBA16F,
bufw, bufh);
glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_COVERAGE_SAMPLES_NV, &query);
if ( query < coverageSamples)
ret = false;
else if ( query > coverageSamples)
{
// report back the actual number
coverageSamples = query;
}
glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_COLOR_SAMPLES_NV, &query);
if ( query < depthSamples)
ret = false;
else if ( query > depthSamples)
{
// report back the actual number
depthSamples = query;
}
}
else
{
// create a regular MSAA color buffer
glRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, depthSamples, GL_RGBA16F, bufw, bufh);
// check the number of samples
glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &query);
if ( query < depthSamples)
ret = false;
else if ( query > depthSamples)
{
depthSamples = query;
}
}
// attach the multisampled color buffer
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, color_rb);
CheckFramebufferStatus();
// bind the multisampled depth buffer
glGenRenderbuffersEXT(1, &depth_rb);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
// create the multisampled depth buffer (with or without coverage sampling)
if (csaa & bCSAA)
{
// create a coverage sampled MSAA depth buffer
glRenderbufferStorageMultisampleCoverageNV( GL_RENDERBUFFER_EXT, coverageSamples, depthSamples, GL_DEPTH_COMPONENT24,
bufw, bufh);
// check the number of coverage samples
glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_COVERAGE_SAMPLES_NV, &query);
if ( query < coverageSamples)
ret = false;
else if ( query > coverageSamples)
// set the coverage samples value to return the actual value
coverageSamples = query;
// cehck the number of stored color samples (same as depth samples)
glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_COLOR_SAMPLES_NV, &query);
if ( query < depthSamples)
ret = false;
else if ( query > depthSamples)
// set the depth samples value to return the actual value
depthSamples = query;
}
else {
// create a regular (not coverage sampled) MSAA depth buffer
glRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, depthSamples, GL_DEPTH_COMPONENT24, bufw, bufh);
// check the number of depth samples
glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &query);
if ( query < depthSamples)
ret = false;
else if ( query < depthSamples)
depthSamples = query;
}
// attach the depth buffer
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
CheckFramebufferStatus();
} // if (multisample)
else // Depth buffer created as a texture...
{
//non-multisample, so bind things directly to the FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureID, 0);
glGenTextures(1, &textureDepthID);
glBindTexture( GL_TEXTURE_2D, textureDepthID);
glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, bufw, bufh, 0,
GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, textureDepthID, 0);
CheckFramebufferStatus();
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, multisample ? fbms : fb);
glGetIntegerv( GL_RED_BITS, &query);
if ( query != 16)
{
printf( "Got %d red bits expected %d\n", query, 16);
ret = false;
}
glGetIntegerv( GL_DEPTH_BITS, &query);
if ( query != 24)
{
printf( "Got %d depth bits expected %d\n", query, 24);;
ret = false;
}
if (multisample)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
glGetIntegerv( GL_RED_BITS, &query);
if ( query != 16)
{
printf( "Got %d red bits expected %d\n", query, 16);
ret = false;
}
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldFbo);
return ret;
}
/*-------------------------------------------------------------------------
-------------------------------------------------------------------------*/
bool AABox::Initialize(int w, int h, float ssfact, int depthSamples, int coverageSamples)
{
if (!glewIsSupported(
"GL_VERSION_2_0 "
"GL_EXT_framebuffer_object "
))
{
printf("Unable to load extensions\n");
return false;
}
bCSAA = glewIsExtensionSupported("GL_NV_framebuffer_multisample_coverage") ? true : false;
if((!bCSAA) && coverageSamples)
{
printf("Note: GL_NV_framebuffer_multisample_coverage unavailable, using regular MSAA only\n");
}
Destroy();
bufw = (int)(ssfact*(float)w+0.99f);
bufh = (int)(ssfact*(float)h+0.99f);
//
// FBO
//
initRT(depthSamples, coverageSamples);
CheckFramebufferStatus();
//
// CGFX things
//
cgContext = cgCreateContext();
cgGLRegisterStates(cgContext);
char fileName[200];
sprintf(fileName, "%s/AABox.cgfx", path.c_str());
cgEffect = cgCreateEffectFromFile(cgContext, fileName, NULL);
if(!cgEffect)
{
const char *listing = cgGetLastListing(cgContext);
//fprintf(stderr, "CgFx Parse error : \n %s\n", listing);
bValid = false;
//printf("Trying other path...\n");
cgEffect = cgCreateEffectFromFile(cgContext, fileName, NULL);
if(!cgEffect)
{
fprintf(stderr, "CgFx Parse error : \n %s\n", listing);
bValid = false;
return false;
}
}
cgTechnique[0] = cgGetFirstTechnique(cgEffect);
cgTechnique[1] = cgGetNextTechnique(cgTechnique[0]);
cgTechnique[2] = cgGetNextTechnique(cgTechnique[1]);
cgTechnique[3] = cgGetNextTechnique(cgTechnique[2]);
cgBlendFactor = cgGetNamedEffectParameter(cgEffect, "blendFactor");
cgSSsampler = cgGetNamedEffectParameter(cgEffect, "SSsampler");
cgDepthSSsampler = cgGetNamedEffectParameter(cgEffect, "DepthSSsampler");
cgTexelSize = cgGetNamedEffectParameter(cgEffect, "SSTexelSize");
cgBlendFactor = cgGetNamedEffectParameter(cgEffect, "blendFactor");
cgGLSetParameter2f(cgTexelSize, 1.0f/(float)bufw, 1.0f/(float)bufh);
bValid = true;
return true;
}
#define FULLSCRQUAD()\
glBegin(GL_QUADS);\
glTexCoord2f(0,0);\
glVertex4f(-1, -1, 0.0,1);\
glTexCoord2f(1,0);\
glVertex4f(1, -1,0.0,1);\
glTexCoord2f(1,1);\
glVertex4f(1, 1,0.0,1);\
glTexCoord2f(0,1);\
glVertex4f(-1, 1,0.0,1);\
glEnd();
/*-------------------------------------------------------------------------
-------------------------------------------------------------------------*/
void AABox::Draw(int technique)
{
CGbool bRes;
if(technique > 4)
return;
bRes = cgValidateTechnique(cgTechnique[technique]);
if(!bRes)
{
if(bValid)
{
fprintf(stderr, "Validation of FilterRect failed\n");
bValid = false;
}
return;
}
else bValid = true;
if(!bValid)
return;
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);
//
// if this FBO is multisampled, resolve it, so it can be displayed
// the blit will allow the multisampled buffer to be stretched to a normal buffer at res bufw/bufh
//
if( fbms )
{
glBindFramebufferEXT( GL_READ_FRAMEBUFFER_EXT, fbms);
glBindFramebufferEXT( GL_DRAW_FRAMEBUFFER_EXT, fb);
glBlitFramebufferEXT(0, 0, bufw, bufh, 0, 0, bufw, bufh, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldFbo);
cgGLSetupSampler(cgSSsampler, textureID);
cgGLSetupSampler(cgDepthSSsampler, textureDepthID);
CGpass cgPass = cgGetFirstPass(cgTechnique[technique]);
cgSetPassState(cgPass);
//
// During this full screen pass, we will down-sample the buffer and
// eventually filter it
//
FULLSCRQUAD();
cgResetPassState(cgPass);
}
/*-------------------------------------------------------------------------
-------------------------------------------------------------------------*/
void AABox::Activate(int x, int y)
{
if(!bValid)
return;
glBindTexture(GL_TEXTURE_2D, 0);
//
// Bind the framebuffer to render on : can be either Multisampled one or normal one
//
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbms ? fbms : fb);
glPushAttrib(GL_VIEWPORT_BIT);
posx = x;
posy = y;
glViewport(0, 0, bufw, bufh);
}
/*-------------------------------------------------------------------------
-------------------------------------------------------------------------*/
void AABox::Deactivate()
{
if(!bValid)
return;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldFbo);
glPopAttrib();
}
void AABox::Rebind() {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbms ? fbms : fb);
glViewport(0, 0, bufw, bufh);
}

View File

@ -0,0 +1,98 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
//
// Implementation of different antialiasing methods.
// - typical MSAA
// - CSAA
// - Hardware AA mixed with FBO for supersampling pass
// - simple downsampling
// - downsampling with 1 or 2 kernel filters
//
// AABox is the class that will handle everything related to supersampling through
// an offscreen surface defined thanks to FBO
// Basic use is :
//
// Initialize()
// ...
// Activate(int x=0, int y=0)
// Draw the scene (so, in the offscreen supersampled buffer)
// Deactivate()
// Draw() : downsample to backbuffer
// ...
// Destroy()
//
//--------------------------------------------------------------------------------------
#define FB_SS 0
#include <Cg/CgGL.h>
#include <string>
class AABox
{
public:
AABox(std::string path);
~AABox();
bool Initialize(int w, int h, float ssfact, int depthSamples, int coverageSamples);
void Destroy();
void Activate(int x=0, int y=0);
void Deactivate();
void Rebind();
void Draw(int technique);
int getBufW() const {return bufw;};
int getBufH() const {return bufh;};
GLuint getTextureID() {return textureID;};
CGparameter cgBlendFactor;
//protected:
bool bValid;
bool bCSAA;
int vpx, vpy, vpw, vph;
int posx, posy;
int bufw, bufh;
CGcontext cgContext;
CGeffect cgEffect;
CGtechnique cgTechnique[4];
CGpass cgPassDownSample;
CGpass cgPassDrawFinal;
GLuint textureID;
GLuint textureDepthID;
CGparameter cgSrcSampler;
CGparameter cgSSsampler;
CGparameter cgDepthSSsampler;
CGparameter cgTexelSize;
GLuint fb;
GLuint fbms;
GLuint depth_rb;
GLuint color_rb;
GLuint oldFbo;
std::string path;
bool initRT(int depthSamples, int coverageSamples);
};

View File

@ -0,0 +1,822 @@
//
// 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-2018 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxPhysicsAPI.h"
#include "extensions/PxExtensionsAPI.h"
#include "Crab.h"
#include "CrabManager.h"
#include "SceneCrab.h"
#include "SimScene.h"
#include "CompoundCreator.h"
#include <GL/glut.h>
#include "PxTkStream.h"
#include "PxTkFile.h"
using namespace PxToolkit;
// if enabled: runs the crab AI in sync, not as a parallel task to physx.
#define DEBUG_RENDERING 0
void setupFiltering(PxRigidActor* actor, PxU32 filterGroup, PxU32 filterMask);
// table with default times in seconds how the crab AI will try to stay in a state
static const PxReal gDefaultStateTime[CrabState::eNUM_STATES] = { 5.0f, 30.0f, 30.0f, 10.0f, 10.0f, 6.0f };
Crab::Crab(CrabManager* crabManager, PxU32 updateFrequency)
{
mUpdateFrequency = updateFrequency;
mManager = crabManager;
initMembers();
}
void Crab::initMembers()
{
mCrabBody = NULL;
//mSqRayBuffer = NULL;
mSqSweepBuffer = NULL;
mLegHeight = 0;
mMaterial = mManager->getPhysics().createMaterial(0.9f, 0.7f, 0.01f);
mCrabState = CrabState::eWAITING;
mStateTime = gDefaultStateTime[CrabState::eWAITING];
mAccumTime = 0;
mElapsedTime = 0;
mAcceleration[0] = 0;
mAcceleration[1] = 0;
mAccelerationBuffer[0] = 0;
mAccelerationBuffer[1] = 0;
for (PxU32 a = 0; a < 6; ++a)
mDistances[a] = 0;
// setup buffer for 10 batched rays and 10 hits
//mSqRayBuffer = PX_PLACEMENT_NEW(PX_ALLOC(sizeof(SqRayBuffer), PX_DEBUG_EXP("SqRayBuffer")), SqRayBuffer)(this, 10, 10);
mSqSweepBuffer = PX_PLACEMENT_NEW(PX_ALLOC(sizeof(SqSweepBuffer), PX_DEBUG_EXP("SqSweepBuffer")), SqSweepBuffer)(this, 6, 6);
}
Crab::~Crab()
{
//mSqRayBuffer->~SqRayBuffer();
//PX_FREE(mSqRayBuffer);
mSqSweepBuffer->~SqSweepBuffer();
PX_FREE(mSqSweepBuffer);
}
void Crab::setScene(PxScene* scene)
{
mSqSweepBuffer->setScene(scene);
}
static void setShapeFlag(PxRigidActor* actor, PxShapeFlag::Enum flag, bool flagValue)
{
const PxU32 numShapes = actor->getNbShapes();
PxShape** shapes = (PxShape**)PX_ALLOC(sizeof(PxShape*)*numShapes, PX_DEBUG_EXP("SceneCrab:setShapeFlag"));
actor->getShapes(shapes, numShapes);
for (PxU32 i = 0; i < numShapes; i++)
{
PxShape* shape = shapes[i];
shape->setFlag(flag, flagValue);
}
PX_FREE(shapes);
}
PxVec3 Crab::getPlaceOnFloor(PxVec3 start)
{
PxRaycastBuffer rayHit;
mManager->getScene().raycast(start, PxVec3(0, -1, 0), 1000.0f, rayHit);
return rayHit.block.position + PxVec3(0, mLegHeight, 0);
}
//static const PxSerialObjectId mMaterial_id = (PxSerialObjectId)0x01;
//static const PxSerialObjectId mCrabBody_id = (PxSerialObjectId)0x02;
//static const PxSerialObjectId mMotorJoint0_id = (PxSerialObjectId)0x03;
//static const PxSerialObjectId mMotorJoint1_id = (PxSerialObjectId)0x04;
//
//struct FilterGroup
//{
// enum Enum
// {
// eSUBMARINE = (1 << 0),
// eMINE_HEAD = (1 << 1),
// eMINE_LINK = (1 << 2),
// eCRAB = (1 << 3),
// eHEIGHTFIELD = (1 << 4),
// };
//};
//
//void setupFiltering(PxRigidActor* actor, PxU32 filterGroup, PxU32 filterMask)
//{
// PxFilterData filterData;
// filterData.word0 = filterGroup; // word0 = own ID
// filterData.word1 = filterMask; // word1 = ID mask to filter pairs that trigger a contact callback;
// const PxU32 numShapes = actor->getNbShapes();
// PxShape** shapes = (PxShape**)PX_ALLOC(sizeof(PxShape*)*numShapes, PX_DEBUG_EXP("setupFiltering"));
// actor->getShapes(shapes, numShapes);
// for (PxU32 i = 0; i < numShapes; i++)
// {
// PxShape* shape = shapes[i];
// shape->setSimulationFilterData(filterData);
// }
// PX_FREE(shapes);
//}
void setupSQFiltering(PxRigidActor* actor, PxU32 crabId)
{
PxFilterData filterData(0, 0, 0, crabId);
PxShape* shape;
PxU32 nbShapes = actor->getNbShapes();
for (PxU32 a = 0; a < nbShapes; ++a)
{
actor->getShapes(&shape, 1, a);
shape->setQueryFilterData(filterData);
}
}
Crab* Crab::create(const PxVec3& _crabPos, const PxReal crabDepth, const PxReal scale, const PxReal legMass, const PxU32 numLegs)
{
static PxU32 crabId = 0;
crabId++;
/*static const PxReal scale = 0.8f;
static const PxReal crabDepth = 2.0f;
static const PxVec3 crabBodyDim = PxVec3(0.8f, 0.8f, crabDepth*0.5f)*scale;
static const PxReal legMass = 0.03f;*/
const PxVec3 crabBodyDim = PxVec3(0.8f, 0.8f, crabDepth*0.5f)*scale;
const PxReal velocity = 0.0f;
//static const PxReal maxForce = 4000.0f;
const PxReal maxForce = 50000.0f;
LegParameters params; // check edge ascii art in Crab.h
params.a = 0.5f;
params.b = 0.6f;
params.c = 0.5f;
params.d = 0.5f;
params.e = 1.5f;
params.m = 0.3f;
params.n = 0.1f;
mLegHeight = scale*2.0f*(params.d + params.c);
mLegHeight += 0.5f;
PxVec3 crabPos = getPlaceOnFloor(_crabPos);
ShaderMaterial mat;
mat.init();
PxVec3 vel(0), omega(0);
PxTransform localPose = PxTransform(PxQuat(PxHalfPi*0.5f, PxVec3(0, 0, 1)));
SimScene* simScene = mManager->getSceneCrab()->getSimScene();
simScene->getCompoundCreator()->createBox(2.f*crabBodyDim, &localPose);
mCrabBodyDimensions = crabBodyDim;
//mCrabBody = PxCreateDynamic(getPhysics(), PxTransform(crabPos), PxBoxGeometry(crabBodyDim), *mMaterial, 10.f);
Compound* compound = mManager->createObject(PxTransform(crabPos), vel, omega, false, mat);
mCrabBody = compound->getPxActor();
/*PxShape* shape; mCrabBody->getShapes(&shape, 1);
shape->setLocalPose(PxTransform(PxQuat(PxHalfPi*0.5f, PxVec3(0, 0, 1))));*/
PxRigidBodyExt::setMassAndUpdateInertia(*mCrabBody, legMass*10.0f);
PxTransform cmPose = mCrabBody->getCMassLocalPose();
cmPose.p.y -= 1.8f;
mCrabBody->setCMassLocalPose(cmPose);
//mCrabBody->setAngularDamping(100.0f);
mCrabBody->setAngularDamping(0.5f);
mCrabBody->userData = this;
//mActors.push_back(mCrabBody);
PxQuat rotation(3.1415 / 2.f, PxVec3(0.f, 0.f, 1.f));
PxD6Joint* joint = PxD6JointCreate(mManager->getPhysics(), NULL, PxTransform(rotation), mCrabBody, PxTransform(mCrabBody->getGlobalPose().q.getConjugate() * rotation));
joint->setMotion(PxD6Axis::eX, PxD6Motion::eFREE);
joint->setMotion(PxD6Axis::eY, PxD6Motion::eFREE);
joint->setMotion(PxD6Axis::eZ, PxD6Motion::eFREE);
joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eLIMITED);
joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eLIMITED);
PxJointLimitCone limitCone(3.1415 / 6.f, 3.1415 / 6.f);
joint->setSwingLimit(limitCone);
// legs
PxReal recipNumLegs = 1.0f / PxReal(numLegs);
PxReal recipNumLegsMinus1 = 1.0f / PxReal(numLegs - 1);
//PX_COMPILE_TIME_ASSERT((numLegs & 1) == 0);
PxRigidDynamic* motor[2];
{
const PxReal density = 1.0f;
const PxReal m = params.m * scale;
const PxReal n = params.n * scale;
const PxBoxGeometry boxGeomM = PxBoxGeometry(m, m, crabBodyDim.z * 0.5f + 0.15f);
// create left and right motor
PxVec3 motorPos = crabPos + PxVec3(0, n, 0);
for (PxU32 i = 0; i < 2; i++)
{
PxVec3 motorOfs = i == 0 ? PxVec3(0, 0, boxGeomM.halfExtents.z) : -PxVec3(0, 0, boxGeomM.halfExtents.z);
simScene->getCompoundCreator()->createBox(2.f*boxGeomM.halfExtents);
Compound* motorCompound = mManager->createObject(PxTransform(motorPos + motorOfs), vel, omega, false, mat);
motor[i] = motorCompound->getPxActor();
PxRigidBodyExt::setMassAndUpdateInertia(*motor[i], legMass);
motor[i]->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
setShapeFlag(motor[i], PxShapeFlag::eSIMULATION_SHAPE, false);
setShapeFlag(motor[i], PxShapeFlag::eSCENE_QUERY_SHAPE, false);
/*mMotorJoint[i] = PxRevoluteJointCreate(mManager->getPhysics(),
mCrabBody, PxTransform(motorOfs, PxQuat(-PxHalfPi, PxVec3(0, 1, 0))),
motor[i], PxTransform(PxVec3(0, 0, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))));
mMotorJoint[i]->setDriveVelocity(velocity);
mMotorJoint[i]->setDriveForceLimit(maxForce);
mMotorJoint[i]->setRevoluteJointFlag(PxRevoluteJointFlag::eDRIVE_ENABLED, true);*/
mMotorJoint[i] = PxD6JointCreate(mManager->getPhysics(),
mCrabBody, PxTransform(motorOfs, PxQuat(-PxHalfPi, PxVec3(0, 1, 0))),
motor[i], PxTransform(PxVec3(0, 0, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))));
mMotorJoint[i]->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
mMotorJoint[i]->setDriveVelocity(PxVec3(0), PxVec3(velocity, 0.f, 0.f));
mMotorJoint[i]->setDrive(PxD6Drive::eTWIST, PxD6JointDrive(0.f, 30.f, maxForce));
//mActors.push_back(motor[i]);
//mJoints.push_back(mMotorJoint[i]);
}
// create legs and attach to left and right motor
PxReal legSpacing = crabDepth*recipNumLegsMinus1*scale;
PxVec3 bodyToLegPos0 = PxVec3(0, 0, crabBodyDim.z);
PxVec3 bodyToLegPos1 = PxVec3(0, 0, crabBodyDim.z - (numLegs / 2)*legSpacing);
PxVec3 motorToLegPos0 = PxVec3(0, 0, crabBodyDim.z*0.5f);
PxVec3 motorToLegPos1 = PxVec3(0, 0, (crabBodyDim.z - legSpacing)*0.5f);
for (PxU32 i = 0; i < numLegs / 2; i++)
{
PxReal angle0 = -PxHalfPi + PxTwoPi*recipNumLegs*i;
PxReal angle1 = angle0 + PxPi;
createLeg(mCrabBody, bodyToLegPos0, legMass, params, scale, motor[0], motorToLegPos0 + m * PxVec3(PxCos(angle0), PxSin(angle0), 0));
createLeg(mCrabBody, bodyToLegPos1, legMass, params, scale, motor[1], motorToLegPos1 + m * PxVec3(PxCos(angle1), PxSin(angle1), 0));
bodyToLegPos0.z -= legSpacing;
bodyToLegPos1.z -= legSpacing;
motorToLegPos0.z -= legSpacing;
motorToLegPos1.z -= legSpacing;
}
}
setupSQFiltering(mCrabBody, crabId);
return this;
}
void Crab::createLeg(PxRigidDynamic* mainBody, PxVec3 localPos, PxReal mass, const LegParameters& params, PxReal scale, PxRigidDynamic* motor, PxVec3 motorAttachmentPos)
{
PxVec3 crabLegPos = mainBody->getGlobalPose().p + localPos;
// params for Theo Jansen's machine
// check edge ascii art in Crab.h
const PxReal stickExt = 0.125f * 0.5f * scale;
const PxReal a = params.a * scale;
const PxReal b = params.b * scale;
const PxReal c = params.c * scale;
const PxReal d = params.d * scale;
const PxReal e = params.e * scale;
const PxReal m = params.m * scale;
const PxReal n = params.n * scale;
const PxReal density = 1.0f;
PxBoxGeometry boxGeomA = PxBoxGeometry(a, stickExt, stickExt);
PxBoxGeometry boxGeomB = PxBoxGeometry(stickExt, b, stickExt);
PxBoxGeometry boxGeomC = PxBoxGeometry(stickExt, c, stickExt);
//PxCapsuleGeometry capsGeomD = PxCapsuleGeometry(stickExt*2.0f, d);
PxBoxGeometry boxGeomD = PxBoxGeometry(d, stickExt*3.0f, stickExt*3.0f);
ShaderMaterial mat;
mat.init();
PxVec3 vel(0), omega(0);
SimScene* simScene = mManager->getSceneCrab()->getSimScene();
PxPhysics& physics = mManager->getPhysics();
for (PxU32 leg = 0; leg < 2; leg++)
{
bool left = (leg == 0);
#define MIRROR(X) left ? -1.0f*(X) : (X)
PxVec3 startPos = crabLegPos + PxVec3(MIRROR(e), 0, 0);
// create upper triangle from boxes
PxRigidDynamic* upperTriangle = NULL;
{
PxTransform poseA = PxTransform(PxVec3(MIRROR(a), 0, 0));
PxTransform poseB = PxTransform(PxVec3(MIRROR(0), b, 0));
simScene->getCompoundCreator()->createBox(2.f*boxGeomA.halfExtents, &poseA);
simScene->getCompoundCreator()->createBox(2.f*boxGeomB.halfExtents, &poseB, false);
Compound* upperTriangleCompound = mManager->createObject(PxTransform(startPos), vel, omega, false, mat);
upperTriangle = upperTriangleCompound->getPxActor();
upperTriangle->setAngularDamping(0.5f);
PxRigidBodyExt::updateMassAndInertia(*upperTriangle, density);
setShapeFlag(upperTriangle, PxShapeFlag::eSCENE_QUERY_SHAPE, false);
}
// create lower triangle from boxes
PxRigidDynamic* lowerTriangle = NULL;
{
PxTransform poseA = PxTransform(PxVec3(MIRROR(a), 0, 0));
//PxTransform poseD = PxTransform(PxVec3(MIRROR(0), -d, 0));
PxTransform poseD = PxTransform(PxVec3(MIRROR(0), -d, 0), PxQuat(PxHalfPi, PxVec3(0, 0, 1)));
simScene->getCompoundCreator()->createBox(2.f*boxGeomA.halfExtents, &poseA);
simScene->getCompoundCreator()->createBox(2.f*boxGeomD.halfExtents, &poseD, false);
Compound* lowerTriangleCompound = mManager->createObject(PxTransform(startPos + PxVec3(0, -2.0f*c, 0)), vel, omega, false, mat);
lowerTriangle = lowerTriangleCompound->getPxActor();
lowerTriangle->setAngularDamping(0.5f);
PxShape* shapes[2];
lowerTriangle->getShapes(shapes, 2);
shapes[1]->setMaterials(&mMaterial, 1);
PxRigidBodyExt::updateMassAndInertia(*lowerTriangle, density);
setShapeFlag(lowerTriangle, PxShapeFlag::eSCENE_QUERY_SHAPE, false);
}
// create vertical boxes to connect the triangles
simScene->getCompoundCreator()->createBox(2.f*boxGeomC.halfExtents);
Compound* verticalBox0Compound = mManager->createObject(PxTransform(startPos + PxVec3(0, -c, 0)), vel, omega, false, mat);
PxRigidDynamic* verticalBox0 = verticalBox0Compound->getPxActor();
PxRigidBodyExt::updateMassAndInertia(*verticalBox0, 10.f);
setShapeFlag(verticalBox0, PxShapeFlag::eSCENE_QUERY_SHAPE, false);
simScene->getCompoundCreator()->createBox(2.f*boxGeomC.halfExtents);
Compound* verticalBox1Compound = mManager->createObject(PxTransform(startPos + PxVec3(MIRROR(2.0f*a), -c, 0)), vel, omega, false, mat);
PxRigidDynamic* verticalBox1 = verticalBox1Compound->getPxActor();
PxRigidBodyExt::updateMassAndInertia(*verticalBox1, 10.f);
setShapeFlag(verticalBox1, PxShapeFlag::eSCENE_QUERY_SHAPE, false);
// disable gravity
/*upperTriangle->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
lowerTriangle->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
verticalBox0->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
verticalBox1->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);*/
// set mass
PxRigidBodyExt::setMassAndUpdateInertia(*upperTriangle, mass);
PxRigidBodyExt::setMassAndUpdateInertia(*lowerTriangle, mass);
PxRigidBodyExt::setMassAndUpdateInertia(*verticalBox0, mass);
PxRigidBodyExt::setMassAndUpdateInertia(*verticalBox1, mass);
// turn off collision upper triangle and vertical boxes
setShapeFlag(upperTriangle, PxShapeFlag::eSIMULATION_SHAPE, false);
setShapeFlag(verticalBox0, PxShapeFlag::eSIMULATION_SHAPE, false);
setShapeFlag(verticalBox1, PxShapeFlag::eSIMULATION_SHAPE, false);
// d6 joint in lower corner of upper triangle
PxD6Joint* jointD6 = PxD6JointCreate(physics,
mainBody, PxTransform(PxVec3(MIRROR(e), 0, 0) + localPos, PxQuat(-PxHalfPi, PxVec3(0, 1, 0))),
upperTriangle, PxTransform(PxVec3(0, 0, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))));
jointD6->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
// 4 d6 joints to connect triangles
jointD6 = PxD6JointCreate(physics,
upperTriangle, PxTransform(PxVec3(0, 0, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))),
verticalBox0, PxTransform(PxVec3(0, c, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))));
jointD6->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
jointD6 = PxD6JointCreate(physics,
upperTriangle, PxTransform(PxVec3(MIRROR(2.0f*a), 0, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))),
verticalBox1, PxTransform(PxVec3(0, c, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))));
jointD6->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
jointD6 = PxD6JointCreate(physics,
lowerTriangle, PxTransform(PxVec3(0, 0, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))),
verticalBox0, PxTransform(PxVec3(0, -c, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))));
jointD6->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
//mJoints.push_back(jointD6);
jointD6 = PxD6JointCreate(physics,
lowerTriangle, PxTransform(PxVec3(MIRROR(2.0f*a), 0, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))),
verticalBox1, PxTransform(PxVec3(0, -c, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))));
jointD6->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
// 2 distance constraints to connect motor with the triangles
PxTransform motorTransform = PxTransform(motorAttachmentPos);
PxReal dist0 = PxSqrt((2.0f*b - n)*(2.0f*b - n) + (e - m)*(e - m));
PxReal dist1 = PxSqrt((2.0f*c + n)*(2.0f*c + n) + (e - m)*(e - m));
PxDistanceJoint* distJoint0 = PxDistanceJointCreate(physics, upperTriangle, PxTransform(PxVec3(0, 2.0f*b, 0)), motor, motorTransform);
// set min & max distance to dist0
distJoint0->setMaxDistance(dist0);
distJoint0->setMinDistance(dist0);
// setup damping & spring
//distJoint0->setDamping(0.1f);
//distJoint0->setStiffness(100.0f);
distJoint0->setDamping(0.2f);
distJoint0->setStiffness(500.0f);
distJoint0->setDistanceJointFlags(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED | PxDistanceJointFlag::eMIN_DISTANCE_ENABLED | PxDistanceJointFlag::eSPRING_ENABLED);
/*
jointD6 = PxD6JointCreate(physics, upperTriangle, PxTransform(PxVec3(0, 2.0f*b, 0)), motor, motorTransform);
jointD6->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
jointD6->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
jointD6->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
jointD6->setMotion(PxD6Axis::eX, PxD6Motion::eLIMITED);
jointD6->setMotion(PxD6Axis::eY, PxD6Motion::eLIMITED);
jointD6->setMotion(PxD6Axis::eZ, PxD6Motion::eLIMITED);
jointD6->setLinearLimit(PxJointLinearLimit(dist0, PxSpring(100.f, 0.1f)));
mJoints.push_back(jointD6);*/
PxDistanceJoint* distJoint1 = PxDistanceJointCreate(physics, lowerTriangle, PxTransform(PxVec3(0, 0, 0)), motor, motorTransform);
// set min & max distance to dist0
distJoint1->setMaxDistance(dist1);
distJoint1->setMinDistance(dist1);
// setup damping & spring
/* distJoint1->setDamping(0.1f);
distJoint1->setStiffness(100.0f);*/
distJoint1->setDamping(0.2f);
distJoint1->setStiffness(500.0f);
distJoint1->setDistanceJointFlags(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED | PxDistanceJointFlag::eMIN_DISTANCE_ENABLED | PxDistanceJointFlag::eSPRING_ENABLED);
/*jointD6 = PxD6JointCreate(physics, lowerTriangle, PxTransform(PxVec3(0, 0, 0)), motor, motorTransform);
mJoints.push_back(jointD6);*/
// one distance joint to ensure that the vertical boxes do not get stuck if they cross the diagonal.
PxReal halfDiagDist = PxSqrt(a*a + c*c);
PxDistanceJoint* noFlip = PxDistanceJointCreate(physics, lowerTriangle, PxTransform(PxVec3(MIRROR(2.0f*a), 0, 0)), upperTriangle, PxTransform(PxVec3(0)));
// set min & max distance to dist0
noFlip->setMaxDistance(2.0f * (a + c));
noFlip->setMinDistance(halfDiagDist);
// setup damping & spring
noFlip->setDamping(1.0f);
noFlip->setStiffness(100.0f);
noFlip->setDistanceJointFlags(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED | PxDistanceJointFlag::eMIN_DISTANCE_ENABLED | PxDistanceJointFlag::eSPRING_ENABLED);
}
}
void Crab::update(PxReal dt)
{
PxReal maxVelocity = 16.0f;
PxReal velDamping = 0.8f;
flushAccelerationBuffer();
for (PxU32 i = 0; i < 2; i++)
{
/*PxReal prevVelocity = mMotorJoint[i]->getDriveVelocity();
PxReal velocityChange = mAcceleration[i] ? mAcceleration[i] * dt : -prevVelocity*velDamping*dt;
PxReal newVelocity = PxClamp(prevVelocity + velocityChange, -maxVelocity, maxVelocity);
mMotorJoint[i]->setDriveVelocity(newVelocity);*/
PxVec3 linear, angular;
mMotorJoint[i]->getDriveVelocity(linear, angular);
PxReal prevVelocity = -angular.x;
PxReal velocityChange = mAcceleration[i] ? mAcceleration[i] * dt : -prevVelocity*velDamping*dt;
PxReal newVelocity = PxClamp(prevVelocity + velocityChange, -maxVelocity, maxVelocity);
mMotorJoint[i]->setDriveVelocity(linear, PxVec3(-newVelocity, 0.f, 0.f));
if (mAcceleration[i] != 0.0f)
mCrabBody->wakeUp();
mAcceleration[i] = 0;
}
// add up elapsed time
mAccumTime += dt;
{
mElapsedTime = mAccumTime;
mAccumTime = 0;
}
}
void Crab::run()
{
scanForObstacles();
updateState();
}
void Crab::setAcceleration(PxReal leftAcc, PxReal rightAcc)
{
mAccelerationBuffer[0] = -leftAcc;
mAccelerationBuffer[1] = -rightAcc;
}
void Crab::flushAccelerationBuffer()
{
mAcceleration[0] = mAccelerationBuffer[0];
mAcceleration[1] = mAccelerationBuffer[1];
}
void Crab::scanForObstacles()
{
if (mCrabState != CrabState::eWAITING)
{
if (mUpdateFrequency == 0)
{
mUpdateFrequency = UPDATE_FREQUENCY_RESET;
PxSceneReadLock scopedLock(mManager->getScene());
PxTransform crabPose = mCrabBody->getGlobalPose();
PxVec3 rayStart[2] = { PxVec3(2.0f, 0.0f, 0.0f), PxVec3(-2.0f, 0.0f, 0.0f) };
rayStart[0] = crabPose.transform(rayStart[0]);
rayStart[1] = crabPose.transform(rayStart[1]);
PxReal rayDist = 100.0f;
PxShape* shape;
mCrabBody->getShapes(&shape, 1);
PxBoxGeometry boxGeom;
boxGeom.halfExtents = mCrabBodyDimensions;
//bool result = shape->getBoxGeometry(boxGeom); //crab body isn't using a box anymore
PxVec3 forward = crabPose.rotate(PxVec3(0, 0, 1));
PxVec3 sideDir = (forward.cross(PxVec3(0, 1, 0)) - PxVec3(0, 0.4f, 0)).getNormalized();
// setup raycasts
// 3 front & 3 back
for (PxU32 j = 0; j < 2; j++)
{
//PxVec3 rayDir = crabPose.rotate(PxVec3(j ? -1.0f : 1.0f, 0, 0));
PxVec3 rayDir = j ? -sideDir : sideDir;
PxQuat rotY = PxQuat(0.4f, PxVec3(0, 1, 0));
rayDir = rotY.rotateInv(rayDir);
for (PxU32 i = 0; i < 3; i++)
{
rayDir.normalize();
//mSqRayBuffer->mBatchQuery->raycast(rayStart[j], rayDir, rayDist);
mSqSweepBuffer->mBatchQuery->sweep(boxGeom, crabPose, rayDir, rayDist, 0, PxHitFlag::eDEFAULT,
PxQueryFilterData(shape->getQueryFilterData(), PxQueryFlags(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER)));
rayDir = rotY.rotate(rayDir);
}
}
mSqSweepBuffer->mBatchQuery->execute();
for (PxU32 i = 0; i < mSqSweepBuffer->mQueryResultSize; i++)
{
PxSweepQueryResult& result = mSqSweepBuffer->mSweepResults[i];
if (result.queryStatus == PxBatchQueryStatus::eSUCCESS && result.getNbAnyHits() == 1)
{
const PxSweepHit& hit = result.getAnyHit(0);
mDistances[i] = hit.distance;
// don't see flat terrain as wall
//SampleRenderer::RendererColor rayColor(0, 0, 255);
//PxReal angle = hit.normal.dot(crabPose.q.rotate(PxVec3(0, 1, 0)));
PxReal angle = hit.normal.dot(PxVec3(0, 1, 0));
if (angle > 0.92f) // = 11.5 degree difference
{
mDistances[i] = rayDist;
// rayColor = SampleRenderer::RendererColor(0, 255, 0);
}
}
else
mDistances[i] = rayDist;
}
}
mUpdateFrequency--;
}
}
void Crab::initState(CrabState::Enum state)
{
//if the original crabstate is waitting, we need to do scan for obstacles. Otherwise, we have done the scan for obstacles before we updateState
if (mCrabState == CrabState::eWAITING)
scanForObstacles();
mCrabState = state;
mStateTime = gDefaultStateTime[mCrabState];
}
void Crab::updateState()
{
// update remaining time in current state
// transition if needed
mStateTime -= mElapsedTime;
mElapsedTime = 0;
if (mStateTime <= 0.0f)
{
initState(CrabState::Enum((rand()%(CrabState::eNUM_STATES-1))+1));
}
PxTransform crabPose;
{
PxSceneReadLock scopedLock(mManager->getScene());
crabPose = mCrabBody->getGlobalPose();
}
PxReal leftAcc = 0, rightAcc = 0;
// compute fwd and bkwd distances
static const PxReal minDist = 10.0f;
static const PxReal fullSpeedDist = 50.0f;
static const PxReal recipFullSpeedDist = 1.0f / fullSpeedDist;
PxReal fDist = 0, bDist = 0;
fDist = PxMin(mDistances[0], PxMin(mDistances[1], mDistances[2]));
bDist = PxMin(mDistances[3], PxMin(mDistances[4], mDistances[5]));
// handle states
if (mCrabState == CrabState::eMOVE_FWD)
{
if (fDist < minDist && fDist < bDist)
{
initState(CrabState::eMOVE_BKWD);
}
else
{
leftAcc = PxMin(fullSpeedDist, mDistances[0])*recipFullSpeedDist*2.0f - 1.0f;
rightAcc = PxMin(fullSpeedDist, mDistances[2])*recipFullSpeedDist*2.0f - 1.0f;
leftAcc *= 3.0f;
rightAcc *= 3.0f;
}
}
else if (mCrabState == CrabState::eMOVE_BKWD)
{
if (bDist < minDist && bDist < fDist)
{
// find rotation dir, where we have some free space
bool rotateLeft = mDistances[0] < mDistances[2];
initState(rotateLeft ? CrabState::eROTATE_LEFT : CrabState::eROTATE_RIGHT);
}
else
{
leftAcc = -(PxMin(fullSpeedDist, mDistances[5])*recipFullSpeedDist*2.0f - 1.0f);
rightAcc = -(PxMin(fullSpeedDist, mDistances[3])*recipFullSpeedDist*2.0f - 1.0f);
leftAcc *= 3.0f;
rightAcc *= 3.0f;
}
}
else if (mCrabState == CrabState::eROTATE_LEFT)
{
leftAcc = -3.0f;
rightAcc = 3.0f;
if (fDist > minDist)
{
initState(CrabState::eMOVE_FWD);
}
}
else if (mCrabState == CrabState::eROTATE_RIGHT)
{
leftAcc = 3.0f;
rightAcc = -3.0f;
if (fDist > minDist)
{
initState(CrabState::eMOVE_FWD);
}
}
else if (mCrabState == CrabState::ePANIC)
{
}
else if (mCrabState == CrabState::eWAITING)
{
// have a break
}
// change acceleration
setAcceleration(leftAcc, rightAcc);
}
PxQueryHitType::Enum myFilterShader(
PxFilterData queryFilterData, PxFilterData objectFilterData,
const void* constantBlock, PxU32 constantBlockSize,
PxHitFlags& hitFlags)
{
if (objectFilterData.word0 == 128 || objectFilterData.word3 == queryFilterData.word3)
return PxQueryHitType::eNONE;
return PxQueryHitType::eBLOCK;
}
SqRayBuffer::SqRayBuffer(Crab* crab, PxU32 numRays, PxU32 numHits) :
mQueryResultSize(numRays), mHitSize(numHits)
{
mCrab = crab;
mOrigAddresses[0] = malloc(mQueryResultSize*sizeof(PxRaycastQueryResult) + 15);
mOrigAddresses[1] = malloc(mHitSize*sizeof(PxRaycastHit) + 15);
mRayCastResults = reinterpret_cast<PxRaycastQueryResult*>((size_t(mOrigAddresses[0]) + 15) & ~15);
mRayCastHits = reinterpret_cast<PxRaycastHit*>((size_t(mOrigAddresses[1]) + 15)& ~15);
PxBatchQueryDesc batchQueryDesc(mQueryResultSize, 0, 0);
batchQueryDesc.queryMemory.userRaycastResultBuffer = mRayCastResults;
batchQueryDesc.queryMemory.userRaycastTouchBuffer = mRayCastHits;
batchQueryDesc.queryMemory.raycastTouchBufferSize = mHitSize;
batchQueryDesc.preFilterShader = myFilterShader;
mBatchQuery = mCrab->getManager()->getScene().createBatchQuery(batchQueryDesc);
}
SqRayBuffer::~SqRayBuffer()
{
mBatchQuery->release();
free(mOrigAddresses[0]);
free(mOrigAddresses[1]);
}
void SqRayBuffer::setScene(PxScene* scene)
{
PxBatchQueryDesc batchQueryDesc(mQueryResultSize, 0, 0);
batchQueryDesc.queryMemory.userRaycastResultBuffer = mRayCastResults;
batchQueryDesc.queryMemory.userRaycastTouchBuffer = mRayCastHits;
batchQueryDesc.queryMemory.raycastTouchBufferSize = mHitSize;
batchQueryDesc.preFilterShader = myFilterShader;
mBatchQuery = scene->createBatchQuery(batchQueryDesc);
}
SqSweepBuffer::SqSweepBuffer(Crab* crab, PxU32 numRays, PxU32 numHits) :
mQueryResultSize(numRays), mHitSize(numHits)
{
mCrab = crab;
mOrigAddresses[0] = malloc(mQueryResultSize*sizeof(PxSweepQueryResult) + 15);
mOrigAddresses[1] = malloc(mHitSize*sizeof(PxSweepHit) + 15);
mSweepResults = reinterpret_cast<PxSweepQueryResult*>((size_t(mOrigAddresses[0]) + 15) & ~15);
mSweepHits = reinterpret_cast<PxSweepHit*>((size_t(mOrigAddresses[1]) + 15)& ~15);
PxBatchQueryDesc batchQueryDesc(0, mQueryResultSize, 0);
batchQueryDesc.queryMemory.userSweepResultBuffer = mSweepResults;
batchQueryDesc.queryMemory.userSweepTouchBuffer = mSweepHits;
batchQueryDesc.queryMemory.sweepTouchBufferSize = mHitSize;
batchQueryDesc.preFilterShader = myFilterShader;
mBatchQuery = mCrab->getManager()->getScene().createBatchQuery(batchQueryDesc);
}
void SqSweepBuffer::setScene(PxScene* scene)
{
PxBatchQueryDesc batchQueryDesc(0, mQueryResultSize, 0);
batchQueryDesc.queryMemory.userSweepResultBuffer = mSweepResults;
batchQueryDesc.queryMemory.userSweepTouchBuffer = mSweepHits;
batchQueryDesc.queryMemory.sweepTouchBufferSize = mHitSize;
batchQueryDesc.preFilterShader = myFilterShader;
mBatchQuery = scene->createBatchQuery(batchQueryDesc);
}
SqSweepBuffer::~SqSweepBuffer()
{
mBatchQuery->release();
free(mOrigAddresses[0]);
free(mOrigAddresses[1]);
}

View File

@ -0,0 +1,191 @@
//
// 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-2018 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 CRAB_H
#define CRAB_H
#include "foundation/Px.h"
#include "foundation/PxSimpleTypes.h"
#include "common/PxPhysXCommonConfig.h"
#include "task/PxTask.h"
#include <vector>
#define UPDATE_FREQUENCY_RESET 10
struct CrabState
{
enum Enum
{
eWAITING,
eMOVE_FWD,
eMOVE_BKWD,
eROTATE_LEFT,
eROTATE_RIGHT,
ePANIC,
eNUM_STATES,
};
};
namespace physx
{
class PxRigidDynamic;
class PxRevoluteJoint;
class PxJoint;
class PxScene;
}
// Edge Labels for Theo Jansen's Mechanism
// _.
// ,' | m
// ,' |2b .....
// ,' 2a | e |n
// +-------+---------+
// | |
// | |2c
// | |
// +-------+
// `. |
// `. |2d
// `. |
// `|
struct LegParameters
{
physx::PxReal a; // half x-dim leg
physx::PxReal b; // half height upper triangle
physx::PxReal c; // half height distance joints (square)
physx::PxReal d; // half height lower triangle
physx::PxReal e; // x distance from main body centre
physx::PxReal m; // half extent of the motor box
physx::PxReal n; // y offset of the motor from the main body centre
};
class Crab;
class CrabManager;
struct SqRayBuffer
{
SqRayBuffer(Crab* crab, physx::PxU32 numRays, physx::PxU32 numHits);
~SqRayBuffer();
Crab* mCrab;
physx::PxBatchQuery* mBatchQuery;
physx::PxRaycastQueryResult* mRayCastResults;
physx::PxRaycastHit* mRayCastHits;
physx::PxU32 mQueryResultSize;
physx::PxU32 mHitSize;
void* mOrigAddresses[2];
void setScene(physx::PxScene* scene);
private:
SqRayBuffer& operator=(const SqRayBuffer&);
};
struct SqSweepBuffer
{
SqSweepBuffer(Crab* crab, physx::PxU32 numRays, physx::PxU32 numHits);
~SqSweepBuffer();
Crab* mCrab;
physx::PxBatchQuery* mBatchQuery;
physx::PxSweepQueryResult* mSweepResults;
physx::PxSweepHit* mSweepHits;
physx::PxU32 mQueryResultSize;
physx::PxU32 mHitSize;
void* mOrigAddresses[2];
void setScene(physx::PxScene* scene);
private:
SqSweepBuffer& operator=(const SqSweepBuffer&);
};
class Crab
{
public:
Crab(CrabManager* crabManager, physx::PxU32 updateFrequency);
~Crab();
void update(physx::PxReal dt);
void setAcceleration(physx::PxReal leftAcc, physx::PxReal rightAcc);
void flushAccelerationBuffer();
PX_INLINE const physx::PxRigidDynamic* getCrabBody() const { return mCrabBody; }
PX_INLINE physx::PxRigidDynamic* getCrabBody() { return mCrabBody; }
void run();
void setScene(physx::PxScene* scene);
void initMembers();
Crab* create(const physx::PxVec3& _crabPos, const physx::PxReal crabDepth, const physx::PxReal scale, const physx::PxReal legMass, const physx::PxU32 numLegs);
physx::PxVec3 getPlaceOnFloor(physx::PxVec3 pos);
void createLeg(physx::PxRigidDynamic* mainBody, physx::PxVec3 localPos, physx::PxReal mass, const LegParameters& params, physx::PxReal scale, physx::PxRigidDynamic* motor, physx::PxVec3 motorAttachmentPos);
void scanForObstacles();
void updateState();
void initState(CrabState::Enum state);
void setManager(CrabManager* crabManager) { mManager = crabManager; }
CrabManager* getManager(){ return mManager; }
private:
CrabManager* mManager;
physx::PxRigidDynamic* mCrabBody;
physx::PxVec3 mCrabBodyDimensions;
//physx::PxRevoluteJoint* mMotorJoint[2];
physx::PxD6Joint* mMotorJoint[2];
physx::PxMaterial* mMaterial;
physx::PxReal mAcceleration[2];
//SqRayBuffer* mSqRayBuffer;
SqSweepBuffer* mSqSweepBuffer;
physx::PxReal mLegHeight;
CrabState::Enum mCrabState;
physx::PxReal mStateTime;
physx::PxReal mDistances[10];
physx::PxReal mAccumTime;
physx::PxReal mElapsedTime;
physx::PxReal mAccelerationBuffer[2];
physx::PxU32 mUpdateFrequency;
};
#endif

View File

@ -0,0 +1,159 @@
//
// 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-2018 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxPhysicsAPI.h"
#include "extensions/PxExtensionsAPI.h"
#include "SceneCrab.h"
#include "Crab.h"
#include "CrabManager.h"
#include "SimScene.h"
#include "CompoundCreator.h"
#include <GL/glut.h>
#include "PxTkStream.h"
#include "PxTkFile.h"
#include "CmTask.h"
using namespace PxToolkit;
CrabManager::CrabManager() : mSceneCrab(NULL), mCrabs(NULL), mCompletionTask(mSync)
{
mSync.set();
}
CrabManager::~CrabManager()
{
for (PxU32 i = 0; i < mCrabs.size(); ++i)
{
mCrabs[i]->~Crab();
PX_FREE(mCrabs[i]);
}
mCrabs.clear();
for (PxU32 i = 0; i < mUpdateStateTask.size(); ++i)
{
mUpdateStateTask[i]->~CrabUpdateStateTask();
PX_FREE(mUpdateStateTask[i]);
}
mUpdateStateTask.clear();
}
PxScene& CrabManager::getScene()
{
return mSceneCrab->getScene();
}
PxPhysics& CrabManager::getPhysics()
{
return mSceneCrab->getPhysics();
}
void CrabManager::setSceneCrab(SceneCrab* sceneCrab)
{
mSceneCrab = sceneCrab;
}
void CrabManager::setScene(PxScene* scene)
{
for (PxU32 a = 0; a < mCrabs.size(); ++a)
{
mCrabs[a]->setScene(scene);
}
}
SceneCrab* CrabManager::getSceneCrab()
{
return mSceneCrab;
}
Compound* CrabManager::createObject(const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega,
bool particles, const ShaderMaterial &mat, bool useSecondaryPattern, ShaderShadow* shader)
{
return mSceneCrab->createObject(pose, vel, omega, particles, mat, useSecondaryPattern, shader,1,1);
}
void CrabManager::initialize(const PxU32 nbCrabs)
{
mCrabs.reserve(nbCrabs);
}
void CrabManager::createCrab(const PxVec3& crabPos, const physx::PxReal crabDepth, const PxReal scale, const PxReal legMass, const PxU32 numLegs)
{
PxU32 idx = mCrabs.size();
mCrabs.pushBack(PX_PLACEMENT_NEW(PX_ALLOC(sizeof(Crab), PX_DEBUG_EXP("Crabs")), Crab)(this, idx%UPDATE_FREQUENCY_RESET));
mCrabs[idx]->create(crabPos, crabDepth, scale, legMass, numLegs);
PxU32 taskSize = mUpdateStateTask.size();
if (taskSize == 0 || ((mCrabs.size() - mUpdateStateTask[taskSize - 1]->mStartIndex) == 64))
{
//Create a new task...
mUpdateStateTask.pushBack(PX_PLACEMENT_NEW(PX_ALLOC(sizeof(CrabUpdateStateTask), PX_DEBUG_EXP("CrabUpdateTask")), CrabUpdateStateTask)(this, idx, mCrabs.size()));
}
mUpdateStateTask[mUpdateStateTask.size() - 1]->mEndIndex = mCrabs.size();
}
void CrabManager::update(const PxReal dt)
{
mSync.reset();
PxSceneWriteLock scopedLock(getScene());
PxTaskManager* manager = getScene().getTaskManager();
mCompletionTask.setContinuation(*manager, NULL);
for (PxU32 i = 0; i < mCrabs.size(); ++i)
{
mCrabs[i]->update(dt);
}
for (PxU32 i = 0; i < mUpdateStateTask.size(); ++i)
{
mUpdateStateTask[i]->setContinuation(&mCompletionTask);
mUpdateStateTask[i]->removeReference();
}
mCompletionTask.removeReference();
//mSync.wait();
}
void CrabManager::syncWork()
{
mSync.wait();
}
void CrabUpdateStateTask::runInternal()
{
Crab** crab = mCrabManager->getCrabs();
for (PxU32 i = mStartIndex; i < mEndIndex; ++i)
{
crab[i]->run();
}
}

View File

@ -0,0 +1,126 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2018 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 CRAB_MANAGER_H
#define CRAB_MANAGER_H
#include "foundation/Px.h"
#include "foundation/PxSimpleTypes.h"
#include "common/PxPhysXCommonConfig.h"
#include "PsSync.h"
#include "CmTask.h"
#include "PsArray.h"
class SceneCrab;
class Crab;
class Compound;
struct ShaderMaterial;
class ShaderShadow;
class CrabManager;
class CompletionTask : public physx::Cm::Task
{
physx::shdfnd::Sync& mSync;
public:
CompletionTask(physx::shdfnd::Sync& sync) : physx::Cm::Task(0), mSync(sync)
{
}
virtual void runInternal() { mSync.set(); }
virtual const char* getName() const { return "CrabCompletionTask"; }
};
class CrabUpdateStateTask : public physx::Cm::Task
{
public:
CrabManager* mCrabManager;
physx::PxU32 mStartIndex;
physx::PxU32 mEndIndex;
CrabUpdateStateTask(CrabManager* crabManager, const physx::PxU32 startIndex, const physx::PxU32 endIndex) :
physx::Cm::Task(0), mCrabManager(crabManager), mStartIndex(startIndex), mEndIndex(endIndex)
{
}
virtual void runInternal();
virtual const char* getName() const { return "CrabCompletionTask"; }
};
class CrabManager
{
public:
CrabManager();
~CrabManager();
void initialize(const physx::PxU32 nbCrabs);
void setCrabScene(SceneCrab* sceneCrab) { mSceneCrab = sceneCrab; }
void createCrab(const physx::PxVec3& crabPos, const physx::PxReal crabDepth, const physx::PxReal scale, const physx::PxReal legMass, const physx::PxU32 nbLegs);
void update(const physx::PxReal dt);
physx::PxScene& getScene();
physx::PxPhysics& getPhysics();
//SimScene* getSimScene();
void setScene(physx::PxScene* scene);
void setSceneCrab(SceneCrab* sceneCrab);
SceneCrab* getSceneCrab();
Compound* createObject(const physx::PxTransform &pose, const physx::PxVec3 &vel, const physx::PxVec3 &omega,
bool particles, const ShaderMaterial &mat, bool useSecondaryPattern = false, ShaderShadow* shader = NULL);
void syncWork();
Crab** getCrabs() { return mCrabs.begin(); }
private:
SceneCrab* mSceneCrab;
//Crab* mCrabs;
//physx::PxU32 mNbCrabs;
physx::shdfnd::Array<Crab*> mCrabs;
physx::shdfnd::Sync mSync;
CompletionTask mCompletionTask;
//CrabUpdateStateTask* mUpdateStateTask;
physx::shdfnd::Array<CrabUpdateStateTask*> mUpdateStateTask;
};
#endif

View File

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

View File

@ -0,0 +1,52 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#ifndef RT_ACTOR_H
#define RT_ACTOR_H
//#include <PxFoundation.h>
#include "ActorBase.h"
class RegularCell3D;
using namespace physx;
using namespace physx::fracture;
class Actor : public base::Actor
{
friend class SimScene;
protected:
Actor(base::SimScene* scene);
public:
virtual ~Actor();
protected:
};
#endif

View File

@ -0,0 +1,97 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "Mesh.h"
#include "CompoundGeometry.h"
#include "CompoundCreator.h"
#include "PxConvexMeshGeometry.h"
#include "PxRigidBodyExt.h"
#include "foundation/PxMat44.h"
#include "PxScene.h"
#include "PxShape.h"
#include "SimScene.h"
#include "Compound.h"
#include "Convex.h"
#include "foundation/PxMathUtils.h"
#include <vector>
#include <stdio.h>
#include "MathUtils.h"
using namespace std;
#define CREATE_DEBRIS 1
float Compound::getSleepingThresholdRB()
{
return 0.1f;
}
// --------------------------------------------------------------------------------------------
void Compound::draw(bool useShader, bool debug)
{
if (useShader && mShader)
mShader->activate(mShaderMat);
else {
glColor3f(mShaderMat.color[0], mShaderMat.color[1], mShaderMat.color[2]);
}
for (int i = 0; i < (int)mConvexes.size(); i++)
mConvexes[i]->draw(debug);
if (useShader && mShader)
mShader->deactivate();
}
// --------------------------------------------------------------------------------------------
void Compound::clear()
{
base::Compound::clear();
mShader = NULL;
mShaderMat.init();
}
void Compound::copyShaders(base::Compound* m)
{
((Compound*)m)->mShader = mShader;
((Compound*)m)->mShaderMat = mShaderMat;
}
void Compound::convexAdded(base::Convex* c, Shader* shader)
{
((SimScene*)mScene)->getConvexRenderer().add(c, shader);
}
void Compound::convexRemoved(base::Convex* c)
{
((SimScene*)mScene)->getConvexRenderer().remove(c);
}

View File

@ -0,0 +1,86 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef COMPOUND
#define COMPOUND
#include <foundation/PxVec3.h>
#include <foundation/PxPlane.h>
#include <foundation/PxBounds3.h>
#include <foundation/PxTransform.h>
#include <PsArray.h>
#include <PxRigidDynamic.h>
#include "Shader.h"
#include "CompoundBase.h"
using namespace physx;
class Convex;
class Particles;
class Mesh;
class SimScene;
class CompoundGeometry;
class XMLParser;
class ShaderShadow;
using namespace physx::fracture;
class Compound : public base::Compound
{
friend class SimScene;
protected:
Compound(SimScene* scene, PxReal contactOffset = 0.005f, PxReal restOffset = -0.001f):
physx::fracture::base::Compound((base::SimScene*)scene,contactOffset,restOffset) {}
public:
virtual void convexAdded(base::Convex* c, Shader* shader);
virtual void convexRemoved(base::Convex* c);
bool createFromXml(XMLParser *p, float scale, const PxTransform &trans, bool ignoreVisualMesh = false);
void setShader(Shader* shader, const ShaderMaterial &mat) { mShader = shader; mShaderMat = mat; }
Shader* getShader() const { return mShader; }
const ShaderMaterial& getShaderMat() { return mShaderMat; }
virtual void draw(bool useShader, bool debug = false);
virtual void clear();
virtual void copyShaders(base::Compound*);
protected:
virtual float getSleepingThresholdRB();
Shader *mShader;
ShaderMaterial mShaderMat;
};
#endif

View File

@ -0,0 +1,65 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "CompoundCreator.h"
#include <algorithm>
#include <assert.h>
#include "CompoundGeometry.h"
#define DEBUG_DRAW 1
#if DEBUG_DRAW
#include <windows.h>
#include <GL/gl.h>
#endif
// -----------------------------------------------------------------------------
void CompoundCreator::debugDraw()
{
#if DEBUG_DRAW
const bool drawEdges = false;
if (drawEdges) {
glBegin(GL_LINES);
for (int i = 0; i < (int)mTetEdges.size(); i++) {
TetEdge &e = mTetEdges[i];
if (e.onSurface)
glColor3f(1.0f, 0.0f, 0.0f);
else
glColor3f(1.0f, 1.0f, 0.0f);
PxVec3 &p0 = mTetVertices[e.i0];
PxVec3 &p1 = mTetVertices[e.i1];
glVertex3f(p0.x, p0.y, p0.z);
glVertex3f(p1.x, p1.y, p1.z);
}
glEnd();
}
#endif
}

View File

@ -0,0 +1,48 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#ifndef COMPOUND_CREATOR_H
#define COMPOUND_CREATOR_H
#include <foundation/PxVec3.h>
#include <foundation/PxTransform.h>
#include <PsArray.h>
#include "CompoundCreatorBase.h"
using namespace physx::fracture;
class CompoundCreator : public base::CompoundCreator
{
friend class SimScene;
public:
virtual void debugDraw();
protected:
CompoundCreator(SimScene* scene): base::CompoundCreator((base::SimScene*)scene) {}
};
#endif

View File

@ -0,0 +1,102 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "CompoundGeometry.h"
#define DEBUG_DRAW 1
#if DEBUG_DRAW
#include <windows.h>
#include <GL/gl.h>
#endif
// -------------------------------------------------------------------------------
void CompoundGeometry::debugDraw(int maxConvexes) const
{
#if DEBUG_DRAW
const bool drawConvexes = true;
const bool drawWireframe = true;
const bool drawClipped = false;
const float clipMaxX = 0.0f;
if (drawConvexes) {
float s = drawClipped ? 1.0f : 0.95f;
if (drawWireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
PxVec3 n;
int num = convexes.size();
if (maxConvexes > 0 && maxConvexes < num)
num = maxConvexes;
for (int i = 0; i < num; i++) {
switch (i%7) {
case 0 : glColor3f(1.0f, 0.0f, 0.0f); break;
case 1 : glColor3f(0.0f, 1.0f, 0.0f); break;
case 2 : glColor3f(1.0f, 0.0f, 1.0f); break;
case 3 : glColor3f(0.0f, 1.0f, 1.0f); break;
case 4 : glColor3f(1.0f, 0.0f, 1.0f); break;
case 5 : glColor3f(1.0f, 1.0f, 0.0f); break;
case 6 : glColor3f(1.0f, 1.0f, 1.0f); break;
};
const Convex &c = convexes[i];
const PxVec3 *verts = &vertices[c.firstVert];
PxVec3 center;
center = PxVec3(0.0f, 0.0f, 0.0f);
for (int j = 0; j < c.numVerts; j++)
center += verts[j];
center /= (float)c.numVerts;
if (drawClipped && center.x > clipMaxX)
continue;
const int *ids = &indices[c.firstIndex];
for (int j = 0; j < c.numFaces; j++) {
int numVerts = *ids++;
int flags = *ids++;
n = (verts[ids[1]] - verts[ids[0]]).cross(verts[ids[2]] - verts[ids[0]]);
n.normalize();
glNormal3f(n.x, n.y, n.z);
glBegin(GL_POLYGON);
for (int k = 0; k < numVerts; k++) {
PxVec3 p = verts[ids[k]];
p = center + (p - center) * s;
glVertex3f(p.x, p.y, p.z);
}
glEnd();
ids += numVerts;
}
}
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
#endif
}

View File

@ -0,0 +1,45 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef COMPOUND_GEOMETRY
#define COMPOUND_GEOMETRY
#include <foundation/PxVec3.h>
#include <foundation/PxPlane.h>
#include <PsArray.h>
#include "CompoundGeometryBase.h"
using namespace physx;
class CompoundGeometry : public physx::fracture::base::CompoundGeometry
{
public:
virtual void debugDraw(int maxConvexes = 0) const;
};
#endif

View File

@ -0,0 +1,276 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "PxPhysics.h"
#include "PxCooking.h"
#include "PxDefaultStreams.h"
#include "PxShape.h"
#include "foundation/PxMath.h"
#include "PxRigidDynamic.h"
#include "PxConvexMesh.h"
#include "foundation/PxMat44.h"
#include "foundation/PxMathUtils.h"
#include "CompoundGeometry.h"
#include "Shader.h"
#include "PolygonTriangulator.h"
#include "Convex.h"
#include "PhysXMacros.h"
class physx::PxPhysics;
class physx::PxCooking;
class physx::PxActor;
class physx::PxScene;
class physx::PxConvexMesh;
#define COOK_TRIANGLES 0
#include <algorithm>
// --------------------------------------------------------------------------------------------
void Convex::draw(bool debug)
{
//if (!mIsGhostConvex)
// return; // foo
bool drawConvex = true;
bool drawVisMesh = true;
bool wireframe = false;
bool drawWorldBounds = false;
bool drawInsideTest = false;
bool drawVisPolys = true;
bool drawTangents = false;
bool drawNewFlag = false;
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0f, 1.0f);
if (!debug) {
drawConvex = false;
drawVisMesh = true;
wireframe = false;
drawWorldBounds = false;
drawInsideTest = false;
drawVisPolys = false;
drawTangents = false;
}
if (drawConvex) {
if (mHasExplicitVisMesh)
glColor3f(0.0f, 0.0f, 1.0f);
else if (mIsGhostConvex)
glColor3f(0.0f, 1.0f, 0.0f);
else
glColor3f(1.0f, 1.0f, 1.0f);
glDisable(GL_LIGHTING);
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
PxMat44 mat(getGlobalPose());
glMultMatrixf((GLfloat*)mat.front());
}
glBegin(GL_LINES);
for (int i = 0; i < (int)mFaces.size(); i++) {
Face &f = mFaces[i];
for (int j = 0; j < f.numIndices; j++) {
PxVec3 &p0 = mVertices[mIndices[f.firstIndex + j]];
PxVec3 &p1 = mVertices[mIndices[f.firstIndex + (j+1)%f.numIndices]];
glVertex3f(p0.x, p0.y, p0.z);
glVertex3f(p1.x, p1.y, p1.z);
}
if (drawNewFlag && (f.flags & CompoundGeometry::FF_NEW) && f.numIndices > 0) {
float r = 0.01f;
PxVec3 c(0.0f, 0.0f, 0.0f);
for (int j = 0; j < f.numIndices; j++)
c += mVertices[mIndices[f.firstIndex + j]];
c /= (float)f.numIndices;
glVertex3f(c.x - r, c.y, c.z); glVertex3f(c.x + r, c.y, c.z);
glVertex3f(c.x, c.y - r, c.z); glVertex3f(c.x, c.y + r, c.z);
glVertex3f(c.x, c.y, c.z - r); glVertex3f(c.x, c.y, c.z + r);
}
}
glEnd();
glEnable(GL_LIGHTING);
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
}
if (mVisVertices.empty())
return;
if (drawVisPolys) {
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
PxMat44 mat(getGlobalPose());
glMultMatrixf((GLfloat*)mat.front());
}
glColor3f(1.0f, 0.0f, 0.0f);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
for (int i = 0; i < (int)mVisPolyStarts.size()-1; i++) {
int first = mVisPolyStarts[i];
int num = mVisPolyStarts[i+1] - first;
for (int j = 0; j < num; j++) {
PxVec3 &p0 = mVisVertices[mVisPolyIndices[first + j]];
PxVec3 &p1 = mVisVertices[mVisPolyIndices[first + (j+1)%num]];
glVertex3f(p0.x, p0.y, p0.z);
glVertex3f(p1.x, p1.y, p1.z);
}
}
glEnd();
glEnable(GL_LIGHTING);
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
}
if (drawTangents) {
const float r = 0.1f;
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
PxMat44 mat(getGlobalPose());
glMultMatrixf((GLfloat*)mat.front());
}
glColor3f(1.0f, 1.0f, 0.0f);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
for (int i = 0; i < (int)mVisVertices.size()-1; i++) {
PxVec3 p0 = mVisVertices[i];
PxVec3 p1 = p0 + r * mVisTangents[i];
glVertex3f(p0.x, p0.y, p0.z);
glVertex3f(p1.x, p1.y, p1.z);
}
glEnd();
glEnable(GL_LIGHTING);
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
}
if (drawVisMesh && mVisTriIndices.size() > 0) {
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
PxMat44 mat(getGlobalPose());
glMultMatrixf((GLfloat*)mat.front());
}
if (wireframe) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDisable(GL_LIGHTING);
}
if (debug)
glColor3f(1.0f, 1.0f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &mVisVertices[0]);
glNormalPointer(GL_FLOAT, sizeof(PxVec3), &mVisNormals[0]);
glDrawElements(GL_TRIANGLES, mVisTriIndices.size(), GL_UNSIGNED_INT, &mVisTriIndices[0]);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
if (wireframe) {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_LIGHTING);
}
}
if (drawWorldBounds) {
static const int corners[12 * 2][3] = {
{0,0,0}, {1,0,0}, {0,1,0}, {1,1,0}, {0,1,1}, {1,1,1}, {0,0,1}, {1,0,1},
{0,0,0}, {0,1,0}, {1,0,0}, {1,1,0}, {1,0,1}, {1,1,1}, {0,0,1}, {0,1,1},
{0,0,0}, {0,0,1}, {1,0,0}, {1,0,1}, {1,1,0}, {1,1,1}, {0,1,0}, {0,1,1}};
PxBounds3 b;
getWorldBounds(b);
glBegin(GL_LINES);
for (int i = 0; i < 24; i++) {
glVertex3f(
corners[i][0] ? b.minimum.x : b.maximum.x,
corners[i][1] ? b.minimum.y : b.maximum.y,
corners[i][2] ? b.minimum.z : b.maximum.z);
}
glEnd();
}
if (drawInsideTest) {
PxBounds3 bounds;
bounds.setEmpty();
for (int i = 0; i < (int)mVertices.size(); i++)
bounds.include(mVertices[i]);
int num = 20;
float r = 0.05f * bounds.getDimensions().magnitude() / (float)num;
PxVec3 p;
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_LINES);
for (int xi = 0; xi < num; xi++) {
for (int yi = 0; yi < num; yi++) {
for (int zi = 0; zi < num; zi++) {
p.x = bounds.minimum.x + xi * (bounds.maximum.x - bounds.minimum.x)/num;
p.y = bounds.minimum.y + yi * (bounds.maximum.y - bounds.minimum.y)/num;
p.z = bounds.minimum.z + zi * (bounds.maximum.z - bounds.minimum.z)/num;
if (insideVisualMesh(p)) {
glVertex3f(p.x - r, p.y, p.z); glVertex3f(p.x + r, p.y, p.z);
glVertex3f(p.x, p.y - r, p.z); glVertex3f(p.x, p.y + r, p.z);
glVertex3f(p.x, p.y, p.z - r); glVertex3f(p.x, p.y, p.z + r);
}
}
}
}
glEnd();
}
glDisable(GL_POLYGON_OFFSET_FILL);
}

View File

@ -0,0 +1,65 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef CONVEX
#define CONVEX
#include <PxPhysics.h>
#include <PxCooking.h>
#include <foundation/PxVec3.h>
#include <foundation/PxPlane.h>
#include <foundation/PxBounds3.h>
#include <foundation/PxTransform.h>
#include <PsArray.h>
#include "ConvexBase.h"
using namespace physx;
class physx::PxShape;
class physx::PxActor;
class physx::PxScene;
class physx::PxConvexMesh;
class Compound;
class CompoundGeometry;
using namespace physx::fracture;
class Convex : public base::Convex
{
friend class SimScene;
protected:
Convex(base::SimScene* scene): base::Convex(scene) {}
public:
virtual void draw(bool debug = false);
};
#endif

View File

@ -0,0 +1,403 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "Shader.h"
#include "ConvexRenderer.h"
#include "Compound.h"
#include <foundation/PxMat44.h>
//--------------------------------------------------------
ConvexRenderer::ConvexRenderer()
{
init();
}
//--------------------------------------------------------
ConvexRenderer::~ConvexRenderer()
{
}
//--------------------------------------------------------
void ConvexRenderer::init()
{
mShader = NULL;
mShaderMat.init();
mBumpTextureUVScale = 0.1f;
mExtraNoiseScale = 2.0f;
mRoughnessScale = 0.2f;
mDiffuseTexArray = 0;
mBumpTexArray = 0;
mSpecularTexArray = 0;
mEmissiveReflectSpecPowerTexArray = 0;
mActive = true;
}
//--------------------------------------------------------
void ConvexRenderer::add(const base::Convex* convex, Shader* shader)
{
if (!mActive)
return;
ConvexGroup *g;
// int gnr = 0; // to search all groups
int gnr = 0;// !mGroups.empty() ? mGroups.size() - 1 : 0; // to search only last
int numNewVerts = convex->getVisVertices().size();
while (gnr < (int)mGroups.size() && (mGroups[gnr]->numVertices + numNewVerts >= maxVertsPerGroup || mGroups[gnr]->mShader != shader))
gnr++;
if (gnr == (int)mGroups.size()) { // create new group
g = new ConvexGroup();
g->init();
g->mShader = shader;
gnr = mGroups.size();
mGroups.push_back(g);
}
g = mGroups[gnr];
convex->setConvexRendererInfo(gnr, g->convexes.size());
g->convexes.push_back((Convex*)convex);
g->numIndices += convex->getVisTriIndices().size();
g->numVertices += convex->getVisVertices().size();
g->dirty = true;
}
//--------------------------------------------------------
void ConvexRenderer::remove(const base::Convex* convex)
{
if (!mActive)
return;
int gnr = convex->getConvexRendererGroupNr();
int pos = convex->getConvexRendererGroupPos();
if (gnr < 0 || gnr >= (int)mGroups.size())
return;
ConvexGroup *g = mGroups[gnr];
if (pos < 0 || pos > (int)g->convexes.size())
return;
if (g->convexes[pos] != convex)
return;
g->numIndices -= convex->getVisTriIndices().size();
g->numVertices -= convex->getVisVertices().size();
g->convexes[pos] = g->convexes[g->convexes.size()-1];
g->convexes[pos]->setConvexRendererInfo(gnr, pos);
g->convexes.pop_back();
g->dirty = true;
}
//--------------------------------------------------------
void ConvexRenderer::updateRenderBuffers()
{
/*
static int maxNumV = 0;
static int maxNumI = 0;
static int maxNumC = 0;
static int maxNumG = 0;
if (mGroups.size() > maxNumG) maxNumG = mGroups.size();
*/
for (int i = 0; i < (int)mGroups.size(); i++) {
ConvexGroup *g = mGroups[i];
if (!g->dirty)
continue;
if (g->numIndices == 0 || g->numVertices == 0)
continue;
if (!g->VBO) {
glGenBuffersARB(1, &g->VBO);
}
if (!g->IBO) {
glGenBuffersARB(1, &g->IBO);
}
if (!g->matTex) {
glGenTextures(1, &g->matTex);
glBindTexture(GL_TEXTURE_2D, g->matTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glBindTexture(GL_TEXTURE_2D, 0);
}
if (g->numVertices == 0 || g->numIndices == 0)
return;
// recalculate in case they have changed
g->numVertices = 0;
g->numIndices = 0;
for (int i = 0; i < (int)g->convexes.size(); i++) {
g->numVertices += g->convexes[i]->getVisVertices().size();
g->numIndices += g->convexes[i]->getVisTriIndices().size();
}
g->vertices.resize(g->numVertices*12);
g->indices.resize(g->numIndices);
float* vp = &g->vertices[0];
unsigned int* ip = &g->indices[0];
int sumV = 0;
// Make cpu copy of VBO and IBO
int convexNr = 0;
for (int j = 0; j < (int)g->convexes.size(); j++, convexNr++) {
const Convex* c = g->convexes[j];
// PxVec3 matOff = c->getMaterialOffset();
int nv = c->getVisVertices().size();
int ni = c->getVisTriIndices().size();
if (nv > 0) {
float* cvp = (float*)&c->getVisVertices()[0]; // float3
float* cnp = (float*)&c->getVisNormals()[0]; // float3
// float* c3dtp = (float*)&c->getVisVertices()[0]; // float3
float* c2dtp = (float*)&c->getVisTexCoords()[0]; // float2
float* ctanp = (float*)&c->getVisTangents()[0]; // float3
int* cip = (int*)&c->getVisTriIndices()[0];
for (int k = 0; k < nv; k++) {
*(vp++) = *(cvp++);
*(vp++) = *(cvp++);
*(vp++) = *(cvp++);
*(vp++) = *(cnp++);
*(vp++) = *(cnp++);
*(vp++) = *(cnp++);
*(vp++) = *(ctanp++);
*(vp++) = *(ctanp++);
*(vp++) = *(ctanp++);
*(vp++) = (float)convexNr;
*(vp++) = *(c2dtp++);
*(vp++) = *(c2dtp++);
}
for (int k = 0; k < ni; k++) {
*(ip++) = *(cip++) + sumV;
}
}
//memcpy(ip, cip, sizeof(int)*ni);
//ip += 3*ni;
//std::vector<PxVec3> mTriVertices;
//std::vector<PxVec3> mTriNormals;
//std::vector<int> mTriIndices;
//std::vector<float> mTriTexCoords; // 3d + obj nr
sumV += nv;
}
/*
if (g->vertices.size() > maxNumV) maxNumV = g->vertices.size();
if (g->indices.size() > maxNumI) maxNumI = g->indices.size();
if (g->convexes.size() > maxNumC) maxNumC = g->convexes.size();
*/
glBindBufferARB(GL_ARRAY_BUFFER_ARB, g->VBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, g->vertices.size()*sizeof(float), &g->vertices[0], GL_DYNAMIC_DRAW);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, g->IBO);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, g->indices.size()*sizeof(unsigned int), &g->indices[0], GL_DYNAMIC_DRAW);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
int oldTexSize = g->texSize;
if (g->texSize == 0) {
// First time
oldTexSize = 1;
g->texSize = 32;
}
while (1) {
int convexesPerRow = g->texSize / 4;
if (convexesPerRow * g->texSize >= (int)g->convexes.size()) {
break;
} else {
g->texSize *= 2;
}
}
if (g->texSize != oldTexSize) {
g->texCoords.resize(g->texSize*g->texSize*4);
// Let's allocate texture
glBindTexture(GL_TEXTURE_2D, g->matTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, g->texSize, g->texSize, 0, GL_RGBA, GL_FLOAT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
g->dirty = false;
}
// printf("maxV = %d, maxI = %d, maxC = %d, maxG = %d\n", maxNumV, maxNumI, maxNumC, maxNumG);
}
//--------------------------------------------------------
void ConvexRenderer::updateTransformations()
{
for (int i = 0; i < (int)mGroups.size(); i++) {
ConvexGroup *g = mGroups[i];
if (g->texCoords.empty())
continue;
float* tt = &g->texCoords[0];
for (int j = 0; j < (int)g->convexes.size(); j++) {
const Convex* c = g->convexes[j];
PxMat44 pose(c->getGlobalPose());
float* mp = (float*)pose.front();
float* ta = tt;
for (int k = 0; k < 16; k++) {
*(tt++) = *(mp++);
}
PxVec3 matOff = c->getMaterialOffset();
ta[3] = matOff.x;
ta[7] = matOff.y;
ta[11] = matOff.z;
int idFor2DTex = c->getSurfaceMaterialId();
int idFor3DTex = c->getMaterialId();
const int MAX_3D_TEX = 8;
ta[15] = (float)(idFor2DTex*MAX_3D_TEX + idFor3DTex);
}
glBindTexture(GL_TEXTURE_2D, g->matTex);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, g->texSize, g->texSize,
GL_RGBA, GL_FLOAT, &g->texCoords[0]);
glBindTexture(GL_TEXTURE_2D, 0);
}
}
//--------------------------------------------------------
void ConvexRenderer::render()
{
if (!mActive)
return;
updateRenderBuffers();
updateTransformations();
for (int i = 0; i < (int)mGroups.size(); i++) {
ConvexGroup *g = mGroups[i];
Shader* shader = mShader;
if (g->mShader != NULL)
shader = g->mShader;
shader->activate(mShaderMat);
// Assume convex all use the same shader
glActiveTexture(GL_TEXTURE7);
glBindTexture(GL_TEXTURE_3D, volTex);
glActiveTexture(GL_TEXTURE8);
glBindTexture(GL_TEXTURE_2D, g->matTex);
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mDiffuseTexArray);
glActiveTexture(GL_TEXTURE11);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mBumpTexArray);
glActiveTexture(GL_TEXTURE12);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mSpecularTexArray);
glActiveTexture(GL_TEXTURE13);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mEmissiveReflectSpecPowerTexArray);
glActiveTexture(GL_TEXTURE0);
float itt = 1.0f/g->texSize;
shader->setUniform("diffuseTexArray", 10);
shader->setUniform("bumpTexArray", 11);
shader->setUniform("specularTexArray", 12);
shader->setUniform("emissiveReflectSpecPowerTexArray", 13);
shader->setUniform("ttt3D", 7);
shader->setUniform("transTex", 8);
shader->setUniform("transTexSize", g->texSize);
shader->setUniform("iTransTexSize", itt);
shader->setUniform("bumpTextureUVScale", mBumpTextureUVScale);
shader->setUniform("extraNoiseScale", mExtraNoiseScale);
shader->setUniform("roughnessScale", mRoughnessScale);
if (mShaderMat.color[3] < 1.0f) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
glColor4f(mShaderMat.color[0], mShaderMat.color[1], mShaderMat.color[2], mShaderMat.color[3]);
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, g->VBO);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, g->IBO);
int stride = 12*sizeof(float);
glVertexPointer(3, GL_FLOAT, stride, 0);
glNormalPointer(GL_FLOAT, stride, (void*)(3*sizeof(float)));
glTexCoordPointer(4, GL_FLOAT, stride, (void*)(6*sizeof(float)));
glClientActiveTexture(GL_TEXTURE1);
glTexCoordPointer(2, GL_FLOAT, stride, (void*)(10*sizeof(float)));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawElements(GL_TRIANGLES, g->numIndices, GL_UNSIGNED_INT, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
if (mShaderMat.color[3] < 1.0f) {
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
shader->deactivate();
}
}

View File

@ -0,0 +1,104 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef CONVEX_RENDERER
#define CONVEX_RENDERER
#include "Convex.h"
#include <vector>
using namespace physx;
class Shader;
// ----------------------------------------------------------------------------
class ConvexRenderer
{
public:
ConvexRenderer();
~ConvexRenderer();
void init();
const static int maxVertsPerGroup = 100000;
void setActive(bool active) { mActive = active; };
void add(const base::Convex* convex, Shader* shader);
void remove(const base::Convex* convex);
void render();
void setShaderMaterial(Shader* shader, const ShaderMaterial& mat) {this->mShader = shader; this->mShaderMat = mat;}
void setTexArrays(unsigned int diffuse, unsigned int bump, unsigned int specular, unsigned int specPower) {
mDiffuseTexArray = diffuse; mBumpTexArray = bump;
mSpecularTexArray = specular; mEmissiveReflectSpecPowerTexArray = specPower; }
void setVolTex(unsigned int volTexi) { volTex = volTexi;}
private:
void updateRenderBuffers();
void updateTransformations();
Shader* mShader;
ShaderMaterial mShaderMat;
struct ConvexGroup {
void init() {
numVertices = 0; numIndices = 0;
VBO = 0; IBO = 0; matTex = 0;
texSize = 0;
}
bool dirty;
std::vector<const Convex*> convexes;
std::vector<float> vertices;
std::vector<unsigned int> indices;
std::vector<float> texCoords;
int numVertices, numIndices;
unsigned int VBO;
unsigned int IBO;
unsigned int matTex;
int texSize;
Shader* mShader;
};
std::vector<ConvexGroup*> mGroups;
bool mActive;
float mBumpTextureUVScale;
float mExtraNoiseScale;
float mRoughnessScale;
unsigned int mDiffuseTexArray;
unsigned int mBumpTexArray;
unsigned int mSpecularTexArray;
unsigned int mEmissiveReflectSpecPowerTexArray;
unsigned int volTex;
};
#endif

View File

@ -0,0 +1,166 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#include "ActorBase.h"
#include <foundation/PxMat44.h>
#include "PxRigidBodyExt.h"
#include "PxScene.h"
#include "SimSceneBase.h"
#include "CompoundBase.h"
namespace physx
{
namespace fracture
{
namespace base
{
Actor::Actor(SimScene* scene):
mScene(scene),
mMinConvexSize(scene->mMinConvexSize),
mDepthLimit(100),
mDestroyIfAtDepthLimit(false)
{
}
Actor::~Actor()
{
mScene->getScene()->lockWrite();
clear();
mScene->getScene()->unlockWrite();
mScene->removeActor(this);
}
void Actor::clear()
{
for (int i = 0; i < (int)mCompounds.size(); i++) {
PX_DELETE(mCompounds[i]);
}
mCompounds.clear();
}
void Actor::addCompound(Compound *c)
{
mCompounds.pushBack(c);
PxRigidDynamic *a = c->getPxActor();
#if 1
if (a) {
// a->setContactReportFlags(Px_NOTIFY_ON_TOUCH_FORCE_THRESHOLD | Px_NOTIFY_ON_START_TOUCH_FORCE_THRESHOLD);
a->setContactReportThreshold(mScene->mFractureForceThreshold);
}
#endif
c->mActor = this;
++(mScene->mSceneVersion);
}
void Actor::removeCompound(Compound *c)
{
int num = 0;
for (int i = 0; i < (int)mCompounds.size(); i++) {
if (mCompounds[i] != c) {
mCompounds[num] = mCompounds[i];
num++;
}
}
if (mScene->mPickActor == c->getPxActor())
mScene->mPickActor = NULL;
c->clear();
//delCompoundList.push_back(c);
//delete c;
mScene->delCompoundList.pushBack(c);
mCompounds.resize(num);
++mScene->mSceneVersion;
}
void Actor::preSim(float dt)
{
int num = 0;
for (int i = 0; i < (int)mCompounds.size(); i++) {
mCompounds[i]->step(dt);
if (mCompounds[i]->getLifeFrames() == 0) {
mCompounds[i]->clear();
//delCompoundList.push_back(mCompounds[i]);
//delete mCompounds[i];
mScene->delCompoundList.pushBack(mCompounds[i]);
}
else {
mCompounds[num] = mCompounds[i];
num++;
}
}
mCompounds.resize(num);
}
void Actor::postSim(float /*dt*/)
{
}
bool Actor::rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &compoundNr, int &convexNr, PxVec3 &normal) const
{
dist = PX_MAX_F32;
compoundNr = -1;
convexNr = -1;
for (int i = 0; i < (int)mCompounds.size(); i++) {
float d;
int cNr;
PxVec3 n;
if (mCompounds[i]->rayCast(orig, dir, d, cNr, n)) {
if (d < dist) {
dist = d;
compoundNr = i;
convexNr = cNr;
normal = n;
}
}
}
return compoundNr >= 0;
}
bool Actor::findCompound(const Compound* c, int& compoundNr)
{
for(int i = 0; i < (int)mCompounds.size(); i++)
{
if(mCompounds[i] == c)
{
compoundNr = i;
return true;
}
}
return false;
}
}
}
}
#endif

View File

@ -0,0 +1,81 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef ACTOR_BASE_H
#define ACTOR_BASE_H
#include <PsArray.h>
#include <PsUserAllocated.h>
namespace physx
{
namespace fracture
{
namespace base
{
class Compound;
class Actor : public ::physx::shdfnd::UserAllocated
{
friend class SimScene;
friend class Compound;
protected:
Actor(SimScene* scene);
public:
virtual ~Actor();
void clear();
void addCompound(Compound *m);
void removeCompound(Compound *m);
bool findCompound(const Compound* c, int& compoundNr);
void preSim(float dt);
void postSim(float dt);
bool rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &compoundNr, int &convexNr, PxVec3 &normal) const;
shdfnd::Array<Compound*> getCompounds() { return mCompounds; }
protected:
SimScene* mScene;
shdfnd::Array<Compound*> mCompounds;
PxF32 mMinConvexSize;
PxU32 mDepthLimit;
bool mDestroyIfAtDepthLimit;
};
}
}
}
#endif
#endif

View File

@ -0,0 +1,563 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#include "MeshBase.h"
#include "CompoundGeometryBase.h"
#include "CompoundCreatorBase.h"
#include "PxConvexMeshGeometry.h"
#include "PxRigidBodyExt.h"
#include "foundation/PxMat44.h"
#include "PxScene.h"
#include "PxShape.h"
#include "SimSceneBase.h"
#include "CompoundBase.h"
#include "ActorBase.h"
#include "ConvexBase.h"
#include "foundation/PxMathUtils.h"
#include <stdio.h>
#include "MathUtils.h"
namespace physx
{
namespace fracture
{
namespace base
{
//vector<PxVec3> tmpPoints;
void Compound::appendUniformSamplesOfConvexPolygon(PxVec3* vertices, int numV, float area, shdfnd::Array<PxVec3>& samples, shdfnd::Array<PxVec3>* normals) {
PxVec3& p0 = vertices[0];
PxVec3 normal;
if (numV < 3) {
normal = PxVec3(0.0f,1.0f,0.0f);
} else {
normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
normal.normalize();
}
for (int i = 1; i < numV-1; i++) {
PxVec3& p1 = vertices[i];
PxVec3& p2 = vertices[i+1];
float tarea = 0.5f*((p1-p0).cross(p2-p0)).magnitude();
float aa = tarea / area;
int np = (int)floor(aa);
if (randRange(0.0f,1.0f) <= aa-np) np++;
for (int j = 0; j < np; j++) {
float r1 = randRange(0.0f,1.0f);
float sr1 = physx::PxSqrt(r1);
float r2 = randRange(0.0f, 1.0f);
PxVec3 p = (1 - sr1) * p0 + (sr1 * (1 - r2)) * p1 + (sr1 * r2) * p2;
samples.pushBack(p);
if (normals) normals->pushBack(normal);
}
}
}
// --------------------------------------------------------------------------------------------
Compound::Compound(SimScene *scene, PxReal contactOffset, PxReal restOffset)
{
mScene = scene;
mActor = NULL;
mPxActor = NULL;
mContactOffset = contactOffset;
mRestOffset = restOffset;
mLifeFrames = -1; // live forever
mDepth = 0;
clear();
}
// --------------------------------------------------------------------------------------------
Compound::~Compound()
{
clear();
}
// --------------------------------------------------------------------------------------------
#define SHAPE_BUFFER_SIZE 100
void Compound::clear()
{
if (mPxActor != NULL) {
// Unmap all shapes for this actor
const physx::PxU32 shapeCount = mPxActor->getNbShapes();
physx::PxShape* shapeBuffer[SHAPE_BUFFER_SIZE];
for (physx::PxU32 shapeStartIndex = 0; shapeStartIndex < shapeCount; shapeStartIndex += SHAPE_BUFFER_SIZE)
{
physx::PxU32 shapesRead = mPxActor->getShapes(shapeBuffer, SHAPE_BUFFER_SIZE, shapeStartIndex);
for (physx::PxU32 shapeBufferIndex = 0; shapeBufferIndex < shapesRead; ++shapeBufferIndex)
{
mScene->unmapShape(*shapeBuffer[shapeBufferIndex]);
}
}
// release the actor
mPxActor->release();
mPxActor = NULL;
}
for (int i = 0; i < (int)mConvexes.size(); i++) {
if (mConvexes[i]->decreaseRefCounter() <= 0) {
convexRemoved(mConvexes[i]); //mScene->getConvexRenderer().remove(mConvexes[i]);
PX_DELETE(mConvexes[i]);
}
}
mConvexes.clear();
mEdges.clear();
//mShader = NULL;
//mShaderMat.init();
mKinematicVel = PxVec3(0.0f, 0.0f, 0.0f);
mAttachmentBounds.clear();
mAdditionalImpactNormalImpulse = 0.0f;
mAdditionalImpactRadialImpulse = 0.0f;
}
// --------------------------------------------------------------------------------------------
void Compound::setKinematic(const PxVec3 &vel)
{
if (mPxActor == NULL)
return;
mPxActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
mKinematicVel = vel;
}
// --------------------------------------------------------------------------------------------
void Compound::step(float dt)
{
//if (mPxActor == NULL)
// return;
if (!mKinematicVel.isZero()) {
PxTransform pose = mPxActor->getGlobalPose();
pose.p += mKinematicVel * dt;
mPxActor->setKinematicTarget(pose);
}
if (mLifeFrames > 0)
mLifeFrames--;
}
// --------------------------------------------------------------------------------------------
bool Compound::createFromConvex(Convex* convex, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, bool copyConvexes, int matID, int surfMatID)
{
return createFromConvexes(&convex, 1, pose, vel, omega, copyConvexes, matID, surfMatID);
}
// --------------------------------------------------------------------------------------------
bool Compound::createFromConvexes(Convex** convexes, int numConvexes, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, bool copyConvexes, int matID, int surfMatID)
{
if (numConvexes == 0)
return false;
clear();
PxVec3 center(0.0f, 0.0f, 0.0f);
for (int i = 0; i < numConvexes; i++)
center += convexes[i]->getCenter();
center /= (float)numConvexes;
shdfnd::Array<PxShape*> shapes;
for (int i = 0; i < numConvexes; i++) {
Convex *c;
if (copyConvexes) {
c = mScene->createConvex();
c->createFromConvex(convexes[i], 0, matID, surfMatID);
}
else
c = convexes[i];
c->increaseRefCounter();
mConvexes.pushBack(c);
PxVec3 off = c->centerAtZero();
c->setMaterialOffset(c->getMaterialOffset() + off);
c->setLocalPose(PxTransform(off - center));
if (convexes[i]->isGhostConvex())
continue;
bool reused = c->getPxConvexMesh() != NULL;
mScene->profileBegin("cook convex meshes"); //Profiler::getInstance()->begin("cook convex meshes");
PxConvexMesh* mesh = c->createPxConvexMesh(this, mScene->getPxPhysics(), mScene->getPxCooking());
mScene->profileEnd("cook convex meshes"); //Profiler::getInstance()->end("cook convex meshes");
if (mesh == NULL) {
if (c->decreaseRefCounter() <= 0)
PX_DELETE(c);
mConvexes.popBack();
continue;
}
if (!c->hasExplicitVisMesh())
c->createVisMeshFromConvex();
if (!reused)
convexAdded(c); //mScene->getConvexRenderer().add(c);
PxShape *shape = mScene->getPxPhysics()->createShape(
PxConvexMeshGeometry(mesh),
*mScene->getPxDefaultMaterial(),
true
);
shape->setLocalPose(c->getLocalPose());
//shape->setContactOffset(mContactOffset);
//shape->setRestOffset(mRestOffset);
if (mContactOffset < mRestOffset || mContactOffset < 0.0f)
{
printf("WRONG\n");
}
mScene->mapShapeToConvex(*shape, *c);
shapes.pushBack(shape);
}
if (shapes.empty())
{
return false;
}
createPxActor(shapes, pose, vel, omega);
return true;
}
// --------------------------------------------------------------------------------------------
bool Compound::createFromGeometry(const CompoundGeometry &geom, PxRigidDynamic* body, Shader* myShader, int matID, int surfMatID)
{
clear();
shdfnd::Array<PxShape*> shapes(body->getNbShapes());
body->getShapes(shapes.begin(), body->getNbShapes());
PX_ASSERT(geom.convexes.size() == body->getNbShapes());
for (int i = 0; i < (int)geom.convexes.size(); i++) {
Convex *c = mScene->createConvex();
c->createFromGeometry(geom, i, 0, matID, surfMatID);
c->increaseRefCounter();
mConvexes.pushBack(c);
PxVec3 off = c->centerAtZero();
c->setMaterialOffset(c->getMaterialOffset() + off);
c->createVisMeshFromConvex();
c->setLocalPose(PxTransform(off));
bool reused = c->getPxConvexMesh() != NULL;
if (!reused)
convexAdded(c, myShader); //mScene->getConvexRenderer().add(c);
mScene->mapShapeToConvex(*shapes[i], *c);
}
if (shapes.empty())
return false;
mPxActor = body;
for (int i = 0; i < (int)mConvexes.size(); i++)
mConvexes[i]->setPxActor(mPxActor);
//createPxActor(shapes, pose, vel, omega);
return true;
}
bool Compound::createFromGeometry(const CompoundGeometry &geom, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, Shader* myShader, int matID, int surfMatID)
{
clear();
shdfnd::Array<PxShape*> shapes;
for (int i = 0; i < (int)geom.convexes.size(); i++) {
Convex *c = mScene->createConvex();
c->createFromGeometry(geom, i, 0, matID, surfMatID);
c->increaseRefCounter();
mConvexes.pushBack(c);
PxVec3 off = c->centerAtZero();
c->setMaterialOffset(c->getMaterialOffset() + off);
c->createVisMeshFromConvex();
c->setLocalPose(PxTransform(off));
bool reused = c->getPxConvexMesh() != NULL;
PxConvexMesh* mesh = c->createPxConvexMesh(this, mScene->getPxPhysics(), mScene->getPxCooking());
if (mesh == NULL) {
if (c->decreaseRefCounter() <= 0)
PX_DELETE(c);
mConvexes.popBack();
continue;
}
if (!reused)
convexAdded(c, myShader); //mScene->getConvexRenderer().add(c);
PxShape *shape;
if (geom.convexes[i].isSphere)
{
shape = mScene->getPxPhysics()->createShape(
PxSphereGeometry(geom.convexes[i].radius),
*mScene->getPxDefaultMaterial(),
true
);
}
else
{
shape = mScene->getPxPhysics()->createShape(
PxConvexMeshGeometry(mesh),
*mScene->getPxDefaultMaterial(),
true
);
}
shape->setLocalPose(c->getLocalPose());
//shape->setContactOffset(mContactOffset);
//shape->setRestOffset(mRestOffset);
mScene->mapShapeToConvex(*shape, *c);
shapes.pushBack(shape);
}
if (shapes.empty())
return false;
createPxActor(shapes, pose, vel, omega);
return true;
}
// --------------------------------------------------------------------------------------------
void Compound::createFromMesh(const Mesh *mesh, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, int submeshNr, const PxVec3& scale, int matID, int surfMatID)
{
const shdfnd::Array<PxVec3> &verts = mesh->getVertices();
const shdfnd::Array<PxVec3> &normals = mesh->getNormals();
const shdfnd::Array<PxVec2> &texcoords = mesh->getTexCoords();
const shdfnd::Array<PxU32> &indices = mesh->getIndices();
if (verts.empty() || indices.empty())
return;
if (submeshNr >= 0 && submeshNr >= (int)mesh->getSubMeshes().size())
return;
PxBounds3 bounds;
mesh->getBounds(bounds, submeshNr);
PxMat33 scaleMat(PxMat33::createDiagonal(scale));
bounds = PxBounds3::transformSafe(scaleMat, bounds);
PxVec3 dims = bounds.getDimensions() * 1.01f;
PxVec3 center = bounds.getCenter();
mScene->getCompoundCreator()->createBox(dims);
createFromGeometry(mScene->getCompoundCreator()->getGeometry(), pose, vel, omega, NULL, matID, surfMatID);
PxTransform trans(-center);
if (submeshNr < 0)
mConvexes[0]->setExplicitVisMeshFromTriangles(verts.size(), &verts[0], &normals[0], &texcoords[0], indices.size(), &indices[0], &trans, &scale);
else {
const Mesh::SubMesh &sm = mesh->getSubMeshes()[submeshNr];
mConvexes[0]->setExplicitVisMeshFromTriangles(verts.size(), &verts[0], &normals[0], &texcoords[0], sm.numIndices, &indices[sm.firstIndex], &trans, &scale);
}
}
// --------------------------------------------------------------------------------------------
bool Compound::createPxActor(shdfnd::Array<PxShape*> &shapes, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega)
{
if (shapes.empty())
return false;
for(int i = 0; i < (int)shapes.size(); i++)
{
applyShapeTemplate(shapes[i]);
}
PxRigidDynamic* body = mScene->getPxPhysics()->createRigidDynamic(pose);
if (body == NULL)
return false;
//body->setSleepThreshold(getSleepingThresholdRB());
#if 0
body->setWakeCounter(100000000000.f);
#endif
mScene->getScene()->addActor(*body);
for (int i = 0; i < (int)shapes.size(); i++)
body->attachShape(*shapes[i]);
//KS - we clamp the mass in the range [minMass, maxMass]. This helps to improve stability
PxRigidBodyExt::updateMassAndInertia(*body, 1.0f);
/*const PxReal maxMass = 50.f;
const PxReal minMass = 1.f;
PxReal mass = PxMax(PxMin(maxMass, body->getMass()), minMass);
PxRigidBodyExt::setMassAndUpdateInertia(*body, mass);*/
body->setLinearVelocity(vel);
body->setAngularVelocity(omega);
/*if (vel.isZero() && omega.isZero())
{
body->putToSleep();
}*/
mPxActor = body;
for (int i = 0; i < (int)mConvexes.size(); i++)
mConvexes[i]->setPxActor(mPxActor);
return true;
}
// --------------------------------------------------------------------------------------------
bool Compound::rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &convexNr, PxVec3 &normal)
{
dist = PX_MAX_F32;
convexNr = -1;
for (int i = 0; i < (int)mConvexes.size(); i++) {
float d;
PxVec3 n;
if (mConvexes[i]->rayCast(orig, dir, d, n)) {
if (d < dist) {
dist = d;
convexNr = i;
normal = n;
}
}
}
return convexNr >= 0;
}
// --------------------------------------------------------------------------------------------
void Compound::getRestBounds(PxBounds3 &bounds) const
{
bounds.setEmpty();
PxBounds3 bi;
for (int i = 0; i < (int)mConvexes.size(); i++) {
Convex *c = mConvexes[i];
PxBounds3 bi = c->getBounds();
bi = PxBounds3::transformSafe(c->getLocalPose(), bi);
bounds.include(bi);
}
}
// --------------------------------------------------------------------------------------------
void Compound::getWorldBounds(PxBounds3 &bounds) const
{
bounds.setEmpty();
PxBounds3 bi;
for (int i = 0; i < (int)mConvexes.size(); i++) {
mConvexes[i]->getWorldBounds(bi);
bounds.include(bi);
}
}
// --------------------------------------------------------------------------------------------
void Compound::getLocalBounds(PxBounds3 &bounds) const
{
bounds.setEmpty();
PxBounds3 bi;
for (int i = 0; i < (int)mConvexes.size(); i++) {
mConvexes[i]->getLocalBounds(bi);
bounds.include(bi);
}
}
// --------------------------------------------------------------------------------------------
bool Compound::isAttached()
{
if (mAttachmentBounds.empty())
return false;
PxBounds3 b;
for (int i = 0; i < (int)mConvexes.size(); i++) {
Convex *c = mConvexes[i];
b = c->getBounds();
b.minimum += c->getMaterialOffset();
b.maximum += c->getMaterialOffset();
for (int j = 0; j < (int)mAttachmentBounds.size(); j++) {
if (b.intersects(mAttachmentBounds[j]))
return true;
}
}
return false;
}
// --------------------------------------------------------------------------------------------
void Compound::attach(const shdfnd::Array<PxBounds3> &bounds)
{
mAttachmentBounds.resize(bounds.size());
PxTransform t = getPxActor()->getGlobalPose().getInverse();
for (int i = 0; i < (int)bounds.size(); i++) {
PxVec3 a = t.transform(bounds[i].minimum);
PxVec3 b = t.transform(bounds[i].maximum);
mAttachmentBounds[i].minimum = PxVec3(PxMin(a.x,b.x),PxMin(a.y,b.y),PxMin(a.z,b.z));
mAttachmentBounds[i].maximum = PxVec3(PxMax(a.x,b.x),PxMax(a.y,b.y),PxMax(a.z,b.z));
}
if (isAttached())
mPxActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
}
// --------------------------------------------------------------------------------------------
void Compound::attachLocal(const shdfnd::Array<PxBounds3> &bounds)
{
mAttachmentBounds.resize(bounds.size());
for (int i = 0; i < (int)bounds.size(); i++) {
mAttachmentBounds[i] = bounds[i];
}
if (isAttached())
mPxActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
}
}
}
}
#endif

View File

@ -0,0 +1,162 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef COMPOUNDBASE
#define COMPOUNDBASE
#define TECHNICAL_MODE 1
#include <foundation/PxVec3.h>
#include <foundation/PxPlane.h>
#include <foundation/PxBounds3.h>
#include <foundation/PxTransform.h>
#include <PsArray.h>
#include <PxRigidDynamic.h>
#include <PsUserAllocated.h>
class Shader;
namespace physx
{
namespace fracture
{
namespace base
{
class Convex;
class Mesh;
class SimScene;
class CompoundGeometry;
// -----------------------------------------------------------------------------------
class Compound : public ::physx::shdfnd::UserAllocated
{
friend class SimScene;
friend class Actor;
protected:
Compound(SimScene* scene, PxReal contactOffset = 0.005f, PxReal restOffset = -0.001f);
public:
virtual ~Compound();
virtual bool createFromConvexes(Convex** convexes, int numConvexes, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, bool copyConvexes = true, int matID = 0, int surfMatID = 0);
bool createFromConvex(Convex* convex, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, bool copyConvexes = true, int matID = 0, int surfMatID = 0);
bool createFromGeometry(const CompoundGeometry &geom, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, Shader* myShader, int matID = 0, int surfMatID = 0);
bool createFromGeometry(const CompoundGeometry &geom, PxRigidDynamic* body, Shader* myShader, int matID = 0, int surfMatID = 0);
void createFromMesh(const Mesh *mesh, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, int submeshNr = -1, const PxVec3& scale = PxVec3(1.f), int matID = 0, int surfMatID = 0);
virtual void applyShapeTemplate(PxShape* /*shape*/) {}
bool rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &convexNr, PxVec3 &normal);
void setLifeFrames(int frames) { mLifeFrames = frames == 0 ? 1 : frames; }
int getLifeFrames() { return mLifeFrames; }
virtual void convexAdded(Convex* /*c*/, Shader* shader = NULL) {}
virtual void convexRemoved(Convex* /*c*/) {}
void attach(const shdfnd::Array<PxBounds3> &bounds);
void attachLocal(const shdfnd::Array<PxBounds3> &bounds);
const shdfnd::Array<Convex*>& getConvexes() const { return mConvexes; }
const shdfnd::Array<PxBounds3>& getAttachmentBounds() const { return mAttachmentBounds; }
PxRigidDynamic* getPxActor() { return mPxActor; }
void getWorldBounds(PxBounds3 &bounds) const;
void getLocalBounds(PxBounds3 &bounds) const;
void getRestBounds(PxBounds3 &bounds) const;
//void setShader(Shader* shader, const ShaderMaterial &mat) { mShader = shader; mShaderMat = mat; }
//Shader* getShader() const { return mShader; }
//const ShaderMaterial& getShaderMat() { return mShaderMat; }
void setKinematic(const PxVec3 &vel);
void step(float dt);
virtual void draw(bool /*useShader*/, bool /*debug*/ = false) {}
virtual void clear();
void setAdditionalImpactImpulse(float radial, float normal) {
mAdditionalImpactRadialImpulse = radial; mAdditionalImpactNormalImpulse = normal;
}
float getAdditionalImpactRadialImpulse() const { return mAdditionalImpactRadialImpulse; }
float getAdditionalImpactNormalImpulse() const { return mAdditionalImpactNormalImpulse; }
virtual void copyShaders(Compound*) {}
protected:
bool isAttached();
bool createPxActor(shdfnd::Array<PxShape*> &shapes, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega);
static void appendUniformSamplesOfConvexPolygon(PxVec3* vertices, int numV, float area, shdfnd::Array<PxVec3>& samples, shdfnd::Array<PxVec3>* normals = NULL);
virtual float getSleepingThresholdRB() {return 0.1f;}
struct Edge {
void init(int c0, int c1) {
this->c0 = c0; this->c1 = c1;
restLen = 0.0f;
deleted = false;
}
int c0, c1;
float restLen;
bool deleted;
};
shdfnd::Array<Convex*> mConvexes;
shdfnd::Array<Edge> mEdges;
SimScene *mScene;
Actor *mActor;
PxRigidDynamic *mPxActor;
PxVec3 mKinematicVel;
shdfnd::Array<PxBounds3> mAttachmentBounds;
//Shader *mShader;
//ShaderMaterial mShaderMat;
PxReal mContactOffset;
PxReal mRestOffset;
int mLifeFrames;
float mAdditionalImpactNormalImpulse;
float mAdditionalImpactRadialImpulse;
PxU32 mDepth; // fracture depth
PxVec3 mNormal; // normal use with mSheetFracture
};
}}}
#endif
#endif

View File

@ -0,0 +1,871 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#include "CompoundCreatorBase.h"
#include <algorithm>
#include <foundation/PxAssert.h>
#include "PhysXMacros.h"
#include "PxConvexMeshGeometry.h"
#include "PxConvexMesh.h"
namespace physx
{
namespace fracture
{
namespace base
{
int CompoundCreator::tetFaceIds[4][3] = {{0,1,3},{1,2,3},{2,0,3},{0,2,1}};
int CompoundCreator::tetEdgeVerts[6][2] = {{0,1},{1,2},{2,0},{0,3},{1,3},{2,3}};
int CompoundCreator::tetFaceEdges[4][3] = {{0,4,3},{1,5,4},{2,3,5},{0,2,1}};
#define CONVEX_THRESHOLD (PxPi + 0.05f)
// -----------------------------------------------------------------------------
void CompoundCreator::createTorus(float r0, float r1, int numSegs0, int numSegs1, const PxTransform *trans)
{
mGeom.clear();
CompoundGeometry::Convex c;
PxVec3 nr0,nr1,nz;
nz = PxVec3(0.0f, 0.0f, 1.0f);
PxVec3 p,n;
PxTransform t = PX_TRANSFORM_ID;
if (trans)
t = *trans;
shdfnd::Array<PxVec3> normals;
float dphi0 = PxTwoPi / (float)numSegs0;
float dphi1 = PxTwoPi / (float)numSegs1;
for (int i = 0; i < numSegs0; i++) {
nr0 = PxVec3(PxCos(i*dphi0), PxSin(i*dphi0), 0.0f);
nr1 = PxVec3(PxCos((i+1)*dphi0), PxSin((i+1)*dphi0), 0.0f);
mGeom.initConvex(c);
c.numVerts = 2*numSegs1;
normals.clear();
for (int j = 0; j < numSegs1; j++) {
p = nr0 * (r0 + r1 * PxCos(j*dphi1)) + nz * r1 * PxSin(j*dphi1);
mGeom.vertices.pushBack(t.transform(p));
n = nr0 * (PxCos(j*dphi1)) + nz * PxSin(j*dphi1);
normals.pushBack(t.rotate(n));
p = nr1 * (r0 + r1 * PxCos(j*dphi1)) + nz * r1 * PxSin(j*dphi1);
mGeom.vertices.pushBack(t.transform(p));
n = nr1 * (PxCos(j*dphi1)) + nz * PxSin(j*dphi1);
normals.pushBack(t.rotate(n));
}
c.numFaces = 2 + numSegs1;
mGeom.indices.pushBack(numSegs1); // face size
mGeom.indices.pushBack(CompoundGeometry::FF_INVISIBLE); // face flags
for (int j = 0; j < numSegs1; j++)
mGeom.indices.pushBack(2*j);
mGeom.indices.pushBack(numSegs1); // face size
mGeom.indices.pushBack(CompoundGeometry::FF_INVISIBLE); // face flags
for (int j = 0; j < numSegs1; j++) {
mGeom.indices.pushBack(2*(numSegs1-1-j) + 1);
}
for (int j = 0; j < numSegs1; j++) {
int k = (j+1)%numSegs1;
mGeom.indices.pushBack(4); // face size
mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE | CompoundGeometry::FF_HAS_NORMALS);
int i0 = 2*j;
int i1 = 2*j+1;
int i2 = 2*k+1;
int i3 = 2*k;
mGeom.indices.pushBack(i0);
mGeom.indices.pushBack(i1);
mGeom.indices.pushBack(i2);
mGeom.indices.pushBack(i3);
mGeom.normals.pushBack(normals[i0]);
mGeom.normals.pushBack(normals[i1]);
mGeom.normals.pushBack(normals[i2]);
mGeom.normals.pushBack(normals[i3]);
}
c.numNeighbors = 2;
mGeom.neighbors.pushBack((i + (numSegs0-1)) % numSegs0);
mGeom.neighbors.pushBack((i + 1) % numSegs0);
mGeom.convexes.pushBack(c);
}
}
// -----------------------------------------------------------------------------
void CompoundCreator::createCylinder(float r, float h, int numSegs, const PxTransform *trans)
{
PxTransform t = PX_TRANSFORM_ID;
if (trans)
t = *trans;
mGeom.clear();
CompoundGeometry::Convex c;
mGeom.initConvex(c);
float dphi = PxTwoPi / (float)numSegs;
c.numVerts = 2*numSegs;
mGeom.vertices.resize(c.numVerts);
for (int i = 0; i < numSegs; i++) {
PxVec3 p0(r * PxCos(i*dphi), r * PxSin(i*dphi), -0.5f * h);
PxVec3 p1(r * PxCos(i*dphi), r * PxSin(i*dphi), 0.5f * h);
mGeom.vertices[2*i] = t.transform(p0);
mGeom.vertices[2*i+1] = t.transform(p1);
}
c.numFaces = 2 + numSegs;
mGeom.indices.pushBack(numSegs);
mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE);
for (int i = 0; i < numSegs; i++)
mGeom.indices.pushBack(2*(numSegs-1-i));
mGeom.indices.pushBack(numSegs);
mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE);
for (int i = 0; i < numSegs; i++)
mGeom.indices.pushBack(2*i+1);
for (int i = 0; i < numSegs; i++) {
int j = (i+1) % numSegs;
PxVec3 n0(PxCos(i*dphi),PxSin(i*dphi),0.0f);
PxVec3 n1(PxCos(j*dphi),PxSin(j*dphi),0.0f);
n0 = t.rotate(n0);
n1 = t.rotate(n1);
//n0*=-1;
//n1*=-1;
mGeom.indices.pushBack(4);
mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE | CompoundGeometry::FF_HAS_NORMALS);
mGeom.indices.pushBack(2*i);
mGeom.indices.pushBack(2*j);
mGeom.indices.pushBack(2*j+1);
mGeom.indices.pushBack(2*i+1);
mGeom.normals.pushBack(n0);
mGeom.normals.pushBack(n1);
mGeom.normals.pushBack(n1);
mGeom.normals.pushBack(n0);
}
mGeom.convexes.pushBack(c);
}
// -----------------------------------------------------------------------------
void CompoundCreator::createBox(const PxVec3 &dims, const PxTransform *trans, bool clear)
{
PxTransform t = PX_TRANSFORM_ID;
if (trans)
t = *trans;
if (clear)
mGeom.clear();
CompoundGeometry::Convex c;
mGeom.initConvex(c);
c.numVerts = 8;
mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, -0.5f * dims.y, -0.5f * dims.z)));
mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, -0.5f * dims.y, -0.5f * dims.z)));
mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, 0.5f * dims.y, -0.5f * dims.z)));
mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, 0.5f * dims.y, -0.5f * dims.z)));
mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, -0.5f * dims.y, 0.5f * dims.z)));
mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, -0.5f * dims.y, 0.5f * dims.z)));
mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, 0.5f * dims.y, 0.5f * dims.z)));
mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, 0.5f * dims.y, 0.5f * dims.z)));
static int faceIds[6][4] = {{0,1,5,4},{1,2,6,5},{2,3,7,6},{3,0,4,7},{0,3,2,1},{4,5,6,7}};
c.numFaces = 6;
for (int i = 0; i < 6; i++) {
mGeom.indices.pushBack(4);
mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE);
for (int j = 0; j < 4; j++)
mGeom.indices.pushBack(faceIds[i][j]);
}
mGeom.convexes.pushBack(c);
}
void CompoundCreator::createFromConvexMesh(const PxConvexMeshGeometry& convexGeom, PxTransform offset, bool clear)
{
if (clear)
{
mGeom.clear();
}
CompoundGeometry::Convex c;
mGeom.initConvex(c);
PxConvexMesh* convexMesh = convexGeom.convexMesh;
c.numVerts = convexMesh->getNbVertices();
c.numFaces = convexMesh->getNbPolygons();
const PxVec3* verts = convexMesh->getVertices();
const PxU8* indexBuff = convexMesh->getIndexBuffer();
for (PxU32 a = 0; a < c.numVerts; ++a)
{
mGeom.vertices.pushBack(offset.transform(verts[a]));
}
for (PxU32 a = 0; a < c.numFaces; ++a)
{
PxHullPolygon data;
convexMesh->getPolygonData(a, data);
mGeom.indices.pushBack(data.mNbVerts);
mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE);
const PxU32 indexBase = data.mIndexBase;
for (PxU32 b = 0; b < data.mNbVerts; ++b)
{
PxU32 ind = indexBuff[indexBase + b];
mGeom.indices.pushBack(ind);
}
}
mGeom.convexes.pushBack(c);
}
// -----------------------------------------------------------------------------
void CompoundCreator::createSphere(const PxVec3 &dims, int resolution, const PxTransform *trans)
{
PxTransform t = PX_TRANSFORM_ID;
if (trans)
t = *trans;
if (resolution < 2) resolution = 2;
int numSegs0 = 2*resolution;
int numSegs1 = resolution;
float rx = 0.5f * dims.x;
float ry = 0.5f * dims.y;
float rz = 0.5f * dims.z;
mGeom.clear();
CompoundGeometry::Convex c;
mGeom.initConvex(c);
if (rx == ry && rx == rz)
{
c.isSphere = true;
c.radius = rx;
}
float dphi = PxTwoPi / (float)numSegs0;
float dteta = PxPi / (float)numSegs1;
PxVec3 p, n;
for (int i = 1; i < numSegs1; i++) {
for (int j = 0; j < numSegs0; j++) {
float phi = j * dphi;
float teta = -PxHalfPi + i * dteta;
p = PxVec3(PxCos(phi)*PxCos(teta), PxSin(phi)*PxCos(teta), PxSin(teta));
mGeom.vertices.pushBack(PxVec3(p.x * rx, p.y * ry, p.z * rz));
}
}
int bottomNr = mGeom.vertices.size();
mGeom.vertices.pushBack(PxVec3(0.0f, 0.0f, -rz));
int topNr = mGeom.vertices.size();
mGeom.vertices.pushBack(PxVec3(0.0f, 0.0f, +rz));
c.numVerts = mGeom.vertices.size();
for (int i = 0; i < numSegs1-2; i++) {
for (int j = 0; j < numSegs0; j++) {
mGeom.indices.pushBack(4); // face size
mGeom.indices.pushBack(CompoundGeometry::FF_HAS_NORMALS | CompoundGeometry::FF_OBJECT_SURFACE);
int i0 = i*numSegs0 + j;
int i1 = i*numSegs0 + (j+1)%numSegs0;
int i2 = (i+1)*numSegs0 + (j+1)%numSegs0;
int i3 = (i+1)*numSegs0 + j;
mGeom.indices.pushBack(i0);
mGeom.indices.pushBack(i1);
mGeom.indices.pushBack(i2);
mGeom.indices.pushBack(i3);
n = mGeom.vertices[i0]; n.normalize(); mGeom.normals.pushBack(n);
n = mGeom.vertices[i1]; n.normalize(); mGeom.normals.pushBack(n);
n = mGeom.vertices[i2]; n.normalize(); mGeom.normals.pushBack(n);
n = mGeom.vertices[i3]; n.normalize(); mGeom.normals.pushBack(n);
c.numFaces++;
}
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < numSegs0; j++) {
mGeom.indices.pushBack(3); // face size
mGeom.indices.pushBack(CompoundGeometry::FF_HAS_NORMALS | CompoundGeometry::FF_OBJECT_SURFACE);
int i0,i1,i2;
if (i == 0) {
i0 = j;
i1 = bottomNr;
i2 = (j+1)%numSegs0;
}
else {
i0 = (numSegs1-2)*numSegs0 + j;
i1 = (numSegs1-2)*numSegs0 + (j+1)%numSegs0;
i2 = topNr;
}
mGeom.indices.pushBack(i0);
mGeom.indices.pushBack(i1);
mGeom.indices.pushBack(i2);
n = mGeom.vertices[i0]; n.normalize(); mGeom.normals.pushBack(n);
n = mGeom.vertices[i1]; n.normalize(); mGeom.normals.pushBack(n);
n = mGeom.vertices[i2]; n.normalize(); mGeom.normals.pushBack(n);
c.numFaces++;
}
}
mGeom.convexes.pushBack(c);
}
// -----------------------------------------------------------------------------
void CompoundCreator::fromTetraMesh(const shdfnd::Array<PxVec3> &tetVerts, const shdfnd::Array<int> &tetIndices)
{
mTetVertices = tetVerts;
mTetIndices = tetIndices;
deleteColors();
computeTetNeighbors();
computeTetEdges();
colorTets();
colorsToConvexes();
}
// -----------------------------------------------------------------------------
void CompoundCreator::computeTetNeighbors()
{
int numTets = mTetIndices.size() / 4;
struct TetFace {
void init(int i0, int i1, int i2, int faceNr, int tetNr) {
if (i0 > i1) { int i = i0; i0 = i1; i1 = i; }
if (i1 > i2) { int i = i1; i1 = i2; i2 = i; }
if (i0 > i1) { int i = i0; i0 = i1; i1 = i; }
this->i0 = i0; this->i1 = i1; this->i2 = i2;
this->faceNr = faceNr; this->tetNr = tetNr;
}
bool operator < (const TetFace &f) const {
if (i0 < f.i0) return true;
if (i0 > f.i0) return false;
if (i1 < f.i1) return true;
if (i1 > f.i1) return false;
return i2 < f.i2;
}
bool operator == (const TetFace &f) const {
return i0 == f.i0 && i1 == f.i1 && i2 == f.i2;
}
int i0,i1,i2;
int faceNr, tetNr;
};
shdfnd::Array<TetFace> faces(numTets * 4);
for (int i = 0; i < numTets; i++) {
int ids[4];
ids[0] = mTetIndices[4*i];
ids[1] = mTetIndices[4*i+1];
ids[2] = mTetIndices[4*i+2];
ids[3] = mTetIndices[4*i+3];
for (int j = 0; j < 4; j++) {
int i0 = ids[tetFaceIds[j][0]];
int i1 = ids[tetFaceIds[j][1]];
int i2 = ids[tetFaceIds[j][2]];
faces[4*i+j].init(i0,i1,i2, j, i);
}
}
std::sort(faces.begin(), faces.end());
mTetNeighbors.clear();
mTetNeighbors.resize(numTets * 4, -1);
int i = 0;
while (i < (int)faces.size()) {
TetFace &f0 = faces[i];
i++;
if (i < (int)faces.size() && faces[i] == f0) {
TetFace &f1 = faces[i];
mTetNeighbors[4*f0.tetNr + f0.faceNr] = f1.tetNr;
mTetNeighbors[4*f1.tetNr + f1.faceNr] = f0.tetNr;
while (i < (int)faces.size() && faces[i] == f0)
i++;
}
}
}
// -----------------------------------------------------------------------------
void CompoundCreator::computeTetEdges()
{
int numTets = mTetIndices.size() / 4;
struct SortEdge {
void init(int i0, int i1, int edgeNr, int tetNr) {
if (i0 < i1) { this->i0 = i0; this->i1 = i1; }
else { this->i0 = i1; this->i1 = i0; }
this->edgeNr = edgeNr; this->tetNr = tetNr;
}
bool operator < (const SortEdge &e) const {
if (i0 < e.i0) return true;
if (i0 > e.i0) return false;
return i1 < e.i1;
}
bool operator == (const SortEdge &e) const {
return i0 == e.i0 && i1 == e.i1;
}
int i0,i1;
int edgeNr, tetNr;
};
shdfnd::Array<SortEdge> edges(numTets * 6);
for (int i = 0; i < numTets; i++) {
int ids[4];
ids[0] = mTetIndices[4*i];
ids[1] = mTetIndices[4*i+1];
ids[2] = mTetIndices[4*i+2];
ids[3] = mTetIndices[4*i+3];
for (int j = 0; j < 6; j++) {
int i0 = ids[tetEdgeVerts[j][0]];
int i1 = ids[tetEdgeVerts[j][1]];
edges[6*i + j].init(i0,i1, j, i);
}
}
std::sort(edges.begin(), edges.end());
mTetEdgeNrs.clear();
mTetEdgeNrs.resize(numTets * 6, -1);
mTetEdges.clear();
mEdgeTetNrs.clear();
mEdgeTetAngles.clear();
TetEdge te;
struct ChainVert {
int adjVert0;
int adjVert1;
int tet0;
int tet1;
float dihed0;
float dihed1;
int mark;
};
ChainVert cv;
cv.mark = 0;
shdfnd::Array<ChainVert> chainVerts(mTetVertices.size(), cv);
shdfnd::Array<int> chainVertNrs;
int mark = 1;
int i = 0;
while (i < (int)edges.size()) {
SortEdge &e0 = edges[i];
int edgeNr = mTetEdges.size();
te.init(e0.i0, e0.i1);
te.firstTet = mEdgeTetNrs.size();
te.numTets = 0;
mark++;
chainVertNrs.clear();
do {
SortEdge &e = edges[i];
mTetEdgeNrs[6 * e.tetNr + e.edgeNr] = edgeNr;
int i2 = -1;
int i3 = -1;
for (int j = 0; j < 4; j++) {
int id = mTetIndices[4 * e.tetNr + j];
if (id != e0.i0 && id != e0.i1) {
if (i2 < 0) i2 = id;
else i3 = id;
}
}
PX_ASSERT(i2 >= 0 && i3 >= 0);
// dihedral angle at edge
PxVec3 &p0 = mTetVertices[e0.i0];
PxVec3 &p1 = mTetVertices[e0.i1];
PxVec3 &p2 = mTetVertices[i2];
PxVec3 &p3 = mTetVertices[i3];
PxVec3 n2 = (p1-p0).cross(p2-p0); n2.normalize();
if ((p3-p0).dot(n2) > 0.0f) n2 = -n2;
PxVec3 n3 = (p1-p0).cross(p3-p0); n3.normalize();
if ((p2-p0).dot(n3) > 0.0f) n3 = -n3;
float dot = n2.dot(n3);
float dihed = PxPi - PxAcos(dot);
// chain for ordering tets of edge correctly
ChainVert &cv2 = chainVerts[i2];
ChainVert &cv3 = chainVerts[i3];
if (cv2.mark != mark) { cv2.adjVert0 = -1; cv2.adjVert1 = -1; cv2.mark = mark; }
if (cv3.mark != mark) { cv3.adjVert0 = -1; cv3.adjVert1 = -1; cv3.mark = mark; }
if (cv2.adjVert0 < 0) { cv2.adjVert0 = i3; cv2.tet0 = e.tetNr; cv2.dihed0 = dihed; }
else { cv2.adjVert1 = i3; cv2.tet1 = e.tetNr; cv2.dihed1 = dihed; }
if (cv3.adjVert0 < 0) { cv3.adjVert0 = i2; cv3.tet0 = e.tetNr; cv3.dihed0 = dihed; }
else { cv3.adjVert1 = i2; cv3.tet1 = e.tetNr; cv3.dihed1 = dihed; }
chainVertNrs.pushBack(i2);
chainVertNrs.pushBack(i3);
i++;
}
while (i < (int)edges.size() && edges[i] == e0);
te.numTets = chainVertNrs.size() / 2;
// find chain start;
int startVertNr = -1;
for (int j = 0; j < (int)chainVertNrs.size(); j++) {
ChainVert &cv = chainVerts[chainVertNrs[j]];
if (cv.adjVert0 < 0 || cv.adjVert1 < 0) {
startVertNr = chainVertNrs[j];
break;
}
}
te.onSurface = startVertNr >= 0;
mTetEdges.pushBack(te);
int curr = startVertNr;
if (curr < 0) curr = chainVertNrs[0];
int prev = -1;
// collect adjacent tetrahedra
for (int j = 0; j < te.numTets; j++) {
ChainVert &cv = chainVerts[curr];
int next;
if (cv.adjVert0 == prev) {
next = cv.adjVert1;
mEdgeTetNrs.pushBack(cv.tet1);
mEdgeTetAngles.pushBack(cv.dihed1);
}
else {
next = cv.adjVert0;
mEdgeTetNrs.pushBack(cv.tet0);
mEdgeTetAngles.pushBack(cv.dihed0);
}
prev = curr;
curr = next;
}
}
}
// -----------------------------------------------------------------------------
bool CompoundCreator::tetHasColor(int tetNr, int color)
{
int nr = mTetFirstColor[tetNr];
while (nr >= 0) {
if (mTetColors[nr].color == color)
return true;
nr = mTetColors[nr].next;
}
return false;
}
// -----------------------------------------------------------------------------
bool CompoundCreator::tetAddColor(int tetNr, int color)
{
if (tetHasColor(tetNr, color))
return false;
Color c;
c.color = color;
c.next = mTetFirstColor[tetNr];
if (mTetColorsFirstEmpty <= 0) { // new entry
mTetFirstColor[tetNr] = mTetColors.size();
mTetColors.pushBack(c);
}
else { // take from empty list
int newNr = mTetColorsFirstEmpty;
mTetFirstColor[tetNr] = newNr;
mTetColorsFirstEmpty = mTetColors[newNr].next;
mTetColors[newNr] = c;
}
return true;
}
// -----------------------------------------------------------------------------
bool CompoundCreator::tetRemoveColor(int tetNr, int color)
{
int nr = mTetFirstColor[tetNr];
int prev = -1;
while (nr >= 0) {
if (mTetColors[nr].color == color) {
if (prev < 0)
mTetFirstColor[tetNr] = mTetColors[nr].next;
else
mTetColors[prev].next = mTetColors[nr].next;
// add to empty list
mTetColors[nr].next = mTetColorsFirstEmpty;
mTetColorsFirstEmpty = nr;
return true;
}
prev = nr;
nr = mTetColors[nr].next;
}
return false;
}
// -----------------------------------------------------------------------------
int CompoundCreator::tetNumColors(int tetNr)
{
int num = 0;
int nr = mTetFirstColor[tetNr];
while (nr >= 0) {
num++;
nr = mTetColors[nr].next;
}
return num;
}
// -----------------------------------------------------------------------------
void CompoundCreator::deleteColors()
{
mTetFirstColor.resize(mTetIndices.size()/4, -1);
mTetColors.clear();
mTetColorsFirstEmpty = -1;
}
// -----------------------------------------------------------------------------
bool CompoundCreator::tryTet(int tetNr, int color)
{
if (tetNr < 0)
return false;
//if (mTetColors[tetNr] >= 0)
// return false;
if (tetHasColor(tetNr, color))
return false;
mTestEdges.clear();
mAddedTets.clear();
tetAddColor(tetNr, color);
mAddedTets.pushBack(tetNr);
for (int i = 0; i < 6; i++)
mTestEdges.pushBack(mTetEdgeNrs[6*tetNr+i]);
bool failed = false;
while (mTestEdges.size() > 0) {
int edgeNr = mTestEdges[mTestEdges.size()-1];
mTestEdges.popBack();
TetEdge &e = mTetEdges[edgeNr];
bool anyOtherCol = false;
float sumAng = 0.0f;
for (int i = 0; i < e.numTets; i++) {
int edgeTetNr = mEdgeTetNrs[e.firstTet + i];
if (tetHasColor(edgeTetNr, color))
sumAng += mEdgeTetAngles[e.firstTet + i];
else if (tetNumColors(edgeTetNr) > 0)
anyOtherCol = true;
}
if (sumAng < CONVEX_THRESHOLD)
continue;
// if (e.onSurface || anyOtherCol) {
if (e.onSurface) {
failed = true;
break;
}
for (int i = 0; i < e.numTets; i++) {
int edgeTetNr = mEdgeTetNrs[e.firstTet + i];
if (!tetHasColor(edgeTetNr, color)) {
tetAddColor(edgeTetNr, color);
mAddedTets.pushBack(edgeTetNr);
for (int j = 0; j < 6; j++)
mTestEdges.pushBack(mTetEdgeNrs[6*edgeTetNr+j]);
}
}
}
if (failed) {
for (int i = 0; i < (int)mAddedTets.size(); i++)
tetRemoveColor(mAddedTets[i], color);
mAddedTets.clear();
return false;
}
return true;
}
// -----------------------------------------------------------------------------
void CompoundCreator::colorTets()
{
int numTets = mTetIndices.size() / 4;
deleteColors();
int color = 0;
shdfnd::Array<int> edges;
shdfnd::Array<int> faces;
for (int i = 0; i < numTets; i++) {
if (tetNumColors(i) > 0)
continue;
tetAddColor(i, color);
faces.clear();
faces.pushBack(4*i);
faces.pushBack(4*i+1);
faces.pushBack(4*i+2);
faces.pushBack(4*i+3);
while (faces.size() > 0) {
int faceNr = faces[faces.size()-1];
faces.popBack();
int adjTetNr = mTetNeighbors[faceNr];
if (adjTetNr < 0)
continue;
//if (tetNumColors(adjTetNr) > 0)
// continue;
if (!tryTet(adjTetNr, color))
continue;
for (int j = 0; j < (int)mAddedTets.size(); j++) {
int addedTet = mAddedTets[j];
for (int k = 0; k < 4; k++) {
int adj = mTetNeighbors[4*addedTet+k];
if (adj >= 0 && !tetHasColor(adj, color))
faces.pushBack(4*addedTet+k);
}
}
}
color++;
}
}
// -----------------------------------------------------------------------------
void CompoundCreator::colorsToConvexes()
{
mGeom.clear();
int numTets = mTetIndices.size() / 4;
int numColors = 0;
for (int i = 0; i < (int)mTetColors.size(); i++) {
int color = mTetColors[i].color;
if (color >= numColors)
numColors = color+1;
}
shdfnd::Array<bool> colorVisited(numColors, false);
shdfnd::Array<int> queue;
shdfnd::Array<int> globalToLocal(mTetVertices.size(), -1);
shdfnd::Array<int> tetMarks(numTets, 0);
shdfnd::Array<int> vertMarks(mTetVertices.size(), 0);
int mark = 1;
shdfnd::Array<int> colorToConvexNr;
CompoundGeometry::Convex c;
for (int i = 0; i < numTets; i++) {
int nr = mTetFirstColor[i];
while (nr >= 0) {
int color = mTetColors[nr].color;
nr = mTetColors[nr].next;
if (colorVisited[color])
continue;
colorVisited[color] = true;
if ((int)colorToConvexNr.size() <= color)
colorToConvexNr.resize(color+1, -1);
colorToConvexNr[color] = mGeom.convexes.size();
queue.clear();
queue.pushBack(i);
mGeom.initConvex(c);
mark++;
c.numVerts = 0;
// flood fill
while (!queue.empty()) {
int tetNr = queue[queue.size()-1];
queue.popBack();
if (tetMarks[tetNr] == mark)
continue;
tetMarks[tetNr] = mark;
for (int j = 0; j < 4; j++) {
int adjNr = mTetNeighbors[4*tetNr + j];
if (adjNr < 0 || !tetHasColor(adjNr, color)) {
// create new face
mGeom.indices.pushBack(3); // face size
int flags = 0;
if (adjNr < 0) flags |= CompoundGeometry::FF_OBJECT_SURFACE;
mGeom.indices.pushBack(flags);
for (int k = 0; k < 3; k++) {
int id = mTetIndices[4*tetNr + tetFaceIds[j][k]];
if (vertMarks[id] != mark) {
vertMarks[id] = mark;
globalToLocal[id] = c.numVerts;
c.numVerts++;
mGeom.vertices.pushBack(mTetVertices[id]);
}
mGeom.indices.pushBack(globalToLocal[id]);
}
c.numFaces++;
}
if (adjNr >= 0) {
// add neighbors
int colNr = mTetFirstColor[adjNr];
while (colNr >= 0) {
int adjColor = mTetColors[colNr].color;
colNr = mTetColors[colNr].next;
if (adjColor != color) {
bool isNew = true;
for (int k = 0; k < c.numNeighbors; k++) {
if (mGeom.neighbors[c.firstNeighbor+k] == adjColor) {
isNew = false;
break;
}
}
if (isNew) {
mGeom.neighbors.pushBack(adjColor);
c.numNeighbors++;
}
}
}
}
if (adjNr < 0 || !tetHasColor(adjNr, color) || tetMarks[adjNr] == mark)
continue;
queue.pushBack(adjNr);
}
}
mGeom.convexes.pushBack(c);
}
}
for (int i = 0; i < (int)mGeom.neighbors.size(); i++) {
if (mGeom.neighbors[i] >= 0)
mGeom.neighbors[i] = colorToConvexNr[mGeom.neighbors[i]];
}
}
}
}
}
#endif

View File

@ -0,0 +1,130 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef COMPOUND_CREATOR_BASE_H
#define COMPOUND_CREATOR_BASE_H
// Matthias Mueller-Fischer
#include <foundation/PxVec3.h>
#include <foundation/PxTransform.h>
#include <PsArray.h>
#include <PsUserAllocated.h>
#include "CompoundGeometryBase.h"
namespace physx
{
class PxConvexMeshGeometry;
namespace fracture
{
namespace base
{
class SimScene;
// ---------------------------------------------------------------------------------------
class CompoundCreator : public ::physx::shdfnd::UserAllocated {
friend class SimScene;
public:
// direct
void createTorus(float r0, float r1, int numSegs0, int numSegs1, const PxTransform *trans = NULL);
void createCylinder(float r, float h, int numSegs, const PxTransform *trans = NULL);
void createBox(const PxVec3 &dims, const PxTransform *trans = NULL, bool clearShape = true);
void createSphere(const PxVec3 &dims, int resolution = 5, const PxTransform *trans = NULL);
void fromTetraMesh(const shdfnd::Array<PxVec3> &tetVerts, const shdfnd::Array<int> &tetIndices);
void createFromConvexMesh(const PxConvexMeshGeometry& convexGeom, PxTransform offset = PxTransform(PxIdentity), bool clear = true);
const CompoundGeometry &getGeometry() { return mGeom; }
virtual void debugDraw() {}
protected:
CompoundCreator(SimScene* scene): mScene(scene) {}
virtual ~CompoundCreator() {}
SimScene* mScene;
static int tetFaceIds[4][3];
static int tetEdgeVerts[6][2];
static int tetFaceEdges[4][3];
void computeTetNeighbors();
void computeTetEdges();
void colorTets();
void colorsToConvexes();
bool tetHasColor(int tetNr, int color);
bool tetAddColor(int tetNr, int color);
bool tetRemoveColor(int tetNr, int color);
int tetNumColors(int tetNr);
void deleteColors();
bool tryTet(int tetNr, int color);
// from tet mesh
shdfnd::Array<PxVec3> mTetVertices;
shdfnd::Array<int> mTetIndices;
shdfnd::Array<int> mTetNeighbors;
shdfnd::Array<int> mTetFirstColor;
struct Color {
int color;
int next;
};
int mTetColorsFirstEmpty;
shdfnd::Array<Color> mTetColors;
struct TetEdge {
void init(int i0, int i1) { this->i0 = i0; this->i1 = i1; firstTet = 0; numTets = 0; onSurface = false; }
int i0, i1;
int firstTet, numTets;
bool onSurface;
};
shdfnd::Array<TetEdge> mTetEdges;
shdfnd::Array<int> mTetEdgeNrs;
shdfnd::Array<int> mEdgeTetNrs;
shdfnd::Array<float> mEdgeTetAngles;
shdfnd::Array<int> mAddedTets;
shdfnd::Array<int> mTestEdges;
// input
shdfnd::Array<PxVec3> mVertices;
shdfnd::Array<int> mIndices;
// output
CompoundGeometry mGeom;
};
}}}
#endif
#endif

View File

@ -0,0 +1,113 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#include "CompoundGeometryBase.h"
namespace physx
{
namespace fracture
{
namespace base
{
// -------------------------------------------------------------------------------
void CompoundGeometry::clear()
{
convexes.clear();
vertices.clear();;
normals.clear();
indices.clear();
neighbors.clear();
planes.clear();
}
// -------------------------------------------------------------------------------
bool CompoundGeometry::loadFromFile(const char * /*filename*/)
{
return true;
}
// -------------------------------------------------------------------------------
bool CompoundGeometry::saveFromFile(const char * /*filename*/)
{
return true;
}
// -------------------------------------------------------------------------------
void CompoundGeometry::initConvex(Convex &c)
{
c.firstVert = vertices.size();
c.numVerts = 0;
c.firstNormal = normals.size();
c.firstIndex = indices.size();
c.numFaces = 0;
c.firstPlane = 0;
c.firstNeighbor = neighbors.size();
c.numNeighbors = 0;
c.radius = 0.f;
c.isSphere = false;
}
// -------------------------------------------------------------------------------
void CompoundGeometry::derivePlanes()
{
planes.clear();
PxPlane p;
for (int i = 0; i < (int)convexes.size(); i++) {
Convex &c = convexes[i];
c.firstPlane = planes.size();
int *ids = &indices[c.firstIndex];
PxVec3 *verts = &vertices[c.firstVert];
for (int j = 0; j < c.numFaces; j++) {
int num = *ids++;
*ids++; //int flags = *ids++;
if (num < 3)
p = PxPlane(1.0f, 0.0f, 0.0f, 0.0f);
else {
p.n = PxVec3(0.0f, 0.0f, 0.0f);
for (int k = 1; k < num-1; k++) {
const PxVec3 &p0 = verts[ids[0]];
const PxVec3 &p1 = verts[ids[k]];
const PxVec3 &p2 = verts[ids[k+1]];
p.n += (p1-p0).cross(p2-p1);
}
p.n.normalize();
p.d = p.n.dot(verts[ids[0]]);
}
planes.pushBack(p);
ids += num;
}
}
}
}
}
}
#endif

View File

@ -0,0 +1,95 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef COMPOUND_GEOMETRY_BASE
#define COMPOUND_GEOMETRY_BASE
#include <foundation/PxVec3.h>
#include <foundation/PxPlane.h>
#include <PsArray.h>
#include <PsUserAllocated.h>
namespace physx
{
namespace fracture
{
namespace base
{
// -----------------------------------------------------------------------------------
class CompoundGeometry : public ::physx::shdfnd::UserAllocated
{
public:
CompoundGeometry() {}
virtual ~CompoundGeometry() {}
bool loadFromFile(const char *filename);
bool saveFromFile(const char *filename);
void clear();
void derivePlanes();
virtual void debugDraw(int /*maxConvexes*/ = 0) const {}
struct Convex { // init using CompoundGeometry::initConvex()
int firstVert;
int numVerts;
int firstNormal; // one per face index! If not provided (see face flags) face normal is used
int firstIndex;
int numFaces;
int firstPlane;
int firstNeighbor;
int numNeighbors;
float radius;
bool isSphere;
};
void initConvex(Convex &c);
shdfnd::Array<Convex> convexes;
shdfnd::Array<PxVec3> vertices;
shdfnd::Array<PxVec3> normals; // one per face and vertex!
// face size, face flags, id, id, .., face size, face flags, id ..
shdfnd::Array<int> indices;
shdfnd::Array<int> neighbors;
shdfnd::Array<PxPlane> planes; // derived for faster cuts
enum FaceFlags {
FF_OBJECT_SURFACE = 1,
FF_HAS_NORMALS = 2,
FF_INVISIBLE = 4,
FF_NEW = 8,
};
};
}
}
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,239 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef CONVEX_BASE
#define CONVEX_BASE
#include <PxPhysics.h>
#include <PxCooking.h>
#include <foundation/PxVec3.h>
#include <foundation/PxPlane.h>
#include <foundation/PxBounds3.h>
#include <foundation/PxTransform.h>
#include <PsArray.h>
#include <PsUserAllocated.h>
namespace physx
{
namespace fracture
{
namespace base
{
class physx::PxShape;
class physx::PxActor;
class physx::PxScene;
class physx::PxConvexMesh;
class Compound;
class CompoundGeometry;
class SimScene;
// ----------------------------------------------------------------------------
class Convex : public ::physx::shdfnd::UserAllocated
{
friend class SimScene;
protected:
Convex(SimScene* scene);
public:
virtual ~Convex();
void createFromConvex(const Convex *convex, const PxTransform *trans = NULL, int matID = 0, int surfMatID = 0);
void createFromGeometry(const CompoundGeometry &geom, int convexNr, const PxMat44 *trans = NULL, int matID = 0, int surfMatID = 0);
void transform(const PxMat44 &trans);
PxVec3 centerAtZero();
PxVec3 getCenter() const;
void setTexScale(float texScale) { mTexScale = texScale; }
void increaseRefCounter() { mRefCounter++; }
int decreaseRefCounter() { mRefCounter--; return mRefCounter; }
bool rayCast(const PxVec3 &ray, const PxVec3 &dir, float &dist, PxVec3 &normal) const;
bool collide(const PxVec3 &pos, float r, float &penetration, PxVec3 &surfaceNormal, PxVec3 &surfaceVel) const;
void intersectWithConvex(const PxPlane *planes, int numPlanes, const PxMat44 &trans, bool &empty);
virtual void draw(bool /*debug*/ = false) {}
PxConvexMesh* createPxConvexMesh(Compound *parent, PxPhysics *pxPhysics, PxCooking *pxCooking);
void setPxActor(PxRigidActor *actor);
void setLocalPose(const PxTransform &pose);
// accessors
Compound *getParent() { return mParent; }
const Compound *getParent() const { return mParent; }
const PxConvexMesh *getPxConvexMesh() const { return mPxConvexMesh; }
PxConvexMesh *getPxConvexMesh() { return mPxConvexMesh; }
const shdfnd::Array<PxPlane> &getPlanes() const { return mPlanes; };
const PxBounds3 &getBounds() const { return mBounds; }
void getWorldBounds(PxBounds3 &bounds) const;
void getLocalBounds(PxBounds3 &bounds) const;
float getVolume() const;
void removeInvisibleFacesFlags();
void updateFaceVisibility(const float *faceCoverage);
void clearFraceFlags(unsigned int flag);
struct Face {
void init() {
firstIndex = 0; numIndices = 0; flags = 0; firstNormal = 0;
}
int firstIndex;
int numIndices;
int flags;
int firstNormal;
};
const shdfnd::Array<Face> &getFaces() const { return mFaces; }
const shdfnd::Array<int> &getIndices() const { return mIndices; }
const shdfnd::Array<PxVec3> &getVertices() const { return mVertices; }
const shdfnd::Array<PxVec3> &getVisVertices() const { return mVisVertices; }
const shdfnd::Array<PxVec3> &getVisNormals() const { return mVisNormals; }
const shdfnd::Array<PxVec3> &getVisTangents() const { return mVisTangents; }
const shdfnd::Array<float> &getVisTexCoords() const { return mVisTexCoords; }
const shdfnd::Array<int> &getVisTriIndices() const { return mVisTriIndices; }
const shdfnd::Array<int> &getVisPolyStarts() const { return mVisPolyStarts; }
const shdfnd::Array<int> &getVisPolyIndices() const { return mVisPolyIndices; }
const shdfnd::Array<int> &getVisPolyNeighbors() const { return mVisPolyNeighbors; }
PxVec3 getMaterialOffset() const { return mMaterialOffset; }
void setMaterialOffset(const PxVec3 &offset);
PxTransform getGlobalPose() const;
PxTransform getLocalPose() const;
bool isGhostConvex() const { return mIsGhostConvex; }
// explicit visual mesh
bool hasExplicitVisMesh() const { return mHasExplicitVisMesh; }
bool setExplicitVisMeshFromTriangles(int numVertices, const PxVec3 *vertices, const PxVec3 *normals, const PxVec2 *texcoords,
int numIndices, const PxU32 *indices, PxTransform *trans = NULL, const PxVec3* scale = NULL);
bool setExplicitVisMeshFromPolygons(int numVertices, const PxVec3 *vertices, const PxVec3 *normals,
const PxVec3 *tangents, const float *texCoords,
int numPolygons, const int *polyStarts, // numPolygons+1 entries
int numIndices, const int *indices, PxTransform *trans = NULL, const PxVec3* scale = NULL);
void createVisTrisFromPolys();
void createVisMeshFromConvex();
void transformVisualMesh(const PxTransform &trans);
bool insideVisualMesh(const PxVec3 &pos) const;
void fitToVisualMesh(bool &cutEmpty, int numFitDirections = 3);
bool isOnConvexSurface(const PxVec3 pts) const;
bool check();
PxActor* getActor();
bool insideFattened(const PxVec3 &pos, float r) const;
bool use2dTexture() const { return mUse2dTexture; }
bool isIndestructible() const { return mIndestructible; }
int getMaterialId() const { return mMaterialId; }
int getSurfaceMaterialId() const { return mSurfaceMaterialId; }
void setSurfaceMaterialId(int id) { mSurfaceMaterialId = id; }
void setModelIslandNr(int nr) { mModelIslandNr = nr; }
int getModelIslandNr() const { return mModelIslandNr; }
void setConvexRendererInfo(int groupNr, int groupPos) const { mConvexRendererGroupNr = groupNr; mConvexRendererGroupPos = groupPos; }
int getConvexRendererGroupNr() const { return mConvexRendererGroupNr; }
int getConvexRendererGroupPos() const { return mConvexRendererGroupPos; }
void setIsFarConvex(bool v) { mIsFarConvex = v; }
bool getIsFarConvex() { return mIsFarConvex; }
protected:
void clear();
void finalize();
void updateBounds();
void updatePlanes();
bool computeVisMeshNeighbors();
void computeVisTangentsFromPoly();
bool cutVisMesh(const PxVec3 &localPlaneN, float localPlaneD, bool &cutEmpty);
bool cut(const PxVec3 &localPlaneN, float localPlaneD, bool &cutEmpty, bool setNewFaceFlag = true);
bool rayCastConvex(const PxVec3 &orig, const PxVec3 &dir, float &dist, PxVec3 &normal) const;
bool rayCastVisMesh(const PxVec3 &orig, const PxVec3 &dir, float &dist, PxVec3 &normal) const;
SimScene* mScene;
shdfnd::Array<Face> mFaces;
shdfnd::Array<int> mIndices;
shdfnd::Array<PxVec3> mVertices;
shdfnd::Array<PxVec3> mNormals;
shdfnd::Array<PxPlane> mPlanes;
shdfnd::Array<PxVec3> mVisVertices;
shdfnd::Array<PxVec3> mVisNormals;
shdfnd::Array<PxVec3> mVisTangents;
shdfnd::Array<float> mVisTexCoords;
shdfnd::Array<int> mVisTriIndices;
int mRefCounter;
bool mHasExplicitVisMesh;
bool mIsGhostConvex;
shdfnd::Array<int> mVisPolyStarts; // for explicit mesh only
shdfnd::Array<int> mVisPolyIndices;
shdfnd::Array<int> mVisPolyNeighbors;
Convex *mNewConvex; // temporary buffer for cut operations
Compound *mParent;
PxRigidActor *mPxActor;
PxTransform mLocalPose;
PxConvexMesh *mPxConvexMesh;
PxBounds3 mBounds;
mutable float mVolume;
mutable bool mVolumeDirty;
PxVec3 mMaterialOffset;
float mTexScale;
int mModelIslandNr;
// material
bool mUse2dTexture;
bool mIndestructible;
int mMaterialId;
int mSurfaceMaterialId;
bool mIsFarConvex;
mutable int mConvexRendererGroupNr;
mutable int mConvexRendererGroupPos;
};
}
}
}
#endif
#endif

View File

@ -0,0 +1,239 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#include <foundation/PxBounds3.h>
#include "MeshBase.h"
#include <algorithm>
namespace physx
{
namespace fracture
{
namespace base
{
// ----------------------------------------------------------------------
void Mesh::updateNormals()
{
if (mVertices.empty())
return;
PxVec3 zero(0.0f, 0.0f, 0.0f);
mNormals.resize(mVertices.size());
for (int i = 0; i < (int)mNormals.size(); i++)
mNormals[i] = zero;
PxVec3 n;
PxU32 *idx = &mIndices[0];
int numTriangles = mIndices.size() / 3;
for (int i = 0; i < numTriangles; i++) {
PxU32 i0 = *idx++;
PxU32 i1 = *idx++;
PxU32 i2 = *idx++;
n = (mVertices[i1] - mVertices[i0]).cross(mVertices[i2] - mVertices[i0]);
mNormals[i0] += n;
mNormals[i1] += n;
mNormals[i2] += n;
}
for (int i = 0; i < (int)mNormals.size(); i++) {
if (!mNormals[i].isZero())
mNormals[i].normalize();
}
}
// ------------------------------------------------------------------------------
void Mesh::getBounds(PxBounds3 &bounds, int subMeshNr) const
{
bounds.setEmpty();
if (subMeshNr < 0 || subMeshNr >= (int)mSubMeshes.size()) {
for (int i = 0; i < (int)mVertices.size(); i++)
bounds.include(mVertices[i]);
}
else {
const SubMesh &sm = mSubMeshes[subMeshNr];
for (int i = 0; i < sm.numIndices; i++) {
bounds.include(mVertices[mIndices[sm.firstIndex + i]]);
}
}
}
// ------------------------------------------------------------------------------
void Mesh::normalize(const PxVec3 &center, float diagonal)
{
if (mVertices.size() < 3)
return;
PxBounds3 bounds;
getBounds(bounds);
float s = diagonal / bounds.getDimensions().magnitude();
PxVec3 c = 0.5f * (bounds.minimum + bounds.maximum);
for (int i = 0; i < (int)mVertices.size(); i++)
mVertices[i] = center + (mVertices[i] - c) * s;
}
// ------------------------------------------------------------------------------
void Mesh::scale(float diagonal)
{
if (mVertices.size() < 3)
return;
PxBounds3 bounds;
getBounds(bounds);
float s = diagonal / bounds.getDimensions().magnitude();
for (int i = 0; i < (int)mVertices.size(); i++)
mVertices[i] *= s;
}
// --------------------------------------------------------------------------------------------
struct IdEdge {
void set(PxU32 &i0, PxU32 &i1, int faceNr, int edgeNr) {
if (i0 < i1) { this->i0 = i0; this->i1 = i1; }
else { this->i0 = i1; this->i1 = i0; }
this->faceNr = faceNr; this->edgeNr = edgeNr;
}
bool operator < (const IdEdge &e) const {
if (i0 < e.i0) return true;
if (i0 == e.i0 && i1 < e.i1) return true;
return false;
}
bool operator == (const IdEdge &e) const { return i0 == e.i0 && i1 == e.i1; }
PxU32 i0,i1;
int faceNr, edgeNr;
};
// ------------------------------------------------------------------------------
bool Mesh::computeNeighbors()
{
int numTris = mIndices.size() / 3;
shdfnd::Array<IdEdge> edges(3*numTris);
for (int i = 0; i < numTris; i++) {
for (int j = 0; j < 3; j++)
edges[3*i+j].set(mIndices[3*i+j], mIndices[3*i + (j+1)%3], i, j);
}
std::sort(edges.begin(), edges.end());
mNeighbors.clear();
mNeighbors.resize(mIndices.size(), -1);
bool manifold = true;
int i = 0;
while (i < (int)edges.size()) {
IdEdge &e0 = edges[i];
i++;
if (i < (int)edges.size() && edges[i] == e0) {
IdEdge &e1 = edges[i];
mNeighbors[3* e0.faceNr + e0.edgeNr] = e1.faceNr;
mNeighbors[3* e1.faceNr + e1.edgeNr] = e0.faceNr;
i++;
}
while (i < (int)edges.size() && edges[i] == e0) {
manifold = false;
i++;
}
}
return manifold;
}
// --------------------------------------------------------------------------------------------
struct PosEdge {
// not using indices for edge match but positions
// so duplicated vertices are handled as one vertex
static bool smaller(const PxVec3 &v0, const PxVec3 &v1) {
if (v0.x < v1.x) return true;
if (v0.x > v1.x) return false;
if (v0.y < v1.y) return true;
if (v0.y > v1.y) return false;
return (v0.z < v1.z);
}
void set(const PxVec3 &v0, const PxVec3 &v1, int faceNr, int edgeNr) {
if (smaller(v0,v1)) { this->v0 = v0; this->v1 = v1; }
else { this->v0 = v1; this->v1 = v0; }
this->faceNr = faceNr; this->edgeNr = edgeNr;
}
bool operator < (const PosEdge &e) const {
if (smaller(v0, e.v0)) return true;
if (v0 == e.v0 && smaller(v1, e.v1)) return true;
return false;
}
bool operator == (const PosEdge &e) const { return v0 == e.v0 && v1 == e.v1; }
PxVec3 v0,v1;
int faceNr, edgeNr;
};
// ------------------------------------------------------------------------------
bool Mesh::computeWeldedNeighbors()
{
int numTris = mIndices.size() / 3;
shdfnd::Array<PosEdge> edges(3*numTris);
for (int i = 0; i < numTris; i++) {
for (int j = 0; j < 3; j++)
edges[3*i+j].set(mVertices[mIndices[3*i+j]], mVertices[mIndices[3*i + (j+1)%3]], i, j);
}
std::sort(edges.begin(), edges.end());
mNeighbors.clear();
mNeighbors.resize(mIndices.size(), -1);
bool manifold = true;
int i = 0;
while (i < (int)edges.size()) {
PosEdge &e0 = edges[i];
i++;
if (i < (int)edges.size() && edges[i] == e0) {
PosEdge &e1 = edges[i];
mNeighbors[3* e0.faceNr + e0.edgeNr] = e1.faceNr;
mNeighbors[3* e1.faceNr + e1.edgeNr] = e0.faceNr;
i++;
}
while (i < (int)edges.size() && edges[i] == e0) {
manifold = false;
i++;
}
}
return manifold;
}
void Mesh::flipV()
{
for(PxU32 i = 0; i < mTexCoords.size(); i++)
{
mTexCoords[i].y = 1.0f - mTexCoords[i].y;
}
}
}
}
}
#endif

View File

@ -0,0 +1,94 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef MESH_BASE
#define MESH_BASE
#include <foundation/PxVec3.h>
#include <foundation/PxVec2.h>
#include <PsArray.h>
#include <PsUserAllocated.h>
namespace physx
{
namespace fracture
{
namespace base
{
// -----------------------------------------------------------------------------------
class Mesh : public ::physx::shdfnd::UserAllocated
{
public:
Mesh() {};
virtual ~Mesh() {};
const shdfnd::Array<PxVec3> &getVertices() const { return mVertices; }
const shdfnd::Array<PxVec3> &getNormals() const { return mNormals; }
const shdfnd::Array<PxVec2> &getTexCoords() const { return mTexCoords; }
const shdfnd::Array<PxU32> &getIndices() const { return mIndices; }
const shdfnd::Array<int> &getNeighbors() const { return mNeighbors; }
struct SubMesh {
void init() { /*name = "";*/ firstIndex = -1; numIndices = 0; }
//std::string name;
int firstIndex;
int numIndices;
};
const shdfnd::Array<SubMesh> &getSubMeshes() const { return mSubMeshes; }
void normalize(const PxVec3 &center, float diagonal);
void scale(float diagonal);
void getBounds(PxBounds3 &bounds, int subMeshNr = -1) const;
void flipV(); // flips v values to hand coordinate system change (Assumes normalized coordinates)
bool computeNeighbors();
bool computeWeldedNeighbors();
protected:
void clear();
void updateNormals();
shdfnd::Array<PxVec3> mVertices;
shdfnd::Array<PxVec3> mNormals;
shdfnd::Array<PxVec2> mTexCoords;
shdfnd::Array<SubMesh> mSubMeshes;
shdfnd::Array<PxU32> mIndices;
shdfnd::Array<int> mNeighbors;
};
}
}
}
#endif
#endif

View File

@ -0,0 +1,299 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#include "PolygonTriangulatorBase.h"
#include <foundation/PxAssert.h>
namespace physx
{
namespace fracture
{
namespace base
{
// ------ singleton pattern -----------------------------------------------------------
//static PolygonTriangulator *gPolygonTriangulator = NULL;
//
//PolygonTriangulator* PolygonTriangulator::getInstance()
//{
// if (gPolygonTriangulator == NULL) {
// gPolygonTriangulator = PX_NEW(PolygonTriangulator)();
// }
// return gPolygonTriangulator;
//}
//
//void PolygonTriangulator::destroyInstance()
//{
// if (gPolygonTriangulator != NULL) {
// PX_DELETE(gPolygonTriangulator);
// }
// gPolygonTriangulator = NULL;
//}
// -------------------------------------------------------------------------------------
PolygonTriangulator::PolygonTriangulator(SimScene* scene):
mScene(scene)
{
}
// -------------------------------------------------------------------------------------
PolygonTriangulator::~PolygonTriangulator()
{
}
// -------------------------------------------------------------------------------------
float PolygonTriangulator::cross(const PxVec3 &p0, const PxVec3 &p1)
{
return p0.x * p1.y - p0.y * p1.x;
}
// -------------------------------------------------------------------------------------
bool PolygonTriangulator::inTriangle(const PxVec3 &p, const PxVec3 &p0, const PxVec3 &p1, const PxVec3 &p2)
{
float d0 = cross(p1 - p0, p - p0);
float d1 = cross(p2 - p1, p - p1);
float d2 = cross(p0 - p2, p - p2);
return (d0 >= 0.0f && d1 >= 0.0f && d2 >= 0.0f) ||
(d0 <= 0.0f && d1 <= 0.0f && d2 <= 0.0f);
}
// -------------------------------------------------------------------------------------
void PolygonTriangulator::triangulate(const PxVec3 *points, int numPoints, const int *indices, PxVec3 *planeNormal)
{
mIndices.clear();
if (numPoints < 3)
return;
if (numPoints == 3) {
if (indices == NULL) {
mIndices.pushBack(0);
mIndices.pushBack(1);
mIndices.pushBack(2);
}
else {
mIndices.pushBack(indices[0]);
mIndices.pushBack(indices[1]);
mIndices.pushBack(indices[2]);
}
return;
}
bool isConvex;
importPoints(points, numPoints, indices, planeNormal, isConvex);
if (isConvex) { // fast path
mIndices.resize(3*(numPoints-2));
for (int i = 0; i < numPoints-2; i++) {
mIndices[3*i] = 0;
mIndices[3*i+1] = i+1;
mIndices[3*i+2] = i+2;
}
}
else
clipEars();
if (indices != NULL) {
for (int i = 0; i < (int)mIndices.size(); i++) {
mIndices[i] = indices[mIndices[i]];
}
}
}
// -------------------------------------------------------------------------------------
void PolygonTriangulator::importPoints(const PxVec3 *points, int numPoints, const int *indices, PxVec3 *planeNormal, bool &isConvex)
{
// find projection 3d -> 2d;
PxVec3 n;
isConvex = true;
if (planeNormal)
n = *planeNormal;
else {
PX_ASSERT(numPoints >= 3);
n = PxVec3(0.0f, 0.0f, 0.0f);
for (int i = 1; i < numPoints-1; i++) {
int i0 = 0;
int i1 = i;
int i2 = i+1;
if (indices) {
i0 = indices[i0];
i1 = indices[i1];
i2 = indices[i2];
}
const PxVec3 &p0 = points[i0];
const PxVec3 &p1 = points[i1];
const PxVec3 &p2 = points[i2];
PxVec3 ni = (p1-p0).cross(p2-p0);
if (i > 1 && ni.dot(n) < 0.0f)
isConvex = false;
n += ni;
}
}
n.normalize();
PxVec3 t0,t1;
if (fabs(n.x) < fabs(n.y) && fabs(n.x) < fabs(n.z))
t0 = PxVec3(1.0f, 0.0f, 0.0f);
else if (fabs(n.y) < fabs(n.z))
t0 = PxVec3(0.0f, 1.0f, 0.0f);
else
t0 = PxVec3(0.0f, 0.0f, 1.0f);
t1 = n.cross(t0);
t1.normalize();
t0 = t1.cross(n);
mPoints.resize(numPoints);
if (indices == NULL) {
for (int i = 0; i < numPoints; i++)
mPoints[i] = PxVec3(points[i].dot(t0), points[i].dot(t1), 0.0f);
}
else {
for (int i = 0; i < numPoints; i++) {
const PxVec3 &p = points[indices[i]];
mPoints[i] = PxVec3(p.dot(t0), p.dot(t1), 0.0f);
}
}
}
// -------------------------------------------------------------------------------------
void PolygonTriangulator::clipEars()
{
// init
int num = mPoints.size();
mCorners.resize(num);
for (int i = 0; i < num; i++) {
Corner &c = mCorners[i];
c.prev = (i > 0) ? i-1 : num-1;
c.next = (i < num-1) ? i + 1 : 0;
c.isEar = false;
c.angle = 0.0f;
PxVec3 &p0 = mPoints[c.prev];
PxVec3 &p1 = mPoints[i];
PxVec3 &p2 = mPoints[c.next];
PxVec3 n1 = p1-p0;
PxVec3 n2 = p2-p1;
if (cross(n1, n2) > 0.0f) {
n1.normalize();
n2.normalize();
c.angle = n1.dot(n2);
c.isEar = true;
int nr = (i+2) % num;
for (int j = 0; j < num-3; j++) {
if (inTriangle(mPoints[nr], p0,p1,p2)) {
c.isEar = false;
break;
}
nr = (nr+1) % num;
}
}
}
int firstCorner = 0;
int numCorners = num;
while (numCorners > 3) {
// find best ear
float minAng = FLT_MAX;
int minNr = -1;
int nr = firstCorner;
for (int i = 0; i < numCorners; i++) {
Corner &c = mCorners[nr];
if (c.isEar && c.angle < minAng) {
minAng = c.angle;
minNr = nr;
}
nr = c.next;
}
// cut ear
// assert(minNr >= 0);
if (minNr < 0)
break;
Corner &cmin = mCorners[minNr];
mIndices.pushBack(cmin.prev);
mIndices.pushBack(minNr);
mIndices.pushBack(cmin.next);
mCorners[cmin.prev].next = cmin.next;
mCorners[cmin.next].prev = cmin.prev;
if (firstCorner == minNr)
firstCorner = cmin.next;
numCorners--;
if (numCorners == 3)
break;
// new ears?
for (int i = 0; i < 2; i++) {
int i1 = (i == 0) ? cmin.prev : cmin.next;
int i0 = mCorners[i1].prev;
int i2 = mCorners[i1].next;
PxVec3 &p0 = mPoints[i0];
PxVec3 &p1 = mPoints[i1];
PxVec3 &p2 = mPoints[i2];
PxVec3 n1 = p1-p0;
PxVec3 n2 = p2-p1;
if (cross(n1, n2) > 0.0f) {
n1.normalize();
n2.normalize();
mCorners[i1].angle = n1.dot(n2);
mCorners[i1].isEar = true;
int nr = mCorners[i2].next;
for (int j = 0; j < numCorners-3; j++) {
if (inTriangle(mPoints[nr], p0,p1,p2)) {
mCorners[i1].isEar = false;
break;
}
nr = mCorners[nr].next;
}
}
}
}
int id = firstCorner;
mIndices.pushBack(id);
id = mCorners[id].next;
mIndices.pushBack(id);
id = mCorners[id].next;
mIndices.pushBack(id);
}
}
}
}
#endif

View File

@ -0,0 +1,86 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef POLYGON_TRIANGULATOR_BASE_H
#define POLYGON_TRIANGULATOR_BASE_H
#include <foundation/PxVec3.h>
#include <foundation/PxMath.h>
#include <PsArray.h>
#include <PsUserAllocated.h>
namespace physx
{
namespace fracture
{
namespace base
{
// ------------------------------------------------------------------------------
class PolygonTriangulator : public ::physx::shdfnd::UserAllocated {
friend class SimScene;
public:
// singleton pattern
//static PolygonTriangulator* getInstance();
//static void destroyInstance();
void triangulate(const PxVec3 *points, int numPoints, const int *indices = NULL, PxVec3 *planeNormal = NULL);
const shdfnd::Array<int> &getIndices() const { return mIndices; }
protected:
void importPoints(const PxVec3 *points, int numPoints, const int *indices, PxVec3 *planeNormal, bool &isConvex);
void clipEars();
inline float cross(const PxVec3 &p0, const PxVec3 &p1);
bool inTriangle(const PxVec3 &p, const PxVec3 &p0, const PxVec3 &p1, const PxVec3 &p2);
PolygonTriangulator(SimScene* scene);
virtual ~PolygonTriangulator();
SimScene* mScene;
shdfnd::Array<PxVec3> mPoints;
shdfnd::Array<int> mIndices;
struct Corner {
int prev;
int next;
bool isEar;
float angle;
};
shdfnd::Array<Corner> mCorners;
};
}
}
}
#endif
#endif

View File

@ -0,0 +1,364 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#include "PsHashMap.h"
#include "SimSceneBase.h"
#include <foundation/PxMat44.h>
#include "PxRigidBodyExt.h"
#include "PxPhysics.h"
#include "PxCooking.h"
#include "PxShape.h"
#include "ActorBase.h"
#include "CompoundBase.h"
#include "ConvexBase.h"
#include "CompoundCreatorBase.h"
#include "PolygonTriangulatorBase.h"
#include "RTdef.h"
#include "PhysXMacros.h"
#include "PxScene.h"
#include "PxD6Joint.h"
#define USE_CONVEX_RENDERER 1
#define NUM_NO_SOUND_FRAMES 1
#define REL_VEL_FRACTURE_THRESHOLD 5.0f
//#define REL_VEL_FRACTURE_THRESHOLD 0.1f
namespace physx
{
namespace fracture
{
namespace base
{
SimScene* SimScene::createSimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath)
{
SimScene* s = PX_NEW(SimScene)(pxPhysics,pxCooking, isGrbScene,minConvexSize,defaultMat,resourcePath);
s->createSingletons();
return s;
}
void SimScene::createSingletons()
{
mCompoundCreator = PX_NEW(CompoundCreator)(this);
mPolygonTriangulator = PX_NEW(PolygonTriangulator)(this);
addActor(createActor()); // make default actor
}
Convex* SimScene::createConvex()
{
return PX_NEW(Convex)(this);
}
Compound* SimScene::createCompound(const FracturePattern *pattern, const FracturePattern *secondaryPattern, PxReal contactOffset, PxReal restOffset)
{
return PX_NEW(Compound)(this,contactOffset,restOffset);
}
Actor* SimScene::createActor()
{
return PX_NEW(Actor)(this);
}
shdfnd::Array<Compound*> SimScene::getCompounds()
{
return mActors[0]->getCompounds();
}
///*extern*/ std::vector<Compound*> delCompoundList;
// --------------------------------------------------------------------------------------------
SimScene::SimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath)
{
mPxPhysics = pxPhysics; // used for cooking
mPxCooking = pxCooking;
mPxDefaultMaterial = defaultMat;
mResourcePath = resourcePath;
clear();
mRenderBuffers.init();
mSceneVersion = 1;
mRenderBufferVersion = 0;
mOptixBufferVersion = 0;
//create3dTexture();
mFractureForceThreshold = 500.0f;
mContactImpactRadius = 0.5f;
mNoFractureFrames = 0;
mNoSoundFrames = 0;
mFrameNr = 0;
mDebugDraw = false;
// mDebugDraw = true; // foo
mPickDepth = 0.0f;
mPickActor = NULL;
mPickJoint = NULL;
mPickPos = mPickLocalPos = PxVec3(0.0f, 0.0f, 0.0f);
mMinConvexSize = minConvexSize;
mNumNoFractureFrames = 2;
bumpTextureUVScale = 0.1f;
roughnessScale = 0.2f;
extraNoiseScale = 2.0f;
particleBumpTextureUVScale = 0.2f;
particleRoughnessScale = 0.8f;
particleExtraNoiseScale = 2.0f;
mPlaySounds = false;
mRenderDebris = true;
mCompoundCreator = NULL;
mPolygonTriangulator = NULL;
mAppNotify = NULL;
}
// --------------------------------------------------------------------------------------------
SimScene::~SimScene()
{
clear();
// Delete actors if not already deleted
for(int i = ((int)mActors.size() - 1) ; i >= 0; i--)
{
PX_DELETE(mActors[i]);
}
PX_DELETE(mCompoundCreator);
PX_DELETE(mPolygonTriangulator);
mCompoundCreator = NULL;
mPolygonTriangulator = NULL;
}
// --------------------------------------------------------------------------------------------
void SimScene::clear()
{
for(int i = 0 ; i < (int)mActors.size(); i++)
{
mActors[i]->clear();
}
deleteCompounds();
mPickActor = NULL;
++mSceneVersion;
}
void SimScene::addActor(Actor* a)
{
mActors.pushBack(a);
}
void SimScene::removeActor(Actor* a)
{
for(int i = 0; i < (int)mActors.size(); i++)
{
if( a == mActors[i] )
{
mActors[i] = mActors[mActors.size()-1];
mActors.popBack();
}
}
}
// --------------------------------------------------------------------------------------------
void SimScene::addCompound(Compound *c)
{
mActors[0]->addCompound(c);
}
// --------------------------------------------------------------------------------------------
void SimScene::removeCompound(Compound *c)
{
mActors[0]->removeCompound(c);
}
// --------------------------------------------------------------------------------------------
void SimScene::deleteCompounds()
{
for (int i = 0; i < (int)delCompoundList.size(); i++)
{
PX_DELETE(delCompoundList[i]);
}
delCompoundList.clear();
}
// --------------------------------------------------------------------------------------------
void SimScene::preSim(float dt)
{
for(int i = 0 ; i < (int)mActors.size(); i++)
{
mActors[i]->preSim(dt);
}
// make sure we use the apex user notify... if the application
// changes their custom one make sure we map to it.
mScene->lockWrite();
PxSimulationEventCallback* userNotify = mScene->getSimulationEventCallback();
if (userNotify != this)
{
mAppNotify = userNotify;
mScene->setSimulationEventCallback(this);
}
mScene->unlockWrite();
}
//float4* posVelG = 0;
//int numPosVelG = 0;
// --------------------------------------------------------------------------------------------
void SimScene::postSim(float dt)
{
for(int i = 0 ; i < (int)mActors.size(); i++)
{
mActors[i]->postSim(dt);
}
mFrameNr++;
mNoFractureFrames--;
mNoSoundFrames--;
}
//-----------------------------------------------------------------------------
bool SimScene::pickStart(const PxVec3 &orig, const PxVec3 &dir)
{
PX_ASSERT(mPickActor == NULL);
float dist = 1000.f;
PxRaycastBuffer buffer;
if (!getScene()->raycast(orig, dir, dist, buffer, PxHitFlag::eDEFAULT, PxQueryFilterData(PxQueryFlag::eDYNAMIC)))
return false;
PxRigidDynamic* pickedActor = buffer.getAnyHit(0).actor->is<PxRigidDynamic>();
dist = buffer.getAnyHit(0).distance;
//mPickActor = mActors[actorNr]->mCompounds[compoundNr]->getPxActor();
mPickPos = orig + dir * dist;
mPickActor = PxGetPhysics().createRigidDynamic(PxTransform(mPickPos));
mPickActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
getScene()->addActor(*mPickActor);
mPickLocalPos = PxVec3(0.f);
mPickJoint = PxD6JointCreate(PxGetPhysics(), mPickActor, PxTransform(PxIdentity), pickedActor, PxTransform(pickedActor->getGlobalPose().transformInv(mPickPos)));
mPickJoint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
mPickJoint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
mPickJoint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
mPickDepth = dist;
return true;
}
//-----------------------------------------------------------------------------
void SimScene::pickMove(const PxVec3 &orig, const PxVec3 &dir)
{
if (mPickActor == NULL)
return;
mPickPos = orig + dir * mPickDepth;
mPickActor->setKinematicTarget(PxTransform(mPickPos));
}
//-----------------------------------------------------------------------------
void SimScene::pickRelease()
{
if (mPickJoint)
mPickJoint->release();
mPickJoint = NULL;
if (mPickActor)
mPickActor->release();
mPickActor = NULL;
}
bool SimScene::findCompound(const Compound* c, int& actorNr, int& compoundNr)
{
actorNr = -1;
compoundNr = -1;
for(int i = 0; i < (int)mActors.size(); i++)
{
if (mActors[i]->findCompound(c,compoundNr))
{
actorNr = i;
return true;
}
}
return false;
}
// --------------------------------------------------------------------------------------------
// CPU
void SimScene::onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs)
{
// Pass along to application's callback, if defined
if (mAppNotify != NULL)
{
mAppNotify->onContact(pairHeader, pairs, nbPairs);
}
}
shdfnd::Array<PxVec3>& SimScene::getDebugPoints() {
return debugPoints;
}
bool SimScene::mapShapeToConvex(const PxShape& shape, Convex& convex)
{
return mShapeMap.insert(&shape, &convex);
}
bool SimScene::unmapShape(const PxShape& shape)
{
return mShapeMap.erase(&shape);
}
Convex* SimScene::findConvexForShape(const PxShape& shape)
{
const physx::shdfnd::HashMap<const PxShape*, Convex*>::Entry* entry = mShapeMap.find(&shape);
return entry != NULL ? entry->second : NULL; // Since we don't expect *entry to be NULL, we shouldn't lose information here
}
}
}
}
#endif

View File

@ -0,0 +1,275 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef SIM_SCENE_BASE
#define SIM_SCENE_BASE
#include "PxSimulationEventCallback.h"
#include <PsArray.h>
#include <PsUserAllocated.h>
#include "PsHashMap.h"
#include "RTdef.h"
namespace physx
{
class PxPhysics;
class PxCooking;
class PxScene;
class PxRigidDynamic;
class PxD6Joint;
namespace fracture
{
namespace base
{
class Actor;
class Compound;
class Convex;
class FracturePattern;
class CompoundCreator;
class Delaunay2d;
class Delaunay3d;
class PolygonTriangulator;
// -----------------------------------------------------------------------------------
class SimScene :
public PxSimulationEventCallback, public ::physx::shdfnd::UserAllocated
{
friend class Actor;
public:
static SimScene* createSimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath);
protected:
SimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath);
public:
virtual ~SimScene();
// Creates Scene Level Singletons
virtual void createSingletons();
// Access singletons
CompoundCreator* getCompoundCreator() {return mCompoundCreator;}
PolygonTriangulator* getPolygonTriangulator() {return mPolygonTriangulator;}
// Create non-Singletons
virtual Actor* createActor();
virtual Convex* createConvex();
virtual Compound* createCompound(const FracturePattern *pattern, const FracturePattern *secondaryPattern = NULL, PxReal contactOffset = 0.005f, PxReal restOffset = -0.001f);
virtual void clear();
void addCompound(Compound *m);
void removeCompound(Compound *m);
// perform deferred deletion
void deleteCompounds();
void setScene(PxScene* scene) { mScene = scene; }
//
bool findCompound(const Compound* c, int& actorNr, int& compoundNr);
void removeActor(Actor* a);
// Profiler hooks
virtual void profileBegin(const char* /*name*/) {}
virtual void profileEnd(const char* /*name*/) {}
virtual void playSound(const char * /*name*/, int /*nr*/ = -1) {}
// accessors
shdfnd::Array<Compound*> getCompounds(); //{ return mCompounds; }
shdfnd::Array<Actor*> getActors() { return mActors; }
PxPhysics* getPxPhysics() { return mPxPhysics; }
PxCooking* getPxCooking() { return mPxCooking; }
PxScene* getScene() { return mScene; }
//ConvexRenderer &getConvexRenderer() { return mConvexRenderer; }
void preSim(float dt);
void postSim(float dt); //, RegularCell3D* fluidSim);
void setPlaySounds(bool play) { mPlaySounds = play; }
void setContactImpactRadius(float radius) { mContactImpactRadius = radius; }
void setNumNoFractureFrames(int num) { mNumNoFractureFrames = num; }
void setCamera(const PxVec3 &pos, const PxVec3 &dir, const PxVec3 &up, float fov ) {
mCameraPos = pos; mCameraDir = dir; mCameraUp = up; mCameraFov = fov;
}
//void draw(bool useShader, Shader* particleShader = NULL) {}
//void setShaderMaterial(Shader* shader, const ShaderMaterial& mat) {this->mShader = shader; this->mShaderMat = mat;}
//void setFractureForceThreshold(float threshold) { mFractureForceThreshold = threshold; }
PxMaterial *getPxDefaultMaterial() { return mPxDefaultMaterial; }
void toggleDebugDrawing() { mDebugDraw = !mDebugDraw; }
virtual bool pickStart(const PxVec3 &orig, const PxVec3 &dir);
virtual void pickMove(const PxVec3 &orig, const PxVec3 &dir);
virtual void pickRelease();
PxRigidDynamic* getPickActor() { return mPickActor; }
const PxVec3 &getPickPos() { return mPickPos; }
const PxVec3 &getPickLocalPos() { return mPickLocalPos; }
// callback interface
void onContactNotify(unsigned int arraySizes, void ** shape0Array, void ** shape1Array, void ** actor0Array, void ** actor1Array, float * positionArray, float * normalArray);
void onConstraintBreak(PxConstraintInfo* constraints, PxU32 count) { PX_UNUSED((constraints, count)); }
void onWake(PxActor** actors, PxU32 count) { PX_UNUSED((actors, count)); }
void onSleep(PxActor** actors, PxU32 count) { PX_UNUSED((actors, count)); }
void onTrigger(PxTriggerPair* pairs, PxU32 count) { PX_UNUSED((pairs, count)); }
void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs);
void onAdvance(const PxRigidBody*const* bodyBuffer, const PxTransform* poseBuffer, const PxU32 count) { PX_UNUSED(bodyBuffer); PX_UNUSED(poseBuffer); PX_UNUSED(count); }
void toggleRenderDebris() {mRenderDebris = !mRenderDebris;}
bool getRenderDebrs() {return mRenderDebris;}
//virtual void dumpSceneGeometry() {}
shdfnd::Array<PxVec3>& getDebugPoints();
//virtual void createRenderBuffers() {}
//void loadAndCreateTextureArrays();
shdfnd::Array<PxVec3>& getCrackNormals() {return crackNormals;}
shdfnd::Array<PxVec3>& getTmpPoints() {return tmpPoints;}
bool mapShapeToConvex(const PxShape& shape, Convex& convex);
bool unmapShape(const PxShape& shape);
Convex* findConvexForShape(const PxShape& shape);
bool owns(const PxShape& shape) {return NULL != findConvexForShape(shape);}
protected:
//virtual void create3dTexture() {}
//virtual void updateConvexesTex() {}
//void playShatterSound(float objectSize);
void addActor(Actor* a); // done internally upon creation
PxPhysics *mPxPhysics;
PxCooking *mPxCooking;
PxScene *mScene;
const char *mResourcePath;
bool mPlaySounds;
//shdfnd::Array<Compound*> mCompounds;
shdfnd::Array<Actor*> mActors;
float mFractureForceThreshold;
float mContactImpactRadius;
shdfnd::Array<PxContactPairPoint> mContactPoints;
struct FractureEvent {
void init() {
compound = NULL;
pos = normal = PxVec3(0.0f, 0.0f, 0.0f);
additionalRadialImpulse = additionalNormalImpulse = 0.0f;
withStatic = false;
}
Compound *compound;
PxVec3 pos;
PxVec3 normal;
float additionalRadialImpulse;
float additionalNormalImpulse;
bool withStatic;
};
struct RenderBuffers {
void init() {
numVertices = 0; numIndices = 0;
VBO = 0; IBO = 0; matTex = 0; volTex = 0;
texSize = 0; numConvexes = -1;
}
shdfnd::Array<float> tmpVertices;
shdfnd::Array<unsigned int> tmpIndices;
shdfnd::Array<float> tmpTexCoords;
int numVertices, numIndices;
unsigned int VBO;
unsigned int IBO;
unsigned int volTex;
unsigned int matTex;
int texSize;
int numConvexes;
};
RenderBuffers mRenderBuffers;
unsigned int mSceneVersion; // changed on each update
unsigned int mRenderBufferVersion; // to handle updates
unsigned int mOptixBufferVersion; // to handle updates
PxMaterial *mPxDefaultMaterial;
//ConvexRenderer mConvexRenderer;
int mNoFractureFrames;
int mNoSoundFrames;
int mFrameNr;
bool mDebugDraw;
float mPickDepth;
PxRigidDynamic *mPickActor;
PxD6Joint* mPickJoint;
PxVec3 mPickPos;
PxVec3 mPickLocalPos;
float mMinConvexSize;
int mNumNoFractureFrames; // > 1 to prevent a slow down by too many fracture events
PxVec3 mCameraPos, mCameraDir, mCameraUp;
float mCameraFov;
float bumpTextureUVScale;
float extraNoiseScale;
float roughnessScale;
float particleBumpTextureUVScale;
float particleRoughnessScale;
float particleExtraNoiseScale;
shdfnd::Array<PxVec3> debugPoints;
bool mRenderDebris;
PxSimulationEventCallback* mAppNotify;
//GLuint diffuseTexArray, bumpTexArray, specularTexArray, emissiveReflectSpecPowerTexArray;
//GLuint loadTextureArray(std::vector<std::string>& names);
//Singletons
CompoundCreator* mCompoundCreator;
PolygonTriangulator* mPolygonTriangulator;
//Array for use by Compound (effectively static)
shdfnd::Array<PxVec3> crackNormals;
shdfnd::Array<PxVec3> tmpPoints;
// Deferred Deletion list
shdfnd::Array<Compound*> delCompoundList;
// Map used to determine SimScene ownership of shape
shdfnd::HashMap<const PxShape*,Convex*> mShapeMap;
};
}
}
}
#endif
#endif

View File

@ -0,0 +1,192 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include <foundation/PxBounds3.h>
#include "Mesh.h"
#include <algorithm>
#include <iostream>
// -------------------------------------------------------------------
struct SimpleVertexRef {
int vert, normal, texCoord;
int indexNr, subMeshNr;
bool operator < (const SimpleVertexRef &r) const {
if (vert < r.vert) return true;
if (vert > r.vert) return false;
if (normal < r.normal) return true;
if (normal > r.normal) return false;
return texCoord < r.texCoord;
}
bool operator == (const SimpleVertexRef &r) const {
return vert == r.vert && normal == r.normal && texCoord == r.texCoord;
}
void parse(char *s, int indexNr) {
int nr[3] = {0,0,0};
char *p = s;
for (int i = 0; i < 3; i++) {
while (*p != 0 && *p != '/') p++;
bool end = (*p == 0);
*p = 0;
sscanf_s(s, "%i", &nr[i]);
if (end) break;
p++; s = p;
}
vert = nr[0]-1; texCoord = nr[1]-1; normal = nr[2]-1;
this->indexNr = indexNr;
}
};
#define OBJ_STR_LEN 256
// -------------------------------------------------------------------
bool Mesh::loadFromObjFile(const std::string &filename)
{
const int maxVertsPerFace = 8;
char s[OBJ_STR_LEN], ps[maxVertsPerFace][OBJ_STR_LEN], sub[OBJ_STR_LEN];
int matNr = -1;
PxVec3 p;
float u,v;
shdfnd::Array<SimpleVertexRef> refs;
SimpleVertexRef ref[maxVertsPerFace];
shdfnd::Array<PxVec3> vertices;
shdfnd::Array<PxVec3> normals;
shdfnd::Array<float> texCoords;
int numIndices = 0;
mSubMeshes.resize(1);
mNames.resize(1);
mSubMeshes[0].init();
mNames[0] = "";
mSubMeshes[0].firstIndex = 0;
FILE *f;
if (fopen_s(&f, filename.c_str(), "r") != 0) {
std::cerr << "Could not load OBJ file: " << filename << std::endl;
return false;
}
// first a vertex ref is generated for each v/n/t combination
while (!feof(f)) {
if (fgets(s, OBJ_STR_LEN, f) == NULL) break;
if (strncmp(s, "usemtl", 6) == 0 || strncmp(s, "g ", 2) == 0) { // new group
bool isGroup = strncmp(s, "g ", 2) == 0;
if (isGroup)
strcpy(sub, &s[2]);
else
strcpy(sub, &s[6]);
int numSubs = mSubMeshes.size();
if (mSubMeshes[numSubs-1].numIndices > 0) {
mSubMeshes.resize(numSubs+1);
mNames.resize(numSubs+1);
mSubMeshes[numSubs].init();
mNames[numSubs] = "";
mSubMeshes[numSubs].firstIndex = mIndices.size();
}
int subNr = mSubMeshes.size() - 1;
if (mNames[subNr] == "" || isGroup)
mNames[subNr] = std::string(sub);
}
else if (strncmp(s, "v ", 2) == 0) { // vertex
sscanf_s(s, "v %f %f %f", &p.x, &p.y, &p.z);
vertices.pushBack(p);
}
else if (strncmp(s, "vn ", 3) == 0) { // normal
sscanf_s(s, "vn %f %f %f", &p.x, &p.y, &p.z);
normals.pushBack(p);
}
else if (strncmp(s, "vt ", 3) == 0) { // texture coords
sscanf_s(s, "vt %f %f", &u, &v);
texCoords.pushBack(u);
texCoords.pushBack(v);
}
else if (strncmp(s, "f ", 2) == 0) { // face, tri or quad
int nr;
nr = sscanf_s(s, "f %s %s %s %s %s %s",
ps[0], OBJ_STR_LEN, ps[1], OBJ_STR_LEN, ps[2], OBJ_STR_LEN, ps[3], OBJ_STR_LEN,
ps[4], OBJ_STR_LEN, ps[5], OBJ_STR_LEN, ps[6], OBJ_STR_LEN, ps[7], OBJ_STR_LEN);
if (nr >= 3) {
for (int i = 0; i < nr; i++)
ref[i].parse(ps[i], 0);
for (int i = 1; i < nr-1; i++) {
ref[0].indexNr = numIndices++; refs.pushBack(ref[0]); mIndices.pushBack(0);
ref[i].indexNr = numIndices++; refs.pushBack(ref[i]); mIndices.pushBack(0);
ref[i+1].indexNr = numIndices++; refs.pushBack(ref[i+1]); mIndices.pushBack(0);
mSubMeshes[mSubMeshes.size()-1].numIndices += 3;
}
}
}
}
fclose(f);
// now we merge multiple v/n/t triplets
std::sort(refs.begin(), refs.end());
int i = 0;
PxVec3 defNormal(1.0f, 0.0f, 0.0f);
bool normalsOK = true;
bool mTextured = true;
int numTexCoords = texCoords.size();
int baseVertNr = 0;
while (i < (int)refs.size()) {
int vertNr = mVertices.size();
SimpleVertexRef &r = refs[i];
mVertices.pushBack(vertices[r.vert]);
if (r.normal >= 0) mNormals.pushBack(normals[r.normal]);
else { mNormals.pushBack(defNormal); normalsOK = false; }
if (r.texCoord >= 0 && r.texCoord < numTexCoords) {
//mTexCoords.pushBack(texCoords[2*r.texCoord]);
//mTexCoords.pushBack(texCoords[2*r.texCoord+1]);
mTexCoords.pushBack(PxVec2(texCoords[2*r.texCoord],texCoords[2*r.texCoord+1]));
}
else {
//mTexCoords.pushBack(0.0f);
//mTexCoords.pushBack(0.0f);
mTexCoords.pushBack(PxVec2(0.0f,0.0f));
}
mIndices[r.indexNr] = vertNr;
i++;
while (i < (int)refs.size() && r == refs[i]) {
mIndices[refs[i].indexNr] = vertNr;
i++;
}
}
if (!normalsOK)
updateNormals();
return true;
}

View File

@ -0,0 +1,59 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef MESH
#define MESH
#include <foundation/PxVec3.h>
#include <PsArray.h>
#include <PsAllocator.h>
#include "Shader.h"
#include "MeshBase.h"
using namespace physx::fracture;
class Mesh : public base::Mesh
{
public:
bool loadFromObjFile(const std::string &filename);
void setShader(Shader* shader, const ShaderMaterial &mat) { mShader = shader; mShaderMat = mat; }
Shader* getShader() const { return mShader; }
const ShaderMaterial& getShaderMat() { return mShaderMat; }
void draw(bool useShader);
protected:
// shading
Shader *mShader;
ShaderMaterial mShaderMat;
Shader *mWrinkleShader;
shdfnd::Array<std::string> mNames;
};
#endif

View File

@ -0,0 +1,31 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "PolygonTriangulator.h"
#include <assert.h>
// Empty until base has code proven to be non-portable

View File

@ -0,0 +1,49 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#ifndef POLYGON_TRIANGULATOR_H
#define POLYGON_TRIANGULATOR_H
#include <foundation/PxVec3.h>
#include <PsArray.h>
using namespace physx;
#include <math.h>
#include "PolygonTriangulatorBase.h"
using namespace physx::fracture;
class PolygonTriangulator : public base::PolygonTriangulator
{
friend class SimScene;
protected:
PolygonTriangulator(SimScene* scene): base::PolygonTriangulator((base::SimScene*)scene) {}
};
#endif

View File

@ -0,0 +1,35 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
// This file exists primarily for APEX integration
#ifndef RT_DEF_H
#define RT_DEF_H
#define RT_COMPILE 1
#define NO_IMPACT_FRACTURE 0
#endif

View File

@ -0,0 +1,736 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "SimScene.h"
#include <foundation/PxMat44.h>
#include "PxRigidBodyExt.h"
#include "Actor.h"
#include "Compound.h"
#include "Convex.h"
#include "CompoundCreator.h"
#include "PolygonTriangulator.h"
#include "SampleViewerScene.h"
#include <windows.h>
#include <iostream>
using namespace std;
#include <vector>
#include "TerrainMesh.h"
#define USE_CONVEX_RENDERER 1
#define NUM_NO_SOUND_FRAMES 1
//#define REL_VEL_FRACTURE_THRESHOLD 5.0f
#define REL_VEL_FRACTURE_THRESHOLD 0.1f
//extern std::vector<Compound*> delCompoundList;
SimScene* SimScene::createSimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath)
{
SimScene* s = PX_NEW(SimScene)(pxPhysics,pxCooking,isGrbScene,minConvexSize,defaultMat,resourcePath);
s->createSingletons();
return s;
}
void SimScene::createSingletons()
{
mCompoundCreator = PX_NEW(CompoundCreator)(this);
mPolygonTriangulator = PX_NEW(PolygonTriangulator)(this);
addActor(createActor());
}
base::Actor* SimScene::createActor()
{
return (base::Actor*)PX_NEW(Actor)(this);
}
base::Convex* SimScene::createConvex()
{
return (base::Convex*)PX_NEW(Convex)(this);
}
base::Compound* SimScene::createCompound(PxReal contactOffset, PxReal restOffset)
{
return (base::Compound*)PX_NEW(Compound)(this, contactOffset, restOffset);
}
SimScene::SimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath):
base::SimScene(pxPhysics,pxCooking,isGrbScene,minConvexSize,defaultMat,resourcePath)
{
//mParticles = NULL;
diffuseTexArray = 0;
bumpTexArray = 0;
specularTexArray = 0;
emissiveReflectSpecPowerTexArray = 0;
create3dTexture();
}
// --------------------------------------------------------------------------------------------
SimScene::~SimScene()
{
mShader = NULL;
mShaderMat.init();
if (mRenderBuffers.volTex) glDeleteTextures(1, &mRenderBuffers.volTex);
if (mRenderBuffers.VBO) glDeleteBuffersARB(1, &mRenderBuffers.VBO);
if (mRenderBuffers.IBO) glDeleteBuffersARB(1, &mRenderBuffers.IBO);
if (mRenderBuffers.matTex) glDeleteTextures(1, &mRenderBuffers.matTex);
}
// --------------------------------------------------------------------------------------------
void SimScene::clear()
{
base::SimScene::clear();
}
// --------------------------------------------------------------------------------------------
void SimScene::postSim(float dt, RegularCell3D* fluidSim)
{
for (int i = 0; i < mActors.size(); i++)
{
mActors[i]->postSim(dt);
}
mFrameNr++;
mNoFractureFrames--;
mNoSoundFrames--;
}
void SimScene::profileBegin(const char* name)
{
}
void SimScene::profileEnd(const char* name)
{
}
// ------------------------- Renderering --------------------------------
GLuint SimScene::loadTextureArray(std::vector<std::string>& names) {
GLuint texid;
glGenTextures(1, &texid);
glBindTexture( GL_TEXTURE_2D_ARRAY_EXT, texid);
glTexParameteri( GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri( GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri( GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri( GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri( GL_TEXTURE_2D_ARRAY_EXT, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
class BmpLoaderBuffer : public ::BmpLoaderBuffer, public ::physx::shdfnd::UserAllocated {};
BmpLoaderBuffer *bmps;
bmps = PX_NEW(BmpLoaderBuffer)[names.size()];
char path[512];
int w = 0, h = 0, d = 0;
for (int i = 0; i < (int)names.size(); i++) {
if (names[i].size() > 0) {
sprintf_s(path, 512, "%s", names[i].c_str());
int len = strlen(path);
int mw = 0, mh = 0;
if (strcmp(&path[len-4], ".jpg") == 0) {
printf("Can't load %s, jpg no longer supported\n", path);
} else {
bmps[i].loadFile(path);
mw = bmps[i].mWidth;
mh = bmps[i].mHeight;
}
if ((mw != 0) && (mh != 0)) {
if ( ((w != 0) && (w != mw)) ||
((h != 0) && (h != mh)) ) {
printf("Textures in array need to be same size!\n");
}
w = mw;
h = mh;
}
}
}
d = names.size();
if (w == 0) {
w=h=128;
}
unsigned char* tmpBlack = (unsigned char*)PX_ALLOC(sizeof(unsigned char)*w*h*3,PX_DEBUG_EXP("RT_FRACTURE"));
memset(tmpBlack, 0, w*h*3);
glTexImage3D(GL_TEXTURE_2D_ARRAY_EXT, 0, GL_RGB8, w, h, d, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
for (int i = 0; i < (int)names.size(); i++) {
glTexSubImage3D( GL_TEXTURE_2D_ARRAY_EXT, 0, 0, 0, i, w, h, 1, GL_RGB, GL_UNSIGNED_BYTE, (bmps[i].mRGB) ? bmps[i].mRGB :tmpBlack
);
}
glGenerateMipmapEXT(GL_TEXTURE_2D_ARRAY_EXT);
PX_FREE(tmpBlack);
PX_DELETE_ARRAY(bmps);
/* names
// 2D Texture arrays a loaded just like 3D textures
glTexImage3D(GL_TEXTURE_2D_ARRAY_EXT, 0, GL_RGBA8, images[0].getWidth(), images[0].getHeight(), NIMAGES, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
for (int i = 0; i < NIMAGES; i++) {
glTexSubImage3D( GL_TEXTURE_2D_ARRAY_EXT, 0, 0, 0, i, images[i].getWidth(), images[i].getHeight(), 1, images[i].getFormat(), images[i].getType(), images[i].getLevel(0));
}
*/
return texid;
}
void SimScene::loadAndCreateTextureArrays() {
diffuseTexArray = loadTextureArray(diffuseTexNames);
bumpTexArray = loadTextureArray(bumpTexNames);
specularTexArray = loadTextureArray(specularTexNames);
emissiveReflectSpecPowerTexArray = loadTextureArray(emissiveReflectSpecPowerTexNames);
}
// --------------------------------------------------------------------------------------------
#define WIDTH 128
#define HEIGHT 128
#define DEPTH 128
#define BYTES_PER_TEXEL 3
#define LAYER(r) (WIDTH * HEIGHT * r * BYTES_PER_TEXEL)
// 2->1 dimension mapping function
#define TEXEL2(s, t) (BYTES_PER_TEXEL * (s * WIDTH + t))
// 3->1 dimension mapping function
#define TEXEL3(s, t, r) (TEXEL2(s, t) + LAYER(r))
// --------------------------------------------------------------------------------------------
void SimScene::create3dTexture()
{
unsigned char *texels = (unsigned char *)malloc(WIDTH * HEIGHT * DEPTH * BYTES_PER_TEXEL);
memset(texels, 0, WIDTH*HEIGHT*DEPTH);
// each of the following loops defines one layer of our 3d texture, there are 3 unsigned bytes (red, green, blue) for each texel so each iteration sets 3 bytes
// the memory pointed to by texels is technically a single dimension (C++ won't allow more than one dimension to be of variable length), the
// work around is to use a mapping function like the one above that maps the 3 coordinates onto one dimension
// layer 0 occupies the first (width * height * bytes per texel) bytes, followed by layer 1, etc...
// define layer 0 as red
// Perlin perlin(8,4,1,91114);
unsigned char* tt = texels;
float idx = 1.0f / DEPTH;
for (int i = 0; i < DEPTH; i++) {
for (int j = 0; j < HEIGHT; j++) {
for (int k = 0; k < WIDTH; k++) {
//float v[3] = {i*idx, j*idx, k*idx};
//float val = (perlin.noise3(v)*0.5f + 0.5f)*255.0f;//cos( (perlin.Noise3(i*0.01f,j*0.01f,k*0.01f)*255000 + i*0.)*5.0f)*0.5f+0.5f;//perlin.Noise3(k,j,i)*255.0f;
//(cos(perlin.Noise3(k,j,i) + j*0.01f) + 1.0f)*0.5f*255;
unsigned char val = rand() % 255;
tt[0] = val;
tt[1] = val;
tt[2] = val;
tt+=3;
}
}
}
// request 1 texture name from OpenGL
glGenTextures(1, &mRenderBuffers.volTex);
// tell OpenGL we're going to be setting up the texture name it gave us
glBindTexture(GL_TEXTURE_3D, mRenderBuffers.volTex);
// when this texture needs to be shrunk to fit on small polygons, use linear interpolation of the texels to determine the color
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// when this texture needs to be magnified to fit on a big polygon, use linear interpolation of the texels to determine the color
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// we want the texture to repeat over the S axis, so if we specify coordinates out of range we still get textured.
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
// same as above for T axis
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// same as above for R axis
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
// this is a 3d texture, level 0 (max detail), GL should store it in RGB8 format, its WIDTHxHEIGHTxDEPTH in size,
// it doesnt have a border, we're giving it to GL in RGB format as a series of unsigned bytes, and texels is where the texel data is.
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB8, WIDTH, HEIGHT, DEPTH, 0, GL_RGB, GL_UNSIGNED_BYTE, texels);
glBindTexture(GL_TEXTURE_3D, 0);
}
// --------------------------------------------------------------------------------------------
void SimScene::createRenderBuffers()
{
if (!mRenderBuffers.VBO) {
glGenBuffersARB(1, &mRenderBuffers.VBO);
}
if (!mRenderBuffers.IBO) {
glGenBuffersARB(1, &mRenderBuffers.IBO);
}
if (!mRenderBuffers.matTex) {
glGenTextures(1, &mRenderBuffers.matTex);
glBindTexture(GL_TEXTURE_2D, mRenderBuffers.matTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glBindTexture(GL_TEXTURE_2D, 0);
}
// Count number of vertices and indices in convexes
// Count number of indices in convexes
mRenderBuffers.numConvexes = 0;
mRenderBuffers.numVertices = 0;
mRenderBuffers.numIndices = 0;
for (int k = 0; k < (int)mActors.size(); k++)
{
const shdfnd::Array<base::Compound*>& mCompounds = mActors[k]->getCompounds();
for (int i = 0; i < (int)mCompounds.size(); i++) {
if (((Compound*)mCompounds[i])->getShader() != mShader)
continue;
const shdfnd::Array<base::Convex*> &convexes = mCompounds[i]->getConvexes();
mRenderBuffers.numConvexes += convexes.size();
for (int j = 0; j < (int)convexes.size(); j++) {
mRenderBuffers.numVertices += convexes[j]->getVisVertices().size();
mRenderBuffers.numIndices += convexes[j]->getVisTriIndices().size();
}
}
}
if (mRenderBuffers.numVertices == 0 || mRenderBuffers.numIndices == 0)
return;
mRenderBuffers.tmpVertices.resize(mRenderBuffers.numVertices*12);
mRenderBuffers.tmpIndices.resize(mRenderBuffers.numIndices);
float* vp = &mRenderBuffers.tmpVertices[0];
unsigned int* ip = &mRenderBuffers.tmpIndices[0];
int sumV = 0;
// Make cpu copy of VBO and IBO
int convexNr = 0;
for (int k = 0; k < (int)mActors.size(); k++)
{
const shdfnd::Array<base::Compound*>& mCompounds = mActors[k]->getCompounds();
for (int i = 0; i < (int)mCompounds.size(); i++) {
if (((Compound*)mCompounds[i])->getShader() != mShader)
continue;
const shdfnd::Array<base::Convex*> &convexes = mCompounds[i]->getConvexes();
for (int j = 0; j < (int)convexes.size(); j++, convexNr++) {
Convex* c = (Convex*)convexes[j];
// PxVec3 matOff = c->getMaterialOffset();
int nv = c->getVisVertices().size();
int ni = c->getVisTriIndices().size();
if (nv > 0) {
float* cvp = (float*)&c->getVisVertices()[0]; // float3
float* cnp = (float*)&c->getVisNormals()[0]; // float3
// float* c3dtp = (float*)&c->getVisVertices()[0]; // float3
float* c2dtp = (float*)&c->getVisTexCoords()[0]; // float2
float* ctanp = (float*)&c->getVisTangents()[0]; // float3
int* cip = (int*)&c->getVisTriIndices()[0];
for (int k = 0; k < nv; k++) {
*(vp++) = *(cvp++);
*(vp++) = *(cvp++);
*(vp++) = *(cvp++);
*(vp++) = *(cnp++);
*(vp++) = *(cnp++);
*(vp++) = *(cnp++);
*(vp++) = *(ctanp++);
*(vp++) = *(ctanp++);
*(vp++) = *(ctanp++);
*(vp++) = (float)convexNr;
*(vp++) = *(c2dtp++);
*(vp++) = *(c2dtp++);
}
for (int k = 0; k < ni; k++) {
*(ip++) = *(cip++) + sumV;
}
}
//memcpy(ip, cip, sizeof(int)*ni);
//ip += 3*ni;
//std::vector<PxVec3> mTriVertices;
//std::vector<PxVec3> mTriNormals;
//std::vector<int> mTriIndices;
//std::vector<float> mTriTexCoords; // 3d + obj nr
sumV += nv;
}
}
}
glBindBufferARB(GL_ARRAY_BUFFER_ARB, mRenderBuffers.VBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, mRenderBuffers.tmpVertices.size()*sizeof(float), &mRenderBuffers.tmpVertices[0], GL_STATIC_DRAW);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mRenderBuffers.IBO);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mRenderBuffers.tmpIndices.size()*sizeof(unsigned int), &mRenderBuffers.tmpIndices[0], GL_STATIC_DRAW);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
int oldTexSize = mRenderBuffers.texSize;
if (mRenderBuffers.texSize == 0) {
// First time
oldTexSize = 1;
mRenderBuffers.texSize = 32;
}
while (1) {
int convexesPerRow = mRenderBuffers.texSize / 4;
if (convexesPerRow * mRenderBuffers.texSize >= mRenderBuffers.numConvexes) {
break;
} else {
mRenderBuffers.texSize *= 2;
}
}
if (mRenderBuffers.texSize != oldTexSize) {
mRenderBuffers.tmpTexCoords.resize(mRenderBuffers.texSize*mRenderBuffers.texSize*4);
// Let's allocate texture
glBindTexture(GL_TEXTURE_2D, mRenderBuffers.matTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, mRenderBuffers.texSize, mRenderBuffers.texSize, 0, GL_RGBA, GL_FLOAT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
mRenderBufferVersion = mSceneVersion;
//instanceVBOCPU.resize( newSize * 16);
}
// --------------------------------------------------------------------------------------------
void SimScene::updateConvexesTex()
{
float* tt = &mRenderBuffers.tmpTexCoords[0];
for (int k = 0; k < (int)mActors.size(); k++)
{
const shdfnd::Array<base::Compound*>& mCompounds = mActors[k]->getCompounds();
for (int i = 0; i < (int)mCompounds.size(); i++) {
if ( ((Compound*)mCompounds[i])->getShader() != mShader)
continue;
const shdfnd::Array<base::Convex*> &convexes = mCompounds[i]->getConvexes();
for (int j = 0; j < (int)convexes.size(); j++) {
Convex* c = (Convex*)convexes[j];
PxMat44 pose(convexes[j]->getGlobalPose());
float* mp = (float*)pose.front();
float* ta = tt;
for (int k = 0; k < 16; k++) {
*(tt++) = *(mp++);
}
PxVec3 matOff = c->getMaterialOffset();
ta[3] = matOff.x;
ta[7] = matOff.y;
ta[11] = matOff.z;
int idFor2DTex = c->getSurfaceMaterialId();
int idFor3DTex = 0;
const int MAX_3D_TEX = 8;
ta[15] = (float)(idFor2DTex*MAX_3D_TEX + idFor3DTex);
}
}
}
glBindTexture(GL_TEXTURE_2D, mRenderBuffers.matTex);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mRenderBuffers.texSize, mRenderBuffers.texSize,
GL_RGBA, GL_FLOAT, &mRenderBuffers.tmpTexCoords[0]);
glBindTexture(GL_TEXTURE_2D, 0);
}
// --------------------------------------------------------------------------------------------
#ifdef USE_OPTIX
// Updater class for Optix renderer.
class FractureModelUpdate : public optix_demo::IModelUpdate
{
public:
FractureModelUpdate( shdfnd::Array< Compound* > const& compounds, bool complete_update )
: m_compounds(compounds), m_is_complete_update( complete_update )
{}
bool isCompleteUpdate() const {return m_is_complete_update;}
void to_first();
void to_next();
bool at_end() const;
size_t num_vertices() const {return (*m_iconvex)->getVisVertices().size();}
size_t num_indices() const {return (*m_iconvex)->getVisTriIndices().size();}
float const* vertices() const {return &(*m_iconvex)->getVisVertices()[0].x;}
float const* normals() const {return &(*m_iconvex)->getVisNormals()[0].x;}
int const* indices() const {return &(*m_iconvex)->getVisTriIndices()[0];}
void global_transform( float* rmat3x3, float* translation );
private:
void advance();
bool is_valid_convex( Convex const* c ) const
{
return !c->getVisVertices().empty();
}
shdfnd::Array< Compound* > const& m_compounds;
bool m_is_complete_update;
shdfnd::Array< Compound* >::ConstIterator m_icompound;
shdfnd::Array< Convex* >::ConstIterator m_iconvex;
};
void FractureModelUpdate::to_first()
{
m_icompound = m_compounds.begin();
if (m_icompound == m_compounds.end()) return;
while ((*m_icompound)->getConvexes().empty()) {
++m_icompound;
if (m_icompound == m_compounds.end()) return;
}
m_iconvex = (*m_icompound)->getConvexes().begin();
while (!is_valid_convex(*m_iconvex)) {
advance();
if (m_icompound == m_compounds.end()) return;
}
}
void FractureModelUpdate::to_next()
{
if (m_icompound != m_compounds.end()) {
do {
advance();
} while (m_icompound != m_compounds.end() && !is_valid_convex(*m_iconvex));
}
}
void FractureModelUpdate::advance()
{
if (m_iconvex != (*m_icompound)->getConvexes().end()) {
++m_iconvex;
}
if (m_iconvex == (*m_icompound)->getConvexes().end()) {
// End of convexes of this compound.
do {
++m_icompound;
if (m_icompound == m_compounds.end()) return;
} while ((*m_icompound)->getConvexes().empty());
m_iconvex = (*m_icompound)->getConvexes().begin();
}
}
bool FractureModelUpdate::at_end() const
{
return m_icompound == m_compounds.end();
}
void FractureModelUpdate::global_transform( float* rmat3x3, float* translation )
{
PxTransform pose = (*m_iconvex)->getGlobalPose();
PxMat33 rot(pose.q);
rmat3x3[0] = rot.column0.x; rmat3x3[1] = rot.column1.x; rmat3x3[2] = rot.column2.x;
rmat3x3[3] = rot.column0.y; rmat3x3[4] = rot.column1.y; rmat3x3[5] = rot.column2.y;
rmat3x3[6] = rot.column0.z; rmat3x3[7] = rot.column1.z; rmat3x3[8] = rot.column2.z;
translation[0] = pose.p.x;
translation[1] = pose.p.y;
translation[2] = pose.p.z;
}
#endif //USE_OPTIX
extern bool gConvexTexOutdate;
// --------------------------------------------------------------------------------------------
void SimScene::draw(bool useShader)
{
if (mDebugDraw) {
for (int k = 0; k < (int)mActors.size(); k++)
{
const shdfnd::Array<base::Compound*>& mCompounds = mActors[k]->getCompounds();
for (int i = 0; i < (int)mCompounds.size(); i++)
mCompounds[i]->draw(false, true);
}
return;
}
int numCompounds = 0;
for (int k = 0; k < (int)mActors.size(); k++)
{
const shdfnd::Array<base::Compound*>& mCompounds = mActors[k]->getCompounds();
numCompounds += mCompounds.size();
}
if (numCompounds == 0) return;
if (SampleViewerScene::getRenderType() == SampleViewerScene::rtOPENGL) {
#if USE_CONVEX_RENDERER
mConvexRenderer.setShaderMaterial(mShader, mShaderMat);
mConvexRenderer.setTexArrays(diffuseTexArray, bumpTexArray,
specularTexArray, emissiveReflectSpecPowerTexArray);
mConvexRenderer.setVolTex(mRenderBuffers.volTex);
mConvexRenderer.render();
#else
mConvexRenderer.setActive(false);
if (mRenderBufferVersion != mSceneVersion)
createRenderBuffers();
if (mRenderBuffers.numIndices > 0) {
if (gConvexTexOutdate) {
updateConvexesTex();
gConvexTexOutdate = false;
}
mShader->activate(mShaderMat);
// Assume convex all use the same shader
glActiveTexture(GL_TEXTURE7);
glBindTexture(GL_TEXTURE_3D, mRenderBuffers.volTex);
glActiveTexture(GL_TEXTURE8);
glBindTexture(GL_TEXTURE_2D, mRenderBuffers.matTex);
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, diffuseTexArray);
glActiveTexture(GL_TEXTURE11);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, bumpTexArray);
glActiveTexture(GL_TEXTURE12);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, specularTexArray);
glActiveTexture(GL_TEXTURE13);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, emissiveReflectSpecPowerTexArray);
glActiveTexture(GL_TEXTURE0);
float itt = 1.0f/mRenderBuffers.texSize;
mShader->setUniform("diffuseTexArray", 10);
mShader->setUniform("bumpTexArray", 11);
mShader->setUniform("specularTexArray", 12);
mShader->setUniform("emissiveReflectSpecPowerTexArray", 13);
mShader->setUniform("ttt3D", 7);
mShader->setUniform("transTex", 8);
mShader->setUniform("transTexSize", mRenderBuffers.texSize);
mShader->setUniform("iTransTexSize", itt);
mShader->setUniform("bumpTextureUVScale", bumpTextureUVScale);
mShader->setUniform("extraNoiseScale",extraNoiseScale);
mShader->setUniform("roughnessScale", roughnessScale);
if (mShaderMat.color[3] < 1.0f) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
glColor4f(mShaderMat.color[0], mShaderMat.color[1], mShaderMat.color[2], mShaderMat.color[3]);
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, mRenderBuffers.VBO);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mRenderBuffers.IBO);
int stride = 12*sizeof(float);
glVertexPointer(3, GL_FLOAT, stride, 0);
glNormalPointer(GL_FLOAT, stride, (void*)(3*sizeof(float)));
glTexCoordPointer(4, GL_FLOAT, stride, (void*)(6*sizeof(float)));
glClientActiveTexture(GL_TEXTURE1);
glTexCoordPointer(2, GL_FLOAT, stride, (void*)(10*sizeof(float)));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawElements(GL_TRIANGLES, mRenderBuffers.numIndices, GL_UNSIGNED_INT, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
if (mShaderMat.color[3] < 1.0f) {
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
mShader->deactivate();
}
#endif
}
#ifdef USE_OPTIX
else if (SampleViewerScene::getRenderType() == SampleViewerScene::rtOPTIX) {
FractureModelUpdate update( mCompounds, mOptixBufferVersion != mSceneVersion );
if (mOptixBufferVersion != mSceneVersion) {
// Complete buffer update.
mOptixBufferVersion = mSceneVersion;
}
Profiler::getInstance()->begin("Optix data update");
SampleViewerScene::getOptixRenderer()->update( update );
OptixRenderer::Camera cam;
const size_t size_of_float3 = sizeof(float) * 3;
PxVec3 lookat = mCameraPos + mCameraDir;
memcpy( cam.eye, &mCameraPos.x, size_of_float3);
memcpy( cam.lookat, &lookat.x, size_of_float3);
memcpy( cam.up, &mCameraUp.x, size_of_float3);
cam.fov = mCameraFov;
Profiler::getInstance()->end("Optix data update");
Profiler::getInstance()->begin("Optix render");
SampleViewerScene::getOptixRenderer()->render( cam );
Profiler::getInstance()->end("Optix render");
}
#endif // USE_OPTIX
}
// --------------------------------------------------------------------------------------------
void SimScene::dumpSceneGeometry()
{
#ifdef USE_OPTIX
if( SampleViewerScene::getRenderType() == SampleViewerScene::rtOPTIX && SampleViewerScene::getOptixRenderer()) {
SampleViewerScene::getOptixRenderer()->dump_geometry();
}
#endif
}

View File

@ -0,0 +1,107 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#ifndef SIM_SCENE
#define SIM_SCENE
#include "Shader.h"
#include "PxPhysics.h"
#include "PxCooking.h"
#include "PxSimulationEventCallback.h"
#include <PsArray.h>
#include "ConvexRenderer.h"
#include "SimSceneBase.h"
using namespace physx::fracture;
class TerrainMesh;
struct ParticlesDesc;
class Particles;
class RegularCell3D;
class Actor;
class SimScene : public base::SimScene
{
public:
static SimScene* createSimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath);
protected:
SimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath);
public:
virtual ~SimScene();
virtual void createSingletons();
virtual base::Actor* createActor();
virtual base::Convex* createConvex();
virtual base::Compound* createCompound(PxReal contactOffset = 0.005f, PxReal restOffset = -0.001f);
virtual void clear();
virtual void profileBegin(const char* name);
virtual void profileEnd(const char* name);
bool addXml(const std::string &path, const std::string &filename, bool ignoreVisualMesh, float scale, const PxTransform &trans,
Shader* defaultShader, const ShaderMaterial &defaultMat);
void postSim(float dt, RegularCell3D* fluidSim);
//Particles* getParticles() { return mParticles; }
ConvexRenderer &getConvexRenderer() { return mConvexRenderer; }
void draw(bool useShader);
void setShaderMaterial(Shader* shader, const ShaderMaterial& mat) {this->mShader = shader; this->mShaderMat = mat;}
void setFractureForceThreshold(float threshold) { mFractureForceThreshold = threshold; }
void createRenderBuffers();
void dumpSceneGeometry();
void loadAndCreateTextureArrays();
std::vector<std::string> diffuseTexNames;
std::vector<std::string> bumpTexNames;
std::vector<std::string> specularTexNames;
std::vector<std::string> emissiveReflectSpecPowerTexNames;
protected:
virtual void create3dTexture();
virtual void updateConvexesTex();
GLuint diffuseTexArray, bumpTexArray, specularTexArray, emissiveReflectSpecPowerTexArray;
GLuint loadTextureArray(std::vector<std::string>& names);
//Particles *mParticles;
ConvexRenderer mConvexRenderer;
Shader* mShader;
ShaderMaterial mShaderMat;
};
#endif

View File

@ -0,0 +1,392 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "MathUtils.h"
#include "foundation/PxMat33.h"
#include "PhysXMacros.h"
//---------------------------------------------------------------------
void jacobiRotate(PxMat33 &A, PxMat33 &R, int p, int q)
{
// rotates A through phi in pq-plane to set A(p,q) = 0
// rotation stored in R whose columns are eigenvectors of A
if (A(p,q) == 0.0f)
return;
float d = (A(p,p) - A(q,q))/(2.0f*A(p,q));
float t = 1.0f / (PxAbs(d) + PxSqrt(d*d + 1.0f));
if (d < 0.0f) t = -t;
float c = 1.0f/PxSqrt(t*t + 1);
float s = t*c;
A(p,p) += t*A(p,q);
A(q,q) -= t*A(p,q);
A(p,q) = A(q,p) = 0.0f;
// transform A
int k;
for (k = 0; k < 3; k++) {
if (k != p && k != q) {
float Akp = c*A(k,p) + s*A(k,q);
float Akq =-s*A(k,p) + c*A(k,q);
A(k,p) = A(p,k) = Akp;
A(k,q) = A(q,k) = Akq;
}
}
// store rotation in R
for (k = 0; k < 3; k++) {
float Rkp = c*R(k,p) + s*R(k,q);
float Rkq =-s*R(k,p) + c*R(k,q);
R(k,p) = Rkp;
R(k,q) = Rkq;
}
}
//---------------------------------------------------------------------
void eigenDecomposition(PxMat33 &A, PxMat33 &R)
{
const int numJacobiIterations = 10;
const float epsilon = 1e-15f;
// only for symmetric matrices!
R = PX_MAT33_ID; // unit matrix
int iter = 0;
while (iter < numJacobiIterations) { // 3 off diagonal elements
// find off diagonal element with maximum modulus
int p,q;
float a,max;
max = PxAbs(A(0,1));
p = 0; q = 1;
a = PxAbs(A(0,2));
if (a > max) { p = 0; q = 2; max = a; }
a = PxAbs(A(1,2));
if (a > max) { p = 1; q = 2; max = a; }
// all small enough -> done
if (max < epsilon) break;
// rotate matrix with respect to that element
jacobiRotate(A, R, p,q);
iter++;
}
}
//---------------------------------------------------------------------
void polarDecomposition(const PxMat33 &A, PxMat33 &R)
{
// A = SR, where S is symmetric and R is orthonormal
// -> S = (A A^T)^(1/2)
PxMat33 AAT;
AAT(0,0) = A(0,0)*A(0,0) + A(0,1)*A(0,1) + A(0,2)*A(0,2);
AAT(1,1) = A(1,0)*A(1,0) + A(1,1)*A(1,1) + A(1,2)*A(1,2);
AAT(2,2) = A(2,0)*A(2,0) + A(2,1)*A(2,1) + A(2,2)*A(2,2);
AAT(0,1) = A(0,0)*A(1,0) + A(0,1)*A(1,1) + A(0,2)*A(1,2);
AAT(0,2) = A(0,0)*A(2,0) + A(0,1)*A(2,1) + A(0,2)*A(2,2);
AAT(1,2) = A(1,0)*A(2,0) + A(1,1)*A(2,1) + A(1,2)*A(2,2);
AAT(1,0) = AAT(0,1);
AAT(2,0) = AAT(0,2);
AAT(2,1) = AAT(1,2);
PxMat33 U;
R = PX_MAT33_ID;
eigenDecomposition(AAT, U);
const float eps = 1e-15f;
float l0 = AAT(0,0); if (l0 <= eps) l0 = 0.0f; else l0 = 1.0f / sqrt(l0);
float l1 = AAT(1,1); if (l1 <= eps) l1 = 0.0f; else l1 = 1.0f / sqrt(l1);
float l2 = AAT(2,2); if (l2 <= eps) l2 = 0.0f; else l2 = 1.0f / sqrt(l2);
PxMat33 S1;
S1(0,0) = l0*U(0,0)*U(0,0) + l1*U(0,1)*U(0,1) + l2*U(0,2)*U(0,2);
S1(1,1) = l0*U(1,0)*U(1,0) + l1*U(1,1)*U(1,1) + l2*U(1,2)*U(1,2);
S1(2,2) = l0*U(2,0)*U(2,0) + l1*U(2,1)*U(2,1) + l2*U(2,2)*U(2,2);
S1(0,1) = l0*U(0,0)*U(1,0) + l1*U(0,1)*U(1,1) + l2*U(0,2)*U(1,2);
S1(0,2) = l0*U(0,0)*U(2,0) + l1*U(0,1)*U(2,1) + l2*U(0,2)*U(2,2);
S1(1,2) = l0*U(1,0)*U(2,0) + l1*U(1,1)*U(2,1) + l2*U(1,2)*U(2,2);
S1(1,0) = S1(0,1);
S1(2,0) = S1(0,2);
S1(2,1) = S1(1,2);
R = S1 * A;
// stabilize
PxVec3 c0 = R.column0;
PxVec3 c1 = R.column1;
PxVec3 c2 = R.column2;
if (c0.magnitudeSquared() < eps)
c0 = c1.cross(c2);
else if (c1.magnitudeSquared() < eps)
c1 = c2.cross(c0);
else
c2 = c0.cross(c1);
R.column0 = c0;
R.column1 = c1;
R.column2 = c2;
}
//---------------------------------------------------------------------
PxVec3 perpVec3(const PxVec3 &v)
{
PxVec3 n;
if (fabs(v.x) < fabs(v.y) && fabs(v.x) < fabs(v.z))
n = PxVec3(1.0f, 0.0f, 0.0f);
else if (fabs(v.y) < fabs(v.z))
n = PxVec3(0.0f, 1.0f, 0.0f);
else
n = PxVec3(0.0f, 0.0f, 1.0f);
n = v.cross(n);
n.normalize();
return n;
}
//---------------------------------------------------------------------
void polarDecompositionStabilized(const PxMat33 &A, PxMat33 &R)
{
PxMat33 ATA;
ATA = A.getTranspose() * A;
PxMat33 Q;
eigenDecomposition(ATA, Q);
int degenerated = 0;
float l0 = ATA(0,0);
if (fabs(l0) <= FLT_EPSILON) {
l0 = 0;
degenerated += 1;
}
else l0 = 1.0f / PxSqrt(l0);
float l1 = ATA(1,1);
if (fabs(l1) <= FLT_EPSILON) {
l1 = 0;
degenerated += 2;
}
else l1 = 1.0f / PxSqrt(l1);
float l2 = ATA(2,2);
if (fabs(l2) <= FLT_EPSILON) {
l2 = 0;
degenerated += 4;
}
else l2 = 1.0f / PxSqrt(l2);
if (A.getDeterminant() < 0) //Invertierung nach Irving,Fedkiw
{
float *max = &l0;
if (l1 > *max) {max = &l1;}
if (l2 > *max) {max = &l2;}
*max *= -1;
}
PxMat33 D = PX_MAT33_ZERO;
D(0,0) = l0;
D(1,1) = l1;
D(2,2) = l2;
R = A * Q * D;
Q = Q.getTranspose();
//handle singular cases
PxVec3 r0 = R.column0;
PxVec3 r1 = R.column1;
PxVec3 r2 = R.column2;
if (degenerated == 0) { // 000
}
else if (degenerated == 1) { // 100
r0 = r1.cross(r2);
R.column0 = r0;
}
else if (degenerated == 2) { // 010
r1 = r2.cross(r0);
R.column1 = r1;
}
else if (degenerated == 4) { // 001
r2 = r0.cross(r1);
R.column2 = r2;
}
else if (degenerated == 6) { // 011
r1 = perpVec3(r0);
r2 = r0.cross(r1);
R.column1 = r1;
R.column2 = r2;
}
else if (degenerated == 5) { // 101
r2 = perpVec3(r1);
r0 = r1.cross(r2);
R.column2 = r2;
R.column0 = r0;
}
else if (degenerated == 3) { // 110
r0 = perpVec3(r2);
r1 = r2.cross(r0);
R.column0 = r0;
R.column1 = r1;
}
else // 111
R = PX_MAT33_ID;
R = R*Q;
}
//---------------------------------------------------------------------
void eigenDecomposition22(const PxMat33 &A, PxMat33 &R, PxMat33 &D)
{
// only for symmetric matrices
// decompose A such that
// A = R D R^T, where D is diagonal and R orthonormal (a rotation)
R = PX_MAT33_ID;
D = PX_MAT33_ID;
D(0,0) = A(0,0); D(0,1) = A(0,1);
D(1,0) = A(1,0); D(1,1) = A(1,1);
if (D(0,1) == 0.0f)
return;
float d = (D(0,0) - D(1,1))/(2.0f*D(0,1));
float t = 1.0f / (PxAbs(d) + PxSqrt(d*d + 1.0f));
if (d < 0.0f) t = -t;
float c = 1.0f/sqrt(t*t + 1);
float s = t*c;
D(0,0) += t*D(0,1);
D(1,1) -= t*D(0,1);
D(0,1) = D(1,0) = 0.0f;
// store rotation in R
for (int k = 0; k < 2; k++) {
float Rkp = c*R(k,0) + s*R(k,1);
float Rkq =-s*R(k,0) + c*R(k,1);
R(k,0) = Rkp;
R(k,1) = Rkq;
}
}
//---------------------------------------------------------------------
PxMat33 outerProduct(const PxVec3 &v0, const PxVec3 &v1)
{
PxMat33 M;
M.column0 = v0 * v1.x;
M.column1 = v0 * v1.y;
M.column2 = v0 * v1.z;
return M;
}
// From geometrictools.com
PxQuat align (const PxVec3& v1, const PxVec3& v2) {
// vector U = Cross(V1,V2)/Length(Cross(V1,V2)). The angle of rotation,
// A, is the angle between V1 and V2. The quaternion for the rotation is
// q = cos(A/2) + sin(A/2)*(ux*i+uy*j+uz*k) where U = (ux,uy,uz).
//
// (1) Rather than extract A = acos(Dot(V1,V2)), multiply by 1/2, then
// compute sin(A/2) and cos(A/2), we reduce the computational costs by
// computing the bisector B = (V1+V2)/Length(V1+V2), so cos(A/2) =
// Dot(V1,B).
//
// (2) The rotation axis is U = Cross(V1,B)/Length(Cross(V1,B)), but
// Length(Cross(V1,B)) = Length(V1)*Length(B)*sin(A/2) = sin(A/2), in
// which case sin(A/2)*(ux*i+uy*j+uz*k) = (cx*i+cy*j+cz*k) where
// C = Cross(V1,B).
//
// If V1 = V2, then B = V1, cos(A/2) = 1, and U = (0,0,0). If V1 = -V2,
// then B = 0. This can happen even if V1 is approximately -V2 using
// floating point arithmetic, since Vector3::Normalize checks for
// closeness to zero and returns the zero vector accordingly. The test
// for exactly zero is usually not recommend for floating point
// arithmetic, but the implementation of Vector3::Normalize guarantees
// the comparison is robust. In this case, the A = pi and any axis
// perpendicular to V1 may be used as the rotation axis.
PxVec3 bisector = v1 + v2;
bisector.normalize();
float cosHalfAngle = v1.dot(bisector);
PxVec3 cross;
float mTuple[4];
mTuple[0] = cosHalfAngle;
if (cosHalfAngle != (float)0)
{
cross = v1.cross(bisector);
mTuple[1] = cross.x;
mTuple[2] = cross.y;
mTuple[3] = cross.z;
}
else
{
float invLength;
if (fabs(v1[0]) >= fabs(v1[1]))
{
// V1.x or V1.z is the largest magnitude component.
invLength = fastInvSqrt(v1[0]*v1[0] + v1[2]*v1[2]);
mTuple[1] = -v1[2]*invLength;
mTuple[2] = (float)0;
mTuple[3] = +v1[0]*invLength;
}
else
{
// V1.y or V1.z is the largest magnitude component.
invLength = fastInvSqrt(v1[1]*v1[1] + v1[2]*v1[2]);
mTuple[1] = (float)0;
mTuple[2] = +v1[2]*invLength;
mTuple[3] = -v1[1]*invLength;
}
}
PxQuat q(mTuple[1],mTuple[2],mTuple[3], mTuple[0]);
return q;
}
void decomposeTwistTimesSwing (const PxQuat& q, const PxVec3& v1,
PxQuat& twist, PxQuat& swing)
{
PxVec3 v2 = v1;
q.rotate(v2);
swing = align(v1, v2);
twist = q*swing.getConjugate();
}
void decomposeSwingTimesTwist (const PxQuat& q, const PxVec3& v1,
PxQuat& swing, PxQuat& twist)
{
PxVec3 v2 = v1;
q.rotate(v2);
swing = align(v1, v2);
twist = swing.getConjugate()*q;
}

View File

@ -0,0 +1,129 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef MATH_UTILS
#define MATH_UTILS
#include "foundation/PxVec3.h"
#include "foundation/PxQuat.h"
#include "foundation/PxMath.h"
using namespace physx;
// ------------------------------------------------------------------------
PX_FORCE_INLINE PxF32 randRange(const PxF32 a, const PxF32 b)
{
return a + (b-a)*::rand()/RAND_MAX;
}
// ------------------------------------------------------------------------
inline static float fastInvSqrt(float input)
{
const float halfInput = 0.5f * input;
int i = *(int*)&input;
i = 0x5f375a86 - ( i >> 1 );
input = *(float*) & i;
input = input * ( 1.5f - halfInput * input * input);
return input;
}
// ------------------------------------------------------------------------
inline static void fastNormalize(PxVec3 &v) {
v *= fastInvSqrt(v.magnitudeSquared());
}
// ------------------------------------------------------------------------
inline static float fastLen(PxVec3 &v) {
return 1.0f / fastInvSqrt(v.magnitudeSquared());
}
// ------------------------------------------------------------------------
inline static float fastNormalizeLen(PxVec3 &v) {
float inv = fastInvSqrt(v.magnitudeSquared());
v *= inv;
return 1.0f / inv;
}
// ------------------------------------------------------------------------
inline static float fastAcos(float x) {
// MacLaurin series
if (x < -1.0f) x = -1.0f;
if (x > 1.0f) x = 1.0f;
float x2 = x*x;
float angle = (35.0f/1152.0f)*x2;
angle = (5.0f/112.0f) + angle*x2;
angle = (3.0f/40.0f) + angle*x2;
angle = (1.0f/6.0f) + angle*x2;
angle = 1 + angle*x2;
angle = 1.5707963267948966f - angle * x;
return angle;
}
// ------------------------------------------------------------------------
inline static void quatFromVectors(const PxVec3 &n0, const PxVec3 &n1, PxQuat &q)
{
// fast approximation
PxVec3 axis = n0.cross(n1) * 0.5f;
q = PxQuat(axis.x, axis.y, axis.z, PxSqrt(1.0f - axis.magnitudeSquared()));
// correct
//PxVec3 axis = n0 ^ n1;
//axis.normalize();
//float s = PxMath::sqrt(0.5f * (1.0f - n0.dot(n1)));
//q.x = axis.x * s;
//q.y = axis.y * s;
//q.z = axis.z * s;
//q.w = PxMath::sqrt(1.0f - s*s);
}
// ------------------------------------------------------------------------
void polarDecomposition(const PxMat33 &A, PxMat33 &R);
void polarDecompositionStabilized(const PxMat33 &A, PxMat33 &R);
// ------------------------------------------------------------------------
void eigenDecomposition(PxMat33 &A, PxMat33 &R);
// ------------------------------------------------------------------------
void eigenDecomposition22(const PxMat33 &A, PxMat33 &R, PxMat33 &D);
// ------------------------------------------------------------------------
PxMat33 outerProduct(const PxVec3 &v0, const PxVec3 &v1);
// ------------------------------------------------------------------------
PxQuat align(const PxVec3& v1, const PxVec3& v2);
// ------------------------------------------------------------------------
void decomposeTwistTimesSwing(const PxQuat& q, const PxVec3& v1,
PxQuat& twist, PxQuat& swing);
// ------------------------------------------------------------------------
void decomposeSwingTimesTwist(const PxQuat& q, const PxVec3& v1,
PxQuat& swing, PxQuat& twist);
#endif

View File

@ -0,0 +1,310 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#if defined(WIN32) || defined(WIN64)
#define NOMINMAX
#include <windows.h>
#endif
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "MediaPath.h"
#if defined(_XBOX)
#include <xtl.h>
#include <Xbdm.h>
static bool MediaFileExists(const char *fname)
{
FILE *fp=fopen(fname,"rb");
if(fp == NULL)
{
return false;
}
else
{
fclose(fp);
return true;
}
}
char* FindMediaFile(const char *fname,char *buff)
{
strcpy(buff,"d:\\");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
DmMapDevkitDrive();
strcpy(buff,"DEVKIT:\\");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
char msg[1024];
sprintf(msg, "Can't find media file: %s\n", fname);
OutputDebugString(msg);
return buff;
}
char* GetTempFilePath(char *buff)
{
strcpy(buff,"d:\\");
return buff;
}
#elif defined(__CELLOS_LV2__)
#include <sys/paths.h>
char* FindMediaFile(const char *fname,char *buff)
{
strcpy(buff,SYS_APP_HOME "/");
strcat(buff,fname);
return buff;
}
char* GetTempFilePath(char *buff)
{
strcpy(buff,SYS_APP_HOME "/");
return buff;
}
#elif defined(WIN32) || defined(WIN64)
static bool MediaFileExists(const char *fname)
{
FILE *fp=fopen(fname,"rb");
if(fp == NULL)
{
return false;
}
else
{
fclose(fp);
return true;
}
}
char* FindMediaFile(const char* fname, const char* path)
{
static char fullPath[512];
strcpy(fullPath, path);
strcat(fullPath, "/");
strcat(fullPath, fname);
return fullPath;
}
char* FindMediaFile(const char *fname,char *buff)
{
char curPath[MAX_PATH];
GetCurrentDirectory(MAX_PATH, curPath);
strcat(curPath, "\\");
strcpy(buff, curPath);
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
char basePath[MAX_PATH];
GetModuleFileName(NULL, basePath, MAX_PATH);
char* pTmp = strrchr(basePath, '\\');
if(pTmp != NULL){
*pTmp = 0;
SetCurrentDirectory(basePath);
pTmp = strrchr(basePath, '\\');
if(pTmp != NULL){
*pTmp = 0;
}
pTmp = strrchr(basePath, '\\');
if(pTmp != NULL){
*(pTmp + 1) = 0;
}
}
strcpy(buff, basePath);
strcat(buff,"..\\..\\..\\externals\\GRB\\1.0\\");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
// printf("base path is: %s\n", basePath);
strcpy(buff, basePath);
strcat(buff,"Samples\\Media\\");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
strcpy(buff, basePath);
strcat(buff,"Samples\\compiler\\vc8win32\\");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
strcpy(buff, basePath);
strcat(buff,"Bin\\win32\\");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
strcpy(buff,fname);
if(MediaFileExists(buff))
return buff;
printf("Can't find media file: %s\n", fname);
strcpy(buff,fname);
return buff;
}
char* GetTempFilePath(char *buff)
{
strcpy(buff,"");
return buff;
}
#elif defined(LINUX)
static bool MediaFileExists(const char *fname)
{
FILE *fp=fopen(fname,"rb");
if(fp == NULL)
{
return false;
}
else
{
fclose(fp);
return true;
}
}
char* FindMediaFile(const char *fname,char *buff)
{
strcpy(buff,fname);
if(MediaFileExists(buff))
return buff;
strcpy(buff,"../../Samples/Media/");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
strcpy(buff,"../../../Media/");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
strcpy(buff,"../../Media/");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
strcpy(buff,"Samples/Media/");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
printf("Can't find media file: %s\n", fname);
strcpy(buff,fname);
return buff;
}
char* GetTempFilePath(char *buff)
{
strcpy(buff,"");
return buff;
}
#elif defined(__PPCGEKKO__)
#include <revolution/dvd.h>
static bool MediaFileExists(const char *fname)
{
DVDFileInfo fileInfo;
if(DVDOpen(fname,&fileInfo))
{
DVDClose(&fileInfo);
return true;
}
return false;
}
char* FindMediaFile(const char *fname,char *buff)
{
strcpy(buff,fname);
if(MediaFileExists(buff))
return buff;
strcpy(buff,"/Media/");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
strcpy(buff,"../../Samples/Media/");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
strcpy(buff,"../../../Media/");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
strcpy(buff,"../../Media/");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
strcpy(buff,"Samples/Media/");
strcat(buff,fname);
if(MediaFileExists(buff))
return buff;
printf("Can't find media file: %s\n", fname);
strcpy(buff,fname);
return buff;
}
char* GetTempFilePath(char *buff)
{
strcpy(buff,"");
return buff;
}
#endif

View File

@ -0,0 +1,43 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#ifndef __MEDIA_PATH__
#define __MEDIA_PATH__
/*
This function locates the media associated with the sample in a non platform specific way.
For example it searches the Samples\Media directory on the PC (assuming the exe is in the bin directory or
or project directory after a compile). This helps prevent duplicate resources for samples.
*/
char* FindMediaFile(const char *fname,char *buff);
char* FindMediaFile(const char *fname, const char* path);
char* GetTempFilePath(char *buff);
#endif

View File

@ -0,0 +1,40 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef PHYSX_MACROS_H
#define PHYSX_MACROS_H
#include "PxPhysicsVersion.h"
#define PX_TRANSFORM_ID PxTransform(PxIdentity)
#define PX_MAT33_ID PxMat33(PxIdentity)
#define PX_MAT33_ZERO PxMat33(PxZero)
#define PX_MAT44_ID PxMat44(PxIdentity)
#define PX_MAT44_ZERO PxMat44(PxZero)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#ifndef SAMPLE_VIEWER_H
#define SAMPLE_VIEWER_H
// glut callbacks
void RenderCallback();
void ReshapeCallback(int width, int height);
void IdleCallback();
void KeyboardCallback(unsigned char key, int x, int y);
void KeyboardUpCallback(unsigned char key, int x, int y);
void SpecialCallback(int key, int x, int y);
void MouseCallback(int button, int state, int x, int y);
void MotionCallback(int x, int y);
void InitGlut(int argc, char **argv);
float UpdateTime();
void WaitForPhysics();
void RunPhysics();
int main(int argc, char** argv);
#endif // SAMPLE_VIEWER_H

View File

@ -0,0 +1,238 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "SampleViewerGamepad.h"
#include "SampleViewerScene.h"
#include <stdio.h>
#include <direct.h>
#include "PsString.h"
//////////////////////////////////////////////////////////////////////////
static bool gTimeInit = false;
static const unsigned int MAX_GAMEPADS = 4;
static const unsigned int MAX_GAMEPAD_AXES = 4;
static XINPUT_STATE m_lastInputState[MAX_GAMEPADS];
static int m_lastAxisData[MAX_GAMEPADS][MAX_GAMEPAD_AXES];
//////////////////////////////////////////////////////////////////////////
SampleViewerGamepad::SampleViewerGamepad()
: mGamePadConnected(false), mConnectedPad(0), mXInputLibrary(), mpXInputGetState(0), mpXInputGetCapabilities(0)
{
}
//////////////////////////////////////////////////////////////////////////
SampleViewerGamepad::~SampleViewerGamepad()
{
release();
}
//////////////////////////////////////////////////////////////////////////
void SampleViewerGamepad::init()
{
static const unsigned int xInputLibCount = 4;
static const char* xInputLibs[xInputLibCount] = { "xinput1_4.dll",
"xinput1_3.dll",
"xinput1_2.dll",
"xinput1_1.dll" };
for (unsigned int i = 0; i < xInputLibCount; ++i)
{
mXInputLibrary = LoadLibraryA(xInputLibs[i]);
if (mXInputLibrary)
break;
}
if(!mXInputLibrary)
{
physx::shdfnd::printString("Could not load XInput library.");
}
if (mXInputLibrary)
{
mpXInputGetState = (LPXINPUTGETSTATE)GetProcAddress(mXInputLibrary, "XInputGetState");
mpXInputGetCapabilities = (LPXINPUTGETCAPABILITIES)GetProcAddress(mXInputLibrary, "XInputGetCapabilities");
if(!mpXInputGetState)
{
physx::shdfnd::printString("Error loading XInputGetState function.");
}
if(!mpXInputGetCapabilities)
{
physx::shdfnd::printString("Error loading XInputGetCapabilities function.");
}
}
}
//////////////////////////////////////////////////////////////////////////
void SampleViewerGamepad::release()
{
if (mXInputLibrary)
{
FreeLibrary(mXInputLibrary);
mXInputLibrary = 0;
}
mpXInputGetState = 0;
mpXInputGetCapabilities = 0;
mGamePadConnected = false;
mConnectedPad = 0;
}
//////////////////////////////////////////////////////////////////////////
void SampleViewerGamepad::processGamepads(SampleViewerScene& viewerScene)
{
if (!gTimeInit)
{
gTimeInit = true;
for (unsigned int p = 0; p < MAX_GAMEPADS; p++)
{
memset(&m_lastInputState[p], 0, sizeof(XINPUT_STATE));
for (unsigned int i = 0; i < MAX_GAMEPAD_AXES; i++)
{
m_lastAxisData[p][i] = 0;
}
}
}
static int32_t disConnected[4] = { 1, 2, 3, 4 };
if (!hasXInput())
return;
for (uint32_t p = 0; p < MAX_GAMEPADS; p++)
{
if ((--disConnected[p]) == 0)
{
XINPUT_STATE inputState;
DWORD state = mpXInputGetState(p, &inputState);
if (state == ERROR_DEVICE_NOT_CONNECTED)
{
disConnected[p] = 4;
if (mGamePadConnected && (mConnectedPad == p))
{
mGamePadConnected = false;
mConnectedPad = 0;
for (uint32_t k = 0; k < MAX_GAMEPADS; k++)
{
XINPUT_STATE inputStateDisc;
DWORD stateDisc = mpXInputGetState(k, &inputStateDisc);
if (stateDisc == ERROR_SUCCESS)
{
mConnectedPad = k;
mGamePadConnected = true;
break;
}
}
}
}
else if (state == ERROR_SUCCESS)
{
if (!mGamePadConnected)
{
mGamePadConnected = true;
mConnectedPad = p;
}
disConnected[p] = 1; //force to test next time
XINPUT_CAPABILITIES caps;
mpXInputGetCapabilities(p, XINPUT_FLAG_GAMEPAD, &caps);
//gamepad
{
// Process buttons
const WORD lastWButtons = m_lastInputState[p].Gamepad.wButtons;
const WORD currWButtons = inputState.Gamepad.wButtons;
const WORD buttonsDown = currWButtons & ~lastWButtons;
const WORD buttonsUp = ~currWButtons & lastWButtons;
// const WORD buttonsHeld = currWButtons & lastWButtons;
for (int i = 0; i < 14; i++)
{
// order has to match struct GamepadControls
static const WORD buttonMasks[] = {
XINPUT_GAMEPAD_DPAD_UP,
XINPUT_GAMEPAD_DPAD_DOWN,
XINPUT_GAMEPAD_DPAD_LEFT,
XINPUT_GAMEPAD_DPAD_RIGHT,
XINPUT_GAMEPAD_START,
XINPUT_GAMEPAD_BACK,
XINPUT_GAMEPAD_LEFT_THUMB,
XINPUT_GAMEPAD_RIGHT_THUMB,
XINPUT_GAMEPAD_Y,
XINPUT_GAMEPAD_A,
XINPUT_GAMEPAD_X,
XINPUT_GAMEPAD_B,
XINPUT_GAMEPAD_LEFT_SHOULDER,
XINPUT_GAMEPAD_RIGHT_SHOULDER,
};
if (buttonsDown & buttonMasks[i])
viewerScene.handleGamepadButton(i, true);
else if (buttonsUp & buttonMasks[i])
viewerScene.handleGamepadButton(i, false);
}
{
const BYTE newTriggerVal = inputState.Gamepad.bRightTrigger;
viewerScene.handleGamepadTrigger(GamepadTrigger::GAMEPAD_RIGHT_SHOULDER_TRIGGER, ((float)newTriggerVal) / 255);
}
{
const BYTE newTriggerVal = inputState.Gamepad.bLeftTrigger;
viewerScene.handleGamepadTrigger(GamepadTrigger::GAMEPAD_LEFT_SHOULDER_TRIGGER, ((float)newTriggerVal) / 255);
}
}
// Gamepad
const int axisData[] = { inputState.Gamepad.sThumbRX, inputState.Gamepad.sThumbRY, inputState.Gamepad.sThumbLX, inputState.Gamepad.sThumbLY };
for (uint32_t i = 0; i < MAX_GAMEPAD_AXES; i++)
{
if (axisData[i] != m_lastAxisData[p][i])
{
int data = axisData[i];
if (abs(data) < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
data = 0;
}
viewerScene.handleGamepadAxis(i, ((float)data) / SHRT_MAX);
}
m_lastAxisData[p][i] = axisData[i];
}
m_lastInputState[p] = inputState;
}
}
}
}

View File

@ -0,0 +1,96 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef SAMPLE_VIEWER_GAMEPAD_H
#define SAMPLE_VIEWER_GAMEPAD_H
#include <WTypes.h>
#include <XInput.h>
class SampleViewerScene;
class SampleViewerGamepad
{
public:
enum GamepadTrigger
{
GAMEPAD_RIGHT_SHOULDER_TRIGGER = 0,
GAMEPAD_LEFT_SHOULDER_TRIGGER = 1
};
enum GamepadButtons
{
GAMEPAD_DPAD_UP = 0,
GAMEPAD_DPAD_DOWN,
GAMEPAD_DPAD_LEFT,
GAMEPAD_DPAD_RIGHT,
GAMEPAD_START,
GAMEPAD_BACK,
GAMEPAD_LEFT_THUMB,
GAMEPAD_RIGHT_THUMB,
GAMEPAD_Y,
GAMEPAD_A,
GAMEPAD_X,
GAMEPAD_B,
GAMEPAD_LEFT_SHOULDER,
GAMEPAD_RIGHT_SHOULDER
};
enum GamepadAxis
{
GAMEPAD_RIGHT_STICK_X = 0,
GAMEPAD_RIGHT_STICK_Y,
GAMEPAD_LEFT_STICK_X,
GAMEPAD_LEFT_STICK_Y
};
SampleViewerGamepad();
~SampleViewerGamepad();
void init();
void release();
void processGamepads(SampleViewerScene& viewerScene);
private:
bool hasXInput() const { return mpXInputGetState && mpXInputGetCapabilities; }
private:
bool mGamePadConnected;
unsigned int mConnectedPad;
typedef DWORD(WINAPI *LPXINPUTGETSTATE)(DWORD, XINPUT_STATE*);
typedef DWORD(WINAPI *LPXINPUTGETCAPABILITIES)(DWORD, DWORD, XINPUT_CAPABILITIES*);
HMODULE mXInputLibrary;
LPXINPUTGETSTATE mpXInputGetState;
LPXINPUTGETCAPABILITIES mpXInputGetCapabilities;
};
#endif // SAMPLE_VIEWER_GAMEPAD_H

View File

@ -0,0 +1,133 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "SampleViewerScene.h"
#include "PxMaterial.h"
#include "ShaderShadow.h"
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#ifdef USE_OPTIX
SampleViewerScene::RenderType SampleViewerScene::mRenderType = SampleViewerScene::rtOPTIX;
#else
SampleViewerScene::RenderType SampleViewerScene::mRenderType = SampleViewerScene::rtOPENGL;
#endif
OptixRenderer *SampleViewerScene::mOptixRenderer = NULL;
bool SampleViewerScene::mBenchmark = false;
//-----------------------------------------------------------------------------
SampleViewerScene::SampleViewerScene(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
Shader *defaultShader, const char *resourcePath, float slowMotionFactor)
{
mPxPhysics = pxPhysics;
mPxCooking = pxCooking;
mCameraPos = PxVec3(0.0f, 20.0f, 10.0f);
mCameraDir = PxVec3(0.0f, 0.0f, 1.0f);
mCameraUp = PxVec3(0.0f, 1.0f, 0.0f);
mCameraFov = 40.f;
mDefaultShader = defaultShader;
//printf("hhh = %s\n", resourcePath);
mResourcePath = resourcePath;
mSlowMotionFactor = slowMotionFactor;
mDefaultMaterial = pxPhysics->createMaterial(0.5f, 0.5f, 0.0f);
mCameraDisable = false;
}
//-----------------------------------------------------------------------------
SampleViewerScene::~SampleViewerScene()
{
for (int i = 0; i < (int)mShaders.size(); i++)
delete mShaders[i];
mShaders.clear();
}
// ----------------------------------------------------------------------------------------------
void SampleViewerScene::getMouseRay(int xi, int yi, PxVec3 &orig, PxVec3 &dir)
{
GLint viewPort[4];
GLdouble modelMatrix[16];
GLdouble projMatrix[16];
glGetIntegerv(GL_VIEWPORT, viewPort);
glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
yi = viewPort[3] - yi - 1;
GLdouble x,y,z;
gluUnProject((GLdouble) xi, (GLdouble) yi, 0.0f,
modelMatrix, projMatrix, viewPort, &x, &y, &z);
orig = PxVec3((float)x, (float)y, (float)z);
gluUnProject((GLdouble) xi, (GLdouble) yi, 1.0f,
modelMatrix, projMatrix, viewPort, &x, &y, &z);
dir = PxVec3((float)x, (float)y, (float)z);
dir = dir - orig;
dir.normalize();
orig -= dir * 100.0f; // to catch ray casts
}
// ----------------------------------------------------------------------------------------------
void SampleViewerScene::setMaterial(float restitution, float staticFriction, float dynamicFriction)
{
mDefaultMaterial->setRestitution(restitution);
mDefaultMaterial->setStaticFriction(staticFriction);
mDefaultMaterial->setDynamicFriction(dynamicFriction);
}
// ----------------------------------------------------------------------------------------------
void SampleViewerScene::render(bool useShader)
{
#ifdef USE_OPTIX
if (mRenderType == rtOPTIX && mOptixRenderer == NULL)
mOptixRenderer = new OptixRenderer( getRendererOptions() );
#endif
}
// ----------------------------------------------------------------------------------------------
void SampleViewerScene::cleanupStaticResources()
{
#ifdef USE_OPTIX
if( mOptixRenderer ) {
OptixRenderer* ren = mOptixRenderer;
mOptixRenderer = 0;
delete ren;
}
#endif
}
// ----------------------------------------------------------------------------------------------
std::string SampleViewerScene::mRendererOptions;
void SampleViewerScene::setRendererOptions( const char* text )
{
if( text ) mRendererOptions = text;
else mRendererOptions.clear();
}

View File

@ -0,0 +1,152 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#ifndef SAMPLE_VIEWER_SCENE_H
#define SAMPLE_VIEWER_SCENE_H
#include "foundation/PxVec3.h"
#include "foundation/PxTransform.h"
#include "PxPhysics.h"
#include "PxCooking.h"
using namespace physx;
#include <vector>
#include <string>
class OptixRenderer;
#ifdef USE_OPTIX
#include "OptixRenderer.h"
#endif
class Shader;
class ShaderShadow;
// ---------------------------------------------------------------------
class SampleViewerScene
{
public:
SampleViewerScene(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
Shader *defaultShader, const char *resourcePath, float slowMotionFactor);
virtual ~SampleViewerScene();
// virtual interface
virtual void preSim(float dt) {};
virtual void postSim(float dt) {};
virtual void duringSim(float dt) {};
virtual void syncAsynchronousWork() {};
virtual void handleMouseButton(int button, int state, int x, int y) {};
virtual void handleMouseMotion(int x, int y) {};
virtual void handleKeyDown(unsigned char key, int x, int y) {};
virtual void handleKeyUp(unsigned char key, int x, int y) {};
virtual void handleSpecialKey(unsigned char key, int x, int y) {};
virtual void handleGamepadButton(int button, bool state) {};
virtual void handleGamepadAxis(int axis, float x) {};
virtual void handleGamepadTrigger(int trigger, float x) {};
virtual void render(bool useShader);
virtual void printPerfInfo() {}
virtual void setSlowMotionFactor(float factor) { mSlowMotionFactor = factor; }
virtual std::string getWeaponName() { return ""; };
virtual void customizeSceneDesc(PxSceneDesc& desc) {}
virtual void onInit(PxScene* pxScene){ mPxScene = pxScene; }
virtual void setScene(PxScene* pxScene) { mPxScene = pxScene; }
// common code
void setCamera(const PxVec3 &pos, const PxVec3 &dir, const PxVec3 &up, float fov ) {
mCameraPos = pos; mCameraDir = dir; mCameraUp = up; mCameraFov = fov;
}
virtual void getCamera(PxVec3& pos, PxVec3& dir){}
virtual bool isCameraDisable() { return mCameraDisable; }
virtual void getInitialCamera(PxVec3& pos, PxVec3& dir) { pos = PxVec3(0.f, 25.f, 30.f); dir = PxVec3(0.f, -0.3f, -1.f).getNormalized(); }
void getMouseRay(int xi, int yi, PxVec3 &orig, PxVec3 &dir);
std::vector<ShaderShadow*>& getShaders() { return mShaders; }
enum RenderType {
rtOPENGL,
rtOPTIX,
rtNUM,
};
static void setRenderType(RenderType renderType) { mRenderType = renderType; }
static void toggleRenderType() { setRenderType((RenderType)(((int)mRenderType+1)%rtNUM)); }
static RenderType getRenderType() { return mRenderType; }
static OptixRenderer* getOptixRenderer() { return mOptixRenderer; }
// Set option string for renderers.
static void setRendererOptions( const char* );
static const char* getRendererOptions() {return mRendererOptions.c_str();}
// Call this before exit().
static void cleanupStaticResources();
static void setBenchmark( bool on ) { mBenchmark = on; }
static bool isBenchmark() { return mBenchmark; }
virtual bool isSceneKapla() {return false;}
PxPhysics& getPhysics() { return *mPxPhysics; }
PxCooking& getCooking() { return *mPxCooking; }
PxScene& getScene() { return *mPxScene; }
protected:
void setMaterial(float restitution = 0.2f, float staticFriction = 0.2f, float dynamicFriction = 0.2f);
PxPhysics *mPxPhysics;
PxCooking *mPxCooking;
PxScene *mPxScene;
PxMaterial *mDefaultMaterial;
PxVec3 mCameraPos, mCameraDir, mCameraUp;
float mCameraFov;
std::vector<ShaderShadow*> mShaders;
Shader *mDefaultShader;
const char *mResourcePath;
float mSlowMotionFactor;
static RenderType mRenderType;
static OptixRenderer *mOptixRenderer;
static bool mBenchmark;
static std::string mRendererOptions;
bool mCameraDisable;
};
#endif // SAMPLE_VIEWER_SCENE_H

View File

@ -0,0 +1,189 @@
//
// 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-2018 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxPhysicsAPI.h"
#include "extensions/PxExtensionsAPI.h"
#include "SceneCrab.h"
#include "SimScene.h"
#include "CompoundCreator.h"
#include <GL/glut.h>
#include "PxTkStream.h"
#include "PxTkFile.h"
using namespace PxToolkit;
// if enabled: runs the crab AI in sync, not as a parallel task to physx.
#define DEBUG_RENDERING 0
bool mSpawnActive = false;
SceneCrab::SceneCrab(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
Shader *defaultShader, const char *resourcePath, float slowMotionFactor) :
SceneKapla(pxPhysics, pxCooking, isGrb, defaultShader, resourcePath, slowMotionFactor)
{
mNbCrabsX = 20;
mNbCrabsZ = 20;
mNbSuperCrabs = 2;
}
void SceneCrab::onInit(PxScene* pxScene)
{
SceneKapla::onInit(pxScene);
mCrabManager.setSceneCrab(this);
mCrabManager.initialize(mNbCrabsX*mNbCrabsZ + mNbSuperCrabs);
createTerrain("terrain_ll2.bmp", "", 60.f, true);
const PxVec3 dims(0.08f, 0.25f, 1.0f);
PxMaterial* towerMaterial = mPxPhysics->createMaterial(0.5f, 0.25f, 0.1f);
ShaderMaterial mat;
mat.init();
PxFilterData queryData;
queryData.word0 = 128;
createCrabs();
createCylindricalTower(48, 3.6f, 3.6f, 15, dims, PxVec3(-25.f, -30.5f, -85.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
createCylindricalTower(48, 3.6f, 3.6f, 15, dims, PxVec3(-5.f, -30.5f, -85.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
createCylindricalTower(48, 3.6f, 3.6f, 15, dims, PxVec3(15.f, -30.5f, -85.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
createCylindricalTower(48, 3.6f, 3.6f, 15, dims, PxVec3(35.f, -30.5f, -85.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
createCylindricalTower(48, 3.6f, 3.6f, 15, dims, PxVec3(55.f, -30.5f, -85.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
//createCylindricalTower(64, 3.6f, 3.6f, 15, dims, PxVec3(-75.f, -30.65f, -95.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
//createCylindricalTower(64, 3.6f, 3.6f, 15, dims, PxVec3(-55.f, -30.65f, -95.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
//createCylindricalTower(64, 3.6f, 3.6f, 15, dims, PxVec3(-35.f, -30.65f, -95.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
/*createCylindricalTower(64, 3.6f, 3.6f, 15, dims, PxVec3(55.f, -1.10f, 55.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);*/
}
SceneCrab::~SceneCrab()
{
}
void SceneCrab::setScene(PxScene* scene)
{
SceneKapla::setScene(scene);
mCrabManager.setScene(scene);
}
void SceneCrab::createCrabs()
{
PxVec3 startCrabPos(-75.f, 1.f, -75.f);
PxReal scale = 0.8f;
PxReal crabDepth = 2.0f;
PxReal legMass = 0.03f;
for (PxU32 i = 0; i < mNbCrabsX; ++i)
{
PxVec3 crabPos = startCrabPos + PxVec3(10.f*i, 0, 0);
for (PxU32 j = 0; j < mNbCrabsZ; ++j)
{
//const PxU32 index = i*mNbCrabsX + j;
crabPos.z += 10.f;
mCrabManager.createCrab(crabPos, crabDepth, scale, legMass, 4);
}
}
startCrabPos = PxVec3(-20.f, 1.f, -20.f);
crabDepth = 8.f;
legMass = 0.3f;
scale = 2.f;
for (PxU32 i = 0; i < mNbSuperCrabs; ++i)
{
PxVec3 crabPos = startCrabPos + PxVec3(-20.f*i, 0, -20.f*i);
//super crabs
mCrabManager.createCrab(crabPos, crabDepth, scale, legMass, 8);
}
}
// ----------------------------------------------------------------------------------------------
void SceneCrab::duringSim(float dt)
{
PxSceneWriteLock scopedLock(getScene());
mCrabManager.update(dt);
}
void SceneCrab::syncAsynchronousWork()
{
mCrabManager.syncWork();
}
void SceneCrab::handleKeyDown(unsigned char key, int x, int y)
{
if (key == 'k' || key == 'K')
{
if (!mSpawnActive)
{
mSpawnActive = true;
PxReal scale = 0.8f;
PxReal crabDepth = 2.0f;
PxReal legMass = 0.03f;
//Raycast against the static world to get a spawn position....
PxRaycastBuffer hit;
PxQueryFilterData fd; fd.flags |= PxQueryFlag::eSTATIC;
PxVec3 orig, dir;
getMouseRay(mMouseX, mMouseY, orig, dir);
if (mSimScene->getScene()->raycast(mCameraPos, dir, 1000.f, hit, PxHitFlags(PxHitFlag::eDEFAULT), fd))
{
//Spawn a walker...
for (PxU32 a = 0; a < 1; ++a)
{
for (PxU32 b = 0; b < 1; ++b)
{
mCrabManager.createCrab(hit.block.position + PxVec3(a*10.f, 0.f, b * 10.f), crabDepth, scale, legMass, 4);
}
}
}
}
}
SceneKapla::handleKeyDown(key, x, y);
}
void SceneCrab::handleKeyUp(unsigned char key, int x, int y)
{
if (key == 'k' || key == 'K')
{
mSpawnActive = false;
}
SceneKapla::handleKeyUp(key, x, y);
}

View File

@ -0,0 +1,80 @@
//
// 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-2018 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 SCENE_CRAB_H
#define SCENE_CRAB_H
#include "SceneKapla.h"
#include "foundation/Px.h"
#include "foundation/PxSimpleTypes.h"
#include "common/PxPhysXCommonConfig.h"
#include "task/PxTask.h"
#include "CrabManager.h"
#include <vector>
namespace physx
{
class PxRigidDynamic;
class PxRevoluteJoint;
class PxJoint;
}
class SceneCrab : public SceneKapla
{
public:
SceneCrab(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb, Shader *defaultShader, const char *resourcePath, float slowMotionFactor);
~SceneCrab();
virtual void onInit(PxScene* pxScene);
virtual void setScene(PxScene* scene);
virtual void duringSim(float dt);
virtual void syncAsynchronousWork();
virtual void getInitialCamera(PxVec3& pos, PxVec3& dir) { pos = PxVec3(-70.f, -5.f, -70.f); dir = PxVec3(1.f, -0.3f, 1.f).getNormalized(); }
virtual void handleKeyDown(unsigned char key, int x, int y);
virtual void handleKeyUp(unsigned char key, int x, int y);
private:
void createCrabs();
private:
CrabManager mCrabManager;
PxU32 mNbCrabsX;
PxU32 mNbCrabsZ;
PxU32 mNbSuperCrabs;
};
#endif

View File

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

View File

@ -0,0 +1,956 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "SceneKapla.h"
#include "Convex.h"
#include "PxSimpleFactory.h"
#include "PxRigidStatic.h"
#include "PxShape.h"
#include "foundation/PxMathUtils.h"
#include "foundation/PxMat44.h"
#include <stdio.h>
#include <GL/glut.h>
#include "ShaderShadow.h"
#include "SimScene.h"
#include "CompoundCreator.h"
#include "Mesh.h"
#include "TerrainMesh.h"
#include "PhysXMacros.h"
#include "MathUtils.h"
#include "PxRigidBodyExt.h"
#include "MediaPath.h"
#include "PxD6Joint.h"
#include "PxScene.h"
extern bool gDrawGroundPlane;
extern PxVec3 gGroupPlanePose;
extern float gGroundY;
SceneKapla::Weapon SceneKapla::mWeapon = wpBullet;
std::vector<Compound*> meteors;
extern bool LoadTexture(const char *filename, GLuint &texId, bool createMipmaps, GLuint type = GL_TEXTURE_2D, int *width = NULL, int *height = NULL);
// ----------------------------------------------------------------------------------------------
SceneKapla::SceneKapla(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
Shader *defaultShader, const char *resourcePath, float slowMotionFactor) :
SampleViewerScene(pxPhysics, pxCooking, isGrb, defaultShader, resourcePath, slowMotionFactor),
mDefaultContactOffset(0.02f), mDefaultRestOffset(0.0f)
{
mShaders.clear();
mFrameNr = 0;
mWeaponLifeTime = 500; // frames
mLaserImpulse = 0.0f;
mWeaponImpulse = 5.0f;
float minConvexSize = 0.02f;
mMeteorDistance = 10.0f;
mMeteorVelocity = 20.0f;
mMeteorSize = 1.0f;
mSimScene = SimScene::createSimScene(pxPhysics, pxCooking, isGrb, minConvexSize, mDefaultMaterial, resourcePath);
mSimScene->setContactImpactRadius(0.0f);
ShaderShadow::SHADER3D_CHOICES shader3d = ShaderShadow::COMBINE;
ShaderShadow::PS_MODE psMode = ShaderShadow::PS_SHADE3D;
mSimSceneShader = new ShaderShadow(ShaderShadow::VS_TEXINSTANCE, psMode, shader3d);
mSimSceneShader->init();
mShaders.push_back(mSimSceneShader);
ShaderMaterial mat;
mat.init();
// For asteroid
float bumpTextureUVScale = 0.1f;
float roughnessScale = 0.2f;
float extraNoiseScale = 2.0f;
LoadTexture("stoneBump.bmp", mat.texId, true);
mSimScene->setShaderMaterial(mSimSceneShader, mat);
mBulletMesh = PX_NEW(Mesh)();
mBulletMesh->loadFromObjFile(std::string(mResourcePath) + "\\bullet.obj");
mBulletMesh->normalize(PxVec3(0.0f, 0.0f, 0.0f), 0.6f);
mAsteroidMesh = PX_NEW(Mesh)();
mAsteroidMesh->loadFromObjFile(std::string(mResourcePath) + "\\asteroid.obj");
mGunActive = false;
mMouseX = 1024 / 2;
mMouseY = 768 / 2;
mMouseDown = false;
mPickQuadric = NULL;
mTerrain = NULL;
gDrawGroundPlane = false;
const PxVec3 dims(0.08f, 0.25f, 1.0f);
mSimScene->diffuseTexNames.push_back(std::string(mResourcePath) + "\\checker_tex0.bmp");
mSimScene->diffuseTexNames.push_back(std::string(mResourcePath) + "\\checker_tex1.bmp");
mSimScene->diffuseTexNames.push_back(std::string(mResourcePath) + "\\checker_tex2.bmp");
mSimScene->diffuseTexNames.push_back(std::string(mResourcePath) + "\\checker_tex3.bmp");
mSimScene->diffuseTexNames.push_back(std::string(mResourcePath) + "\\checker_tex4.bmp");
PxMaterial* DefaultMaterial = pxPhysics->createMaterial(0.4f, 0.15f, 0.1f);
mSimScene->setFractureForceThreshold(PX_MAX_F32);
mAsteroidMesh->normalize(PxVec3(0.0f, 0.0f, 0.0f), mMeteorSize);
debugDrawNumConvexes = 0;
mSimScene->createRenderBuffers();
}
void SceneKapla::onInit(PxScene* pxScene)
{
SampleViewerScene::onInit(pxScene);
mSimScene->setScene(pxScene);
}
void SceneKapla::setScene(PxScene* pxScene)
{
SampleViewerScene::setScene(pxScene); mSimScene->setScene(pxScene);
}
void SceneKapla::createGroundPlane(PxFilterData simFilterData, PxVec3 pose, PxFilterData queryFilterData)
{
// ground plane
PxRigidStatic* groundPlane = PxCreatePlane(*mPxPhysics, PxPlane(0, 1.f, 0, 0.f), *mDefaultMaterial);
gGroupPlanePose =pose;
PxTransform transform(gGroupPlanePose, groundPlane->getGlobalPose().q);
groundPlane->setGlobalPose(transform);
PxShape * groundShape;
groundPlane->getShapes(&groundShape, 1);
groundShape->setSimulationFilterData(simFilterData);
//groundShape->setContactOffset(mDefaultContactOffset);
//groundShape->setRestOffset(mDefaultRestOffset);
groundShape->setQueryFilterData(queryFilterData);
mPxScene->addActor(*groundPlane);
gDrawGroundPlane = true;
}
void SceneKapla::createTerrain(const char* terrainName, const char* textureName, PxReal maxHeight, bool invert)
{
string fullTerrainName = FindMediaFile(terrainName, mResourcePath);
string fullTerrainTexName = (strcmp(textureName, "") == 0) ? textureName:FindMediaFile(textureName, mResourcePath);
mTerrain = new TerrainMesh(getPhysics(), getCooking(), getScene(), *mDefaultMaterial, PxVec3(-1.0f, -30.85f, -1.0f), fullTerrainName.c_str(),
fullTerrainTexName.c_str(), 10.f, maxHeight, mDefaultShader, invert);
}
static void configD6Joint(PxReal swing0, PxReal swing1, PxReal twistLo, PxReal twistHi, PxD6Joint* joint)
{
joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eLIMITED);
joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eLIMITED);
joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eLIMITED);
joint->setSwingLimit(PxJointLimitCone(swing0, swing1));
joint->setTwistLimit(PxJointAngularLimitPair(twistLo, twistHi));
}
static void finishBody(PxRigidDynamic* dyn, PxReal density, PxReal inertiaScale)
{
dyn->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
dyn->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*dyn, density);
dyn->setMassSpaceInertiaTensor(dyn->getMassSpaceInertiaTensor() * inertiaScale);
dyn->setAngularDamping(0.15f);
}
void SceneKapla::createRagdoll(PxVec3 pos, PxVec3 vel, ShaderMaterial& mat)
{
PxVec3 tempVel = vel;
vel = vel * 0.75f;
PxReal density = 4.f;
//Head (a sphere)
PxPhysics* physics = getSimScene()->getPxPhysics();
mSimScene->getCompoundCreator()->createSphere(PxVec3(0.4f), 4); //Spheres defined by dims - not radius!
Compound* head = createObject(PxTransform(pos + PxVec3(0.f, 0.9f, 0.f)), vel, PxVec3(0), false, mat);
mSimScene->getCompoundCreator()->createCylinder(0.1f, 0.25f, 10);
Compound* neck = createObject(PxTransform(pos + PxVec3(0.f, 0.65f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(1.f, 0.f, 0.f))), vel, PxVec3(0), false, mat);
PxRigidDynamic* headBody = head->getPxActor();
PxRigidDynamic* neckBody = neck->getPxActor();
finishBody(headBody, density, 4.f);
finishBody(neckBody, density, 4.f);
PxD6Joint *neckJoint = PxD6JointCreate(*physics, headBody,
headBody->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, 0.75f, -0.05f))), neckBody, neckBody->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, 0.75f, -0.05f))));
configD6Joint(3.14 / 8.f, 3.14f / 8.f, -3.14f / 8.f, 3.14f / 8.f, neckJoint);
mSimScene->getCompoundCreator()->createCylinder(0.25f, 0.55f, 10);
Compound* upperTorso = createObject(PxTransform(pos + PxVec3(0.f, 0.375f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), tempVel, PxVec3(0), false, mat);
mSimScene->getCompoundCreator()->createCylinder(0.2f, 0.45f, 10);
Compound* lowerTorso = createObject(PxTransform(pos + PxVec3(0.f, 0.075f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), tempVel, PxVec3(0), false, mat);
Compound* hips = createObject(PxTransform(pos + PxVec3(0.f, -0.225f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), tempVel, PxVec3(0), false, mat);
finishBody(upperTorso->getPxActor(), density, 4.f);
finishBody(lowerTorso->getPxActor(), density, 4.f);
finishBody(hips->getPxActor(), density, 4.f);
PxD6Joint *neckTorsoJoint = PxD6JointCreate(*physics, neckBody,
neckBody->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, 0.6f, -0.05f))), upperTorso->getPxActor(), upperTorso->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, 0.6f, -0.05f))));
configD6Joint(3.14 / 8.f, 3.14f / 8.f, -3.14f / 8.f, 3.14f / 8.f, neckTorsoJoint);
PxD6Joint *TorsoTorsoJoint = PxD6JointCreate(*physics, upperTorso->getPxActor(),
upperTorso->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, 0.25f, -0.1f))), lowerTorso->getPxActor(),
lowerTorso->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, 0.25f, -0.1f))));
configD6Joint(3.14 / 4.f, 3.14f / 4.f, -3.14f / 4.f, 3.14f / 4.f, neckTorsoJoint);
PxD6Joint *hipTorsoJoint = PxD6JointCreate(*physics, lowerTorso->getPxActor(),
lowerTorso->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, -0.1f, -0.1f))), hips->getPxActor(),
hips->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, -0.1f, -0.1f))));
configD6Joint(3.14 / 4.f, 3.14f / 4.f, -3.14f / 4.f, 3.14f / 4.f, neckTorsoJoint);
mSimScene->getCompoundCreator()->createCylinder(0.1f, 0.55f, 10);
Compound* leftShoulder = createObject(PxTransform(pos + PxVec3(-0.48f, 0.375f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), vel, PxVec3(0), false, mat);
Compound* rightShoulder = createObject(PxTransform(pos + PxVec3(0.48f, 0.375f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), vel, PxVec3(0), false, mat);
finishBody(leftShoulder->getPxActor(), density, 4.f);
finishBody(rightShoulder->getPxActor(), density, 4.f);
PxD6Joint *leftShoulderJoint = PxD6JointCreate(*physics, upperTorso->getPxActor(),
upperTorso->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.28f, 0.375f, 0.f))),
leftShoulder->getPxActor(), leftShoulder->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.28f, 0.375f, 0.f))));
configD6Joint(3.14 / 2.5f, 3.14f / 2.5f, -3.14f / 2.5f, 3.14f / 2.5f, leftShoulderJoint);
PxD6Joint *rightShoulderJoint = PxD6JointCreate(*physics, upperTorso->getPxActor(),
upperTorso->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.28f, 0.375f, -0.f))),
rightShoulder->getPxActor(), rightShoulder->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.28f, 0.375f, -0.f))));
configD6Joint(3.14 / 2.5f, 3.14f / 2.5f, -3.14f / 2.5f, 3.14f / 2.5f, rightShoulderJoint);
Compound* leftForearm = createObject(PxTransform(pos + PxVec3(-0.88f, 0.375f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), vel, PxVec3(0), false, mat);
Compound* rightForearm = createObject(PxTransform(pos + PxVec3(0.88f, 0.375f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), vel, PxVec3(0), false, mat);
finishBody(leftForearm->getPxActor(), density, 4.f);
finishBody(rightForearm->getPxActor(), density, 4.f);
PxD6Joint *leftElbowJoint = PxD6JointCreate(*physics, leftShoulder->getPxActor(),
leftShoulder->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.68f, 0.375f, 0.0f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))),
leftForearm->getPxActor(), leftForearm->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.68f, 0.375f, 0.f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))));
configD6Joint(3.14 / 16.f, 3.14f / 16.f, -3.14 / 16.f, 3.14f / 2.5f, leftElbowJoint);
PxD6Joint *rightElbowJoint = PxD6JointCreate(*physics, rightShoulder->getPxActor(),
rightShoulder->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.68f, 0.375f, -0.f), PxQuat(3.141592f/2.f, PxVec3(0.f, 1.f, 0.f)))),
rightForearm->getPxActor(), rightForearm->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.68f, 0.375f, -0.f), PxQuat(3.141592f/2.f, PxVec3(0.f, 1.f, 0.f)))));
configD6Joint(3.14 / 16.f, 3.14f / 16.f, -3.14 / 16.f, 3.14f / 2.5f, rightElbowJoint);
mSimScene->getCompoundCreator()->createBox(PxVec3(0.2f, 0.05f, 0.2f));
Compound* leftHand = createObject(PxTransform(pos + PxVec3(-1.18f, 0.375f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), vel, PxVec3(0), false, mat);
Compound* rightHand = createObject(PxTransform(pos + PxVec3(1.18f, 0.375f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), vel, PxVec3(0), false, mat);
finishBody(leftHand->getPxActor(), density, 4.f);
finishBody(rightHand->getPxActor(), density, 4.f);
PxD6Joint *leftWristJoint = PxD6JointCreate(*physics, leftForearm->getPxActor(),
leftForearm->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-1.13f, 0.375f, 0.0f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))),
leftHand->getPxActor(), leftHand->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-1.13f, 0.375f, 0.f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))));
configD6Joint(3.14 / 8.f, 3.14f / 8.f, -3.14 / 2.f, 3.14f / 2.f, leftWristJoint);
PxD6Joint *rightWristJoint = PxD6JointCreate(*physics, rightForearm->getPxActor(),
rightForearm->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(1.13f, 0.375f, 0.0f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))),
rightHand->getPxActor(), rightHand->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(1.13f, 0.375f, 0.f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))));
configD6Joint(3.14 / 8.f, 3.14f / 8.f, -3.14 / 2.f, 3.14f / 2.f, rightWristJoint);
mSimScene->getCompoundCreator()->createCylinder(0.125f, 0.7f, 10);
Compound* leftThigh = createObject(PxTransform(pos + PxVec3(-0.15f, -0.7f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(1.f, 0.f, 0.f))), vel, PxVec3(0), false, mat);
Compound* rightThigh = createObject(PxTransform(pos + PxVec3(0.15f, -0.7f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(1.f, 0.f, 0.f))), vel, PxVec3(0), false, mat);
finishBody(leftThigh->getPxActor(), density, 4.f);
finishBody(rightThigh->getPxActor(), density, 4.f);
PxD6Joint *leftHipJoint = PxD6JointCreate(*physics, hips->getPxActor(),
hips->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.15f, -0.4f, 0.f))),
leftThigh->getPxActor(), leftThigh->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.15f, -0.4f, 0.f))));
configD6Joint(3.14 / 2.5f, 3.14f / 2.5f, -3.14f / 2.5f, 3.14f / 2.5f, leftHipJoint);
PxD6Joint *rightHipJoint = PxD6JointCreate(*physics, hips->getPxActor(),
hips->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.15f, -0.4f, 0.f))),
rightThigh->getPxActor(), rightThigh->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.15f, -0.4f, 0.f))));
configD6Joint(3.14 / 2.5f, 3.14f / 2.5f, -3.14f / 2.5f, 3.14f / 2.5f, rightHipJoint);
mSimScene->getCompoundCreator()->createCylinder(0.1f, 0.7f, 10);
Compound* leftShin = createObject(PxTransform(pos + PxVec3(-0.15f, -1.3f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(1.f, 0.f, 0.f))), vel, PxVec3(0), false, mat);
Compound* rightShin = createObject(PxTransform(pos + PxVec3(0.15f, -1.3f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(1.f, 0.f, 0.f))), vel, PxVec3(0), false, mat);
finishBody(leftShin->getPxActor(), density, 4.f);
finishBody(rightShin->getPxActor(), density, 4.f);
PxD6Joint *leftKneeJoint = PxD6JointCreate(*physics, leftThigh->getPxActor(),
leftThigh->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.15f, -1.f, 0.0f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))),
leftShin->getPxActor(), leftShin->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.15f, -1.f, 0.f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))));
configD6Joint(3.14 / 16.f, 3.14f / 16.f, -3.14 / 16.f, 3.14f / 2.5f, leftKneeJoint);
PxD6Joint *rightKneeJoint = PxD6JointCreate(*physics, rightThigh->getPxActor(),
rightThigh->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.15f, -1.f, 0.0f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))),
rightShin->getPxActor(), rightShin->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.15f, -1.f, 0.f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))));
configD6Joint(3.14 / 16.f, 3.14f / 16.f, -3.14 / 16.f, 3.14f / 2.5f, rightKneeJoint);
mSimScene->getCompoundCreator()->createBox(PxVec3(0.2f, 0.1f, 0.4f));
Compound* leftFoot = createObject(PxTransform(pos + PxVec3(-0.15f, -1.65f, 0.15f)), vel, PxVec3(0), false, mat);
Compound* rightFoot = createObject(PxTransform(pos + PxVec3(0.15f, -1.65f, 0.15f)), vel, PxVec3(0), false, mat);
finishBody(leftFoot->getPxActor(), density, 4.f);
finishBody(rightFoot->getPxActor(), density, 4.f);
PxD6Joint *leftAnkle = PxD6JointCreate(*physics, leftShin->getPxActor(),
leftShin->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.15f, -1.6f, 0.0f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))),
leftFoot->getPxActor(), leftFoot->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.15f, -1.6f, 0.f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))));
configD6Joint(3.14 / 16.f, 3.14f / 16.f, -3.14 / 16.f, 3.14f / 8.f, leftAnkle);
PxD6Joint *rightAnkle = PxD6JointCreate(*physics, rightShin->getPxActor(),
rightShin->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.15f, -1.6f, 0.0f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))),
rightFoot->getPxActor(), rightFoot->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.15f, -1.6f, 0.f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))));
configD6Joint(3.14 / 16.f, 3.14f / 16.f, -3.14 / 16.f, 3.14f / 8.f, rightAnkle);
}
void SceneKapla::createCylindricalTower(PxU32 nbRadialPoints, PxReal maxRadius, PxReal minRadius, PxU32 height, PxVec3 dims, PxVec3 centerPos, PxMaterial* material, ShaderMaterial& mat,
PxFilterData& simFilterData, PxFilterData& queryFilterData, PxReal density, bool bUseSweeps, bool bStartAsleep)
{
PxShape* shape;
PxVec3 vel(0), omega(0);
mSimScene->getCompoundCreator()->createBox(2.f*dims);//0.5f, 0.2f, 20, 20);
PxReal startHeight = 0.f;
PxTransform objectTransform(PxVec3(3.172 - 2.3 - 39.87), PxQuat());
for (PxU32 i = 0; i < height; ++i)
{
PxReal radius = minRadius + (maxRadius - minRadius) * (1.f - PxReal(i) / PxReal(height));
for (PxU32 a = 0; a < nbRadialPoints; ++a)
{
PxF32 angle = 6.28f*PxF32(a) / PxF32(nbRadialPoints);
PxVec3 innerPos(cosf(angle)*radius, dims.y + startHeight, sinf(angle)*radius);
PxQuat rot(3.14 / 2.f - angle, PxVec3(0.f, 1.f, 0.f));
PxTransform transform(innerPos + centerPos, rot);
Compound* compound = createObject(transform, vel, omega, false, mat);
PxRigidDynamic* innerBox = compound->getPxActor();
innerBox->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
shape->setQueryFilterData(queryFilterData);
shape->setSimulationFilterData(simFilterData);
innerBox->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
innerBox->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*innerBox, density);
innerBox->setMassSpaceInertiaTensor(innerBox->getMassSpaceInertiaTensor() * 4.f);
if (bStartAsleep)
innerBox->putToSleep();
}
PxReal innerCircumference = (radius - (dims.z - dims.x)) * 3.1415928 * 2.f;
PxReal midCircumference = (radius)* 3.1415928 * 2.f;
PxReal outerCircumference = (radius + (dims.z - dims.x)) * 3.1415928 * 2.f;
PxU32 nbInnerSlabs = innerCircumference / (dims.z * 2);
PxU32 nbMidSlabs = midCircumference / (dims.z * 2);
PxU32 nbOuterSlabs = outerCircumference / (dims.z * 2);
for (PxU32 a = 0; a < nbInnerSlabs; a++)
{
PxF32 angle = 6.28f*PxF32(a) / PxF32(nbInnerSlabs);
PxVec3 innerPos(cosf(angle)*(radius - (dims.z - dims.x)), 3.f * dims.y + startHeight, sinf(angle)*(radius - (dims.z - dims.x)));
PxQuat rot(-angle, PxVec3(0.f, 1.f, 0.f));
Compound* compound = createObject(PxTransform(innerPos + centerPos, rot), vel, omega, false, mat);
PxRigidDynamic* innerBox = compound->getPxActor();
innerBox->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
shape->setQueryFilterData(queryFilterData);
shape->setSimulationFilterData(simFilterData);
innerBox->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
innerBox->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*innerBox, density);
innerBox->setMassSpaceInertiaTensor(innerBox->getMassSpaceInertiaTensor() * 4.f);
if (bStartAsleep)
innerBox->putToSleep();
}
for (PxU32 a = 0; a < nbMidSlabs; a++)
{
PxF32 angle = 6.28f*PxF32(a) / PxF32(nbMidSlabs);
PxVec3 innerPos(cosf(angle)*(radius), 3.f * dims.y + startHeight, sinf(angle)*(radius));
PxQuat rot(-angle, PxVec3(0.f, 1.f, 0.f));
Compound* compound = createObject(PxTransform(innerPos + centerPos, rot), vel, omega, false, mat);
PxRigidDynamic* innerBox = compound->getPxActor();
innerBox->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
shape->setQueryFilterData(queryFilterData);
shape->setSimulationFilterData(simFilterData);
innerBox->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
innerBox->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*innerBox, density);
innerBox->setMassSpaceInertiaTensor(innerBox->getMassSpaceInertiaTensor() * 4.f);
if (bStartAsleep)
innerBox->putToSleep();
}
for (PxU32 a = 0; a < nbOuterSlabs; a++)
{
PxF32 angle = 6.28f*PxF32(a) / PxF32(nbOuterSlabs);
PxVec3 outerPos(cosf(angle)*(radius + (dims.z - dims.x)), 3.f * dims.y + startHeight, sinf(angle)*(radius + (dims.z - dims.x)));
PxQuat rot(-angle, PxVec3(0.f, 1.f, 0.f));
Compound* compound = createObject(PxTransform(outerPos + centerPos, rot), vel, omega, false, mat);
PxRigidDynamic* outerBox = compound->getPxActor();
outerBox->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
shape->setQueryFilterData(queryFilterData);
shape->setSimulationFilterData(simFilterData);
outerBox->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
outerBox->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*outerBox, density);
outerBox->setMassSpaceInertiaTensor(outerBox->getMassSpaceInertiaTensor() * 4.f);
if (bStartAsleep)
outerBox->putToSleep();
}
startHeight += 4.f * dims.y;
density *= 0.975f;
}
//Now place the lid on the structure...
PxReal midCircumference = (minRadius - dims.z) * 3.1415928 * 2.f;
PxU32 nbMidSlabs = midCircumference / (dims.y * 2);
PxQuat baseRotation(3.1415 / 2.f, PxVec3(0.f, 0.f, 1.f));
for (PxU32 a = 0; a < nbMidSlabs; ++a)
{
const PxF32 angle = 6.28f*PxF32(a) / PxF32(nbMidSlabs);
PxVec3 innerPos(cosf(angle)*minRadius, dims.x + startHeight, sinf(angle)*minRadius);
PxQuat rot(3.14 / 2.f - angle, PxVec3(0.f, 1.f, 0.f));
Compound* compound = createObject(PxTransform(innerPos + centerPos, rot*baseRotation), vel, omega, false, mat);
PxRigidDynamic* innerBox = compound->getPxActor();
innerBox->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
shape->setQueryFilterData(queryFilterData);
shape->setSimulationFilterData(simFilterData);
innerBox->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
innerBox->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*innerBox, density);
innerBox->setMassSpaceInertiaTensor(innerBox->getMassSpaceInertiaTensor() * 4.f);
if (bStartAsleep)
innerBox->putToSleep();
}
}
// ----------------------------------------------------------------------------------------------
std::string SceneKapla::getWeaponName()
{
switch (mWeapon) {
case wpBullet : return "Bullet";
case wpBall : return "Ball";
case wpMeteor : return "Meteor";
}
return "";
}
// ----------------------------------------------------------------------------------------------
Compound* SceneKapla::createObject(const PxVec3 &pos, const PxVec3 &vel, const PxVec3 &omega,
bool particles, const ShaderMaterial &mat, bool useSecondaryPattern, ShaderShadow* shader, int matID, int surfMatID)
{
Compound *cp = (Compound*)mSimScene->createCompound(mDefaultContactOffset, mDefaultRestOffset);
PxTransform pose(pos);
cp->createFromGeometry(mSimScene->getCompoundCreator()->getGeometry(), pose, vel, omega, shader, matID, surfMatID);
cp->setShader(shader ? shader : mSimSceneShader, mat);
mSimScene->addCompound(cp);
return cp;
}
Compound* SceneKapla::createObject(const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega,
bool particles, const ShaderMaterial &mat, bool useSecondaryPattern, ShaderShadow* shader, int matID, int surfMatID)
{
Compound *cp = (Compound*)mSimScene->createCompound(mDefaultContactOffset, mDefaultRestOffset);
ShaderShadow* myShader = shader ? shader : mSimSceneShader;
cp->createFromGeometry(mSimScene->getCompoundCreator()->getGeometry(), pose, vel, omega, myShader, matID, surfMatID);
cp->setShader(shader ? shader : mSimSceneShader, mat);
mSimScene->addCompound(cp);
return cp;
}
Compound* SceneKapla::createObject(PxRigidDynamic* body, const ShaderMaterial &mat, ShaderShadow* shader, int matID, int surfMatID)
{
Compound *cp = (Compound*)mSimScene->createCompound(mDefaultContactOffset, mDefaultRestOffset);
ShaderShadow* myShader = shader ? shader : mSimSceneShader;
cp->createFromGeometry(mSimScene->getCompoundCreator()->getGeometry(), body, myShader, matID, surfMatID);
cp->setShader(shader ? shader : mSimSceneShader, mat);
mSimScene->addCompound(cp);
return cp;
}
// ----------------------------------------------------------------------------------------------
SceneKapla::~SceneKapla()
{
if (mTerrain) delete mTerrain;
mTerrain = NULL;
if (mSimScene != NULL)
delete mSimScene;
if (mPickQuadric != NULL)
gluDeleteQuadric(mPickQuadric);
if (mBulletMesh)
delete mBulletMesh;
if (mAsteroidMesh)
delete mAsteroidMesh;
meteors.clear();
}
// ----------------------------------------------------------------------------------------------
void SceneKapla::preSim(float dt)
{
if (mSimScene)
mSimScene->preSim(dt);
if (meteors.size() > 0)
{
/*static vector<PxVec3> sites;
sites.clear();*/
int num = 0;
const int numSamples = 20;
for (int i = 0; i < (int)meteors.size(); i++)
{
if (meteors[i]->getLifeFrames() > 1 && meteors[i]->getPxActor() != NULL)
{
meteors[num] = meteors[i];
num++;
}
}
meteors.resize(num);
}
}
// ----------------------------------------------------------------------------------------------
void SceneKapla::postSim(float dt)
{
if (mSimScene)
mSimScene->postSim(dt, NULL);
mFrameNr++;
}
// ----------------------------------------------------------------------------------------------
void SceneKapla::handleMouseButton(int button, int state, int x, int y)
{
mMouseX = x;
mMouseY = y;
mMouseDown = (state == GLUT_DOWN);
PxVec3 orig, dir;
getMouseRay(x,y, orig, dir);
if (glutGetModifiers() & GLUT_ACTIVE_SHIFT) {
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
if (mSimScene)
mSimScene->pickStart(orig, dir);
}
}
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
if (mSimScene)
mSimScene->pickRelease();
}
}
// ----------------------------------------------------------------------------------------------
void SceneKapla::handleMouseMotion(int x, int y)
{
mMouseX = x;
mMouseY = y;
if (mSimScene && mSimScene->getPickActor() != NULL) {
PxVec3 orig, dir;
getMouseRay(x,y, orig, dir);
mSimScene->pickMove(orig, dir);
}
}
//ofstream orays("ray.txt");
// ----------------------------------------------------------------------------------------------
void SceneKapla::handleKeyDown(unsigned char key, int x, int y)
{
switch (key) {
case ' ':
{
if (!mGunActive)
{
float vel = 1.0f;
PxVec3 orig, dir;
getMouseRay(mMouseX, mMouseY, orig, dir);
/*
float sx = 0.0f, sy = 30.0f, sz = 0.0f;
int nx = 10;
int ny = 10;
float dx = 1.0f;
for (int i = 0; i < ny; i++) {
for (int j = 0; j < nx; j++) {
shoot(PxVec3(sx+j*dx, sy, sz + i*dx), PxVec3(0.0f,1.0f,0.0f));
}
}
*/
shoot(mCameraPos, dir);
}
mGunActive = true;
//orays<<"{"<<mCameraPos.x<<","<<mCameraPos.y<<","<<mCameraPos.z<<","<<dir.x<<","<<dir.y<<","<<dir.z<<"},\n";
//orays.flush();
//printf("{%f,%f,%f,%f,%f,%f},\n ", mCameraPos.x, mCameraPos.y, mCameraPos.z, dir.x, dir.y, dir.z);
break;
}
/*
case 'j':
{
mSimScene->dumpSceneGeometry();
break;
}
*/
}
}
// ----------------------------------------------------------------------------------------------
void SceneKapla::handleKeyUp(unsigned char key, int x, int y)
{
switch (key) {
case 'v':
if (mSimScene) mSimScene->toggleDebugDrawing(); break;
case ' ':
{
mGunActive = false;
}
}
}
// ----------------------------------------------------------------------------------------------
void SceneKapla::handleSpecialKey(unsigned char key, int x, int y)
{
switch (key)
{
case GLUT_KEY_F4: mWeapon = (Weapon)(((int)mWeapon+1)%numWeapons); break;
}
}
// ----------------------------------------------------------------------------------------------
void SceneKapla::shoot(PxVec3 &orig, PxVec3 &dir)
{
if (mSimScene == NULL)
return;
mGunActive = true;
if (mWeapon == wpBall || mWeapon == wpBullet || mWeapon == wpMeteor) {
PxVec3 dims(0.4f, 0.4f, 0.4f);
Compound* cp = (Compound*)mSimScene->createCompound( mDefaultContactOffset, mDefaultRestOffset); // invincible
PxTransform pose = PX_TRANSFORM_ID;
PxVec3 vel, omega;
omega = PxVec3(0.0f, 0.0f, 0.0f);
if (mWeapon == wpMeteor)
{
float idist = 1000.f;
PxRaycastBuffer buffer;
if (getScene().raycast(orig, dir, idist, buffer, PxHitFlag::eDEFAULT, PxQueryFilterData(PxQueryFlag::eDYNAMIC)))
idist = buffer.getAnyHit(0).distance;
PxVec3 impactPos = orig + dir*idist;
PxVec3 cameraRight = mCameraDir.cross(mCameraUp);
const float angle = 45.0f * physx::PxPi / 180.0f;
const float distance = mMeteorDistance;
PxVec3 meteorDirection = cos(angle)*cameraRight + sin(angle)*mCameraUp;
pose.p = impactPos + meteorDirection*distance;
vel = -meteorDirection*mMeteorVelocity* mSlowMotionFactor;
}
else
{
{
pose.p = mCameraPos;
PxVec3 a0;
if (fabs(dir.x) < fabs(dir.y) && fabs(dir.x) < fabs(dir.z))
a0 = PxVec3(1.0f, 0.0f, 0.0f);
else if (fabs(dir.y) < fabs(dir.z))
a0 = PxVec3(0.f, 1.0f, 0.0f);
else
a0 = PxVec3(0.0f, 0.0f, 1.0f);
PxVec3 a1 = dir.cross(a0);
a1.normalize();
a0 = a1.cross(dir);
pose.q = PxQuat(PxMat33(a1, dir, a0));
float dist = 1000.0f;
vel = orig + dir * dist - mCameraPos;
vel.normalize();
}
vel *= 30.0f * mSlowMotionFactor;
}
//vel *= 0.0f;
ShaderMaterial mat;
mat.init();
mat.color[0] = 0.9f;
mat.color[1] = 0.2f;
mat.color[2] = 0.2f;
cp->setShader(NULL, mat);
if (mWeapon == wpMeteor)
{
vel *= 2.0f;
PxVec3 a0;
PxVec3 dir = vel;
dir.normalize();
if (fabs(dir.x) < fabs(dir.y) && fabs(dir.x) < fabs(dir.z))
a0 = PxVec3(1.0f, 0.0f, 0.0f);
else if (fabs(dir.y) < fabs(dir.z))
a0 = PxVec3(0.f, 1.0f, 0.0f);
else
a0 = PxVec3(0.0f, 0.0f, 1.0f);
PxVec3 a1 = dir.cross(a0);
a1.normalize();
a0 = a1.cross(dir);
pose.q = PxQuat(PxMat33(dir, a0, a1)).getNormalized();
const float maxRot = 50.0f;
omega = PxVec3(randRange(-maxRot, maxRot),randRange(-maxRot, maxRot),randRange(-maxRot, maxRot));
mAsteroidMesh->normalize(PxVec3(0.0f, 0.0f, 0.0f), mMeteorSize);
cp->createFromMesh(mAsteroidMesh, pose, vel, omega);
cp->getPxActor()->setMass(10000000.0f);
cp->getPxActor()->setMaxContactImpulse(2.5f);
cp->getPxActor()->setMaxDepenetrationVelocity(1.f);
cp->setKinematic(vel);
cp->setLifeFrames(mWeaponLifeTime);
cp->setAdditionalImpactImpulse(mWeaponImpulse, mWeaponImpulse);
meteors.push_back(cp);
}
else if (mWeapon == wpBall)
{
mSimScene->getCompoundCreator()->createSphere(dims, 8);
cp->createFromGeometry(mSimScene->getCompoundCreator()->getGeometry(), pose, vel, omega, NULL);
PxRigidBodyExt::updateMassAndInertia(*cp->getPxActor(), 1000.f);
cp->getPxActor()->setAngularDamping(0.75f);
}
else
{
cp->createFromMesh(mBulletMesh, pose, vel, omega);
cp->setKinematic(vel);
cp->setLifeFrames(mWeaponLifeTime);
cp->setAdditionalImpactImpulse(mWeaponImpulse, mWeaponImpulse);
}
mSimScene->addCompound(cp);
}
}
// ----------------------------------------------------------------------------------------------
void SceneKapla::render(bool useShader)
{
SampleViewerScene::render(useShader);
if (mSimScene != NULL) {
mSimScene->setCamera( mCameraPos, mCameraDir, mCameraUp, mCameraFov );
mSimScene->draw(useShader);
}
if (useShader && mTerrain) {
mTerrain->draw(useShader);
}
pickDraw();
//if (useShader)
//renderCrossLines();
// mFracPattern.getGeometry().debugDraw();
}
//-----------------------------------------------------------------------------
void SceneKapla::pickDraw()
{
if (mSimScene && mSimScene->getPickActor() == NULL)
return;
PxRigidDynamic *pickActor = mSimScene->getPickActor();
float r = 0.05f;
if (mPickQuadric == NULL) {
mPickQuadric = gluNewQuadric();
gluQuadricDrawStyle(mPickQuadric, GLU_FILL);
}
glColor3f(1.0f, 0.0f, 0.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
const PxVec3 &pickPos = mSimScene->getPickPos();
glTranslatef(pickPos.x, pickPos.y, pickPos.z);
gluSphere(mPickQuadric, r, 10, 10);
glPopMatrix();
PxVec3 pos = pickActor->getGlobalPose().transform(mSimScene->getPickLocalPos());
glColor3f(1.0f, 0.0f, 0.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(pos.x, pos.y, pos.z);
gluSphere(mPickQuadric, r, 10, 10);
glPopMatrix();
glBegin(GL_LINES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(pickPos.x, pickPos.y, pickPos.z);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(pos.x, pos.y, pos.z);
glEnd();
glColor3f(1, 1, 1);
}
//-----------------------------------------------------------------------------
void SceneKapla::printPerfInfo()
{
if (mSimScene != NULL) {
printf("num SDK bodies %i\n", mSimScene->getCompounds().size());
/* if(mSimScene->getParticles())
printf("num particles %i\n", mSimScene->getParticles()->getNumParticles());*/
}
}

View File

@ -0,0 +1,149 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef SCENE_FRACTURE_H
#define SCENE_FRACTURE_H
#include "SampleViewerScene.h"
#include "Compound.h"
#include "Shader.h"
#include "foundation/PxVec3.h"
#include "PhysXMacros.h"
#include "PxFiltering.h"
extern int DEFAULT_SOLVER_ITERATIONS;
using namespace physx;
class GLUquadric;
class Particles;
class ShaderShadow;
class SimScene;
class Mesh;
class RegularCell3D;
class TerrainMesh;
// ---------------------------------------------------------------------
class SceneKapla : public SampleViewerScene
{
public:
SceneKapla(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
Shader *defaultShader, const char *resourcePath, float slowMotionFactor);
virtual ~SceneKapla();
virtual void preSim(float dt);
virtual void postSim(float dt);
virtual void handleMouseButton(int button, int state, int x, int y);
virtual void handleMouseMotion(int x, int y);
virtual void handleKeyDown(unsigned char key, int x, int y);
virtual void handleKeyUp(unsigned char key, int x, int y);
virtual void handleSpecialKey(unsigned char key, int x, int y);
virtual void render(bool useShader);
virtual void printPerfInfo();
SimScene* getSimScene() {return mSimScene;}
ShaderShadow* getSimSceneShader() {return mSimSceneShader;}
virtual std::string getWeaponName();
virtual bool isSceneKapla() {return true;}
void shoot(PxVec3 &orig, PxVec3 &dir);
void createCylindricalTower(PxU32 nbRadialPoints, PxReal maxRadius, PxReal minRadius, PxU32 height, PxVec3 dims, PxVec3 centerPos, PxMaterial* material, ShaderMaterial& mat,
PxFilterData& simFilterData, PxFilterData& queryFilterData, PxReal density = 1.f, const bool useSweep = false, bool startAsleep = false);
void createWall(PxReal radius, PxU32 height, PxVec3 dims, PxVec3 centerPos, PxMaterial* material, ShaderMaterial& mat, PxFilterData& simFilterData, PxFilterData& queryFilterData,
PxReal density = 1.f);
void createGroundPlane(PxFilterData simFilterData = PxFilterData(), PxVec3 pose = PxVec3(0,0,0), PxFilterData queryFilterData = PxFilterData());
void createTerrain(const char* terrainName, const char* textureName, PxReal maxHeight = 30.f, bool invert = false);
void createRagdoll(PxVec3 pos, PxVec3 vel, ShaderMaterial& mat);
virtual void onInit(PxScene* pxScene);
virtual void setScene(PxScene* pxScene);
ShaderShadow* mSimSceneShader;
Compound* createObject(const PxVec3 &pos, const PxVec3 &vel, const PxVec3 &omega,
bool particles, const ShaderMaterial &mat, bool useSecondaryPattern = false, ShaderShadow* shader = NULL, int matID = 0, int surfMatID = 0);
Compound* createObject(const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega,
bool particles, const ShaderMaterial &mat, bool useSecondaryPattern = false, ShaderShadow* shader = NULL, int matID = 0, int surfMatID = 0);
Compound* createObject(PxRigidDynamic* body, const ShaderMaterial &mat, ShaderShadow* shader = NULL, int matID = 0, int surfMatID = 0);
protected:
void pickDraw();
GLUquadric *mPickQuadric;
SimScene *mSimScene;
//RegularCell3D* mFluidSim;
bool mGunActive;
int mMouseX;
int mMouseY;
bool mMouseDown;
int mFrameNr;
enum Weapon {
wpMeteor,
wpBullet,
wpBall,
numWeapons,
};
static Weapon mWeapon;
int mWeaponLifeTime;
Mesh *mBulletMesh;
Mesh *mAsteroidMesh;
float mMeteorDistance;
float mMeteorVelocity;
float mMeteorSize;
float mLaserImpulse;
float mWeaponImpulse;
PxReal mDefaultContactOffset;
PxReal mDefaultRestOffset;
int debugDrawNumConvexes;
TerrainMesh* mTerrain;
};
#endif // SCENE_BOXES_H

View File

@ -0,0 +1,78 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "SceneKaplaArena.h"
#include "Convex.h"
#include "PxSimpleFactory.h"
#include "PxRigidStatic.h"
#include "PxShape.h"
#include "foundation/PxMathUtils.h"
#include "foundation/PxMat44.h"
#include <stdio.h>
#include <GL/glut.h>
#include "SimScene.h"
#include "CompoundCreator.h"
#include "TerrainMesh.h"
#include "PhysXMacros.h"
#include "MathUtils.h"
#include "PxRigidBodyExt.h"
// ----------------------------------------------------------------------------------------------
SceneKaplaArena::SceneKaplaArena(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
Shader *defaultShader, const char *resourcePath, float slowMotionFactor) :
SceneKapla(pxPhysics, pxCooking, isGrb, defaultShader, resourcePath, slowMotionFactor)
{
//onInit(pxPhysics);
}
void SceneKaplaArena::onInit(PxScene* pxScene)
{
SceneKapla::onInit(pxScene);
createGroundPlane();
const PxVec3 dims(0.08f, 0.25f, 1.0f);
PxMaterial* DefaultMaterial = mPxPhysics->createMaterial(0.4f, 0.15f, 0.1f);
ShaderMaterial mat;
mat.init();
const PxU32 nbOuterRadialLayouts = 384;
const PxReal outerRadius = 40;
PxFilterData queryFilterData;
PxFilterData simFilterData;
createCylindricalTower(nbOuterRadialLayouts, outerRadius, outerRadius, 8, dims, PxVec3(0.f, 0.f, 0.f), DefaultMaterial, mat, simFilterData, queryFilterData);
createCylindricalTower(nbOuterRadialLayouts, outerRadius - 2.f, outerRadius - 2.f, 8, dims, PxVec3(0.f, 0.f, 0.f), DefaultMaterial, mat, simFilterData, queryFilterData);
}

View File

@ -0,0 +1,51 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#ifndef SCENE_KAPLA_ARENA_H
#define SCENE_KAPLA_ARENA_H
#include "SceneKapla.h"
using namespace physx;
// ---------------------------------------------------------------------
class SceneKaplaArena : public SceneKapla
{
public:
SceneKaplaArena(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
Shader *defaultShader, const char *resourcePath, float slowMotionFactor);
virtual ~SceneKaplaArena(){}
virtual void onInit(PxScene* pxScene);
private:
};
#endif // SCENE_BOXES_H

View File

@ -0,0 +1,718 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "SceneKaplaTower.h"
#include "Convex.h"
#include "PxSimpleFactory.h"
#include "PxRigidStatic.h"
#include "PxShape.h"
#include "foundation/PxMathUtils.h"
#include "foundation/PxMat44.h"
#include <stdio.h>
#include <GL/glut.h>
#include "SimScene.h"
#include "CompoundCreator.h"
#include "Mesh.h"
#include "TerrainMesh.h"
#include "PhysXMacros.h"
#include "MathUtils.h"
#include "PxRigidBodyExt.h"
#include "PxD6Joint.h"
static PxU32 gMaxNbPermittedProjectiles = 0;
#define PROJECTILES_USE_GOLD_MATERIAL 1
// ----------------------------------------------------------------------------------------------
SceneKaplaTower::SceneKaplaTower(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
Shader *defaultShader, const char *resourcePath, float slowMotionFactor) :
SceneKapla(pxPhysics, pxCooking, isGrb, defaultShader, resourcePath, slowMotionFactor)
{
hadInteraction = false;
mAccumulatedTime = -5.f;
nbProjectiles = 0;
}
static void finishBody(PxRigidDynamic* dyn, PxReal density, PxReal inertiaScale)
{
dyn->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
dyn->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*dyn, density);
dyn->setMassSpaceInertiaTensor(dyn->getMassSpaceInertiaTensor() * inertiaScale);
dyn->setAngularDamping(0.15f);
}
void SceneKaplaTower::preSim(float dt)
{
SceneKapla::preSim(dt);
}
void SceneKaplaTower::postSim(float dt)
{
if (hadInteraction)
{
mAccumulatedTime = -5.f;
hadInteraction = false;
}
mAccumulatedTime += dt;
if (mAccumulatedTime > 0.25f && nbProjectiles < gMaxNbPermittedProjectiles)
{
nbProjectiles++;
mAccumulatedTime = 0.f;
float wx = randRange(0.5f, 1.5f);
float wz = randRange(0.5f, 1.0f);
float h = randRange(0.5f, 0.8f);
ShaderMaterial mat;
mat.init();
PxReal angle = randRange(0.f, 3.14159*2.f); //Random direction...
PxReal range = randRange(30.f, 40.f);
PxVec3 pos(range * cosf(angle), 2.f, range * sinf(angle) - 22.f);
PxReal speed = randRange(10.f, 60.f);
PxVec3 vel = (PxVec3(0, 0, -22) - pos).getNormalized() * speed + PxVec3(0.f, 250.f/speed, 0.f);
PxVec3 omega(10.0f, 30.0f, 20.0f);
int randomNumber = rand();
bool createBody = true;
switch (randomNumber % 4)
{
case 0:
{
float r = randRange(0.1f, 0.2f);
float R = r + randRange(0.4f, 0.5f);
mSimScene->getCompoundCreator()->createTorus(R, r, 15, 10);
break;
}
case 1:
{
float minLen = 0.6f;
float maxLen = 0.9f;
PxVec3 dims(randRange(minLen, maxLen), randRange(minLen, maxLen), randRange(minLen, maxLen));
mSimScene->getCompoundCreator()->createBox(dims);
break;
}
case 2:
{
float r = randRange(0.5f, 0.5f);
float h = randRange(0.6f, 0.8f);
mSimScene->getCompoundCreator()->createCylinder(r, h, 15);
break;
}
case 3:
{
vel += PxVec3(0.f, 5.f, 0.f);
createRagdoll(pos, vel, mat);
createBody = false;
break;
}
}
if (createBody)
{
Compound* compound = createObject(pos, vel, omega, false, mat, false
#if PROJECTILES_USE_GOLD_MATERIAL
, 0, 1, 1
#endif
);
PxRigidDynamic* dyn = compound->getPxActor();
finishBody(dyn, 2.f, 1.f);
if ((randomNumber % 4) == 0)
{
PxU32 nbLinks = ((randomNumber / 4) & 3);
PxTransform trans(pos);
PxQuat deltaRot(3.1415f / 2.f, PxVec3(1.f, 0.f, 0.f));
for (PxU32 a = 1; a < nbLinks; ++a)
{
trans.q = (trans.q * deltaRot).getNormalized();
trans.p.x += 0.8f;
Compound* compound = createObject(trans, vel, omega, false, mat, false
#if PROJECTILES_USE_GOLD_MATERIAL
, 0, 1, 1
#endif
);
PxRigidDynamic* dyn = compound->getPxActor();
finishBody(dyn, 2.f, 1.f);
}
}
}
}
SceneKapla::postSim(dt);
}
void SceneKaplaTower::onInit(PxScene* pxScene)
{
SceneKapla::onInit(pxScene);
createGroundPlane();
mAccumulatedTime = 0.f;
const PxVec3 dims(0.08f, 0.25f, 1.0f);
PxMaterial* DefaultMaterial = mPxPhysics->createMaterial(0.5f, 0.25f, 0.1f);
ShaderMaterial mat;
mat.init();
const PxU32 nbInnerInnerRadialLayouts = 40;
const PxU32 nbInnerRadialLayouts = 48;
const PxU32 nbMidRadialLayouts = 72;
const PxU32 nbOuterRadialLayouts = 96;
const PxU32 nbOuterOuterRadialLayouts = 128;
const PxReal innerInnerRadius = 2.5f;
const PxReal innerRadius = 4.5f;
const PxReal midRadius = 6.5f;
const PxReal outerRadius = 8.5f;
const PxReal outerOuterRadius = 10.5f;
/*createRectangularTower(10, 10, 4, dims, PxVec3(10, 0.f, -30), DefaultMaterial, mat);
createRectangularTower(8, 8, 7, dims, PxVec3(10, 0.f, -30), DefaultMaterial, mat);
createRectangularTower(6, 6, 10, dims, PxVec3(10, 0.f, -30), DefaultMaterial, mat);
createRectangularTower(4, 4, 14, dims, PxVec3(10, 0.f, -30), DefaultMaterial, mat);
createRectangularTower(2, 2, 18, dims, PxVec3(10, 0.f, -30), DefaultMaterial, mat);*/
PxFilterData queryFilterData;
PxFilterData simFilterData;
createCylindricalTower(nbInnerInnerRadialLayouts, innerInnerRadius, innerInnerRadius, 22, dims, PxVec3(0, 0.f, -22), DefaultMaterial, mat, simFilterData, queryFilterData,1,false,true);
createCylindricalTower(nbInnerRadialLayouts, innerRadius, innerRadius, 15, dims, PxVec3(0, 0.f, -22), DefaultMaterial, mat, simFilterData, queryFilterData, 1, false, true);
createCylindricalTower(nbMidRadialLayouts, midRadius, midRadius, 11, dims, PxVec3(0, 0.f, -22), DefaultMaterial, mat, simFilterData, queryFilterData, 1, false, true);
createCylindricalTower(nbOuterRadialLayouts, outerRadius, outerRadius, 8, dims, PxVec3(0, 0.f, -22), DefaultMaterial, mat, simFilterData, queryFilterData, 1, false, true);
createCylindricalTower(nbOuterOuterRadialLayouts, outerOuterRadius, outerOuterRadius, 6, dims, PxVec3(0, 0.f, -22), DefaultMaterial, mat, simFilterData, queryFilterData, 1, false, true);
createTwistTower(30, 6, dims, PxVec3(13, 0, -28), DefaultMaterial, mat);
createTwistTower(30, 6, dims, PxVec3(13, 0, -23), DefaultMaterial, mat);
createTwistTower(30, 6, dims, PxVec3(13, 0, -18), DefaultMaterial, mat);
createTwistTower(30, 6, dims, PxVec3(13, 0, -13), DefaultMaterial, mat);
const PxReal capRadius = PxSqrt(dims.z*dims.z + dims.z*dims.z);
mSimScene->getCompoundCreator()->createCylinder(capRadius, 2*dims.y, 20);
Compound* compound0 = createObject(PxTransform(PxVec3(-20, dims.y + 15 * 2 * dims.y, -35.5), PxQuat(3.1415 / 2.f, PxVec3(1.f, 0.f, 0.f))), PxVec3(0), PxVec3(0), false, mat);
Compound* compound1 = createObject(PxTransform(PxVec3(20, dims.y + 15 * 2 * dims.y, -35.5), PxQuat(3.1415 / 2.f, PxVec3(1.f, 0.f, 0.f))), PxVec3(0), PxVec3(0), false, mat);
Compound* compound2 = createObject(PxTransform(PxVec3(-20, dims.y + 15 * 2 * dims.y, -9.5), PxQuat(3.1415 / 2.f, PxVec3(1.f, 0.f, 0.f))), PxVec3(0), PxVec3(0), false, mat);
Compound* compound3 = createObject(PxTransform(PxVec3(20, dims.y + 15 * 2 * dims.y, -9.5), PxQuat(3.1415 / 2.f, PxVec3(1.f, 0.f, 0.f))), PxVec3(0), PxVec3(0), false, mat);
PxRigidDynamic* cylinder0 = compound0->getPxActor();
PxRigidDynamic* cylinder1 = compound1->getPxActor();
PxRigidDynamic* cylinder2 = compound2->getPxActor();
PxRigidDynamic* cylinder3 = compound3->getPxActor();
finishBody(cylinder0, 0.2f, 4.f);
finishBody(cylinder1, 0.2f, 4.f);
finishBody(cylinder2, 0.2f, 4.f);
finishBody(cylinder3, 0.2f, 4.f);
createGeometricTower(15, 4, dims, PxVec3(-20, 0, -35.5), 1.f, DefaultMaterial, mat);
createGeometricTower(15, 4, dims, PxVec3(20, 0, -35.5), 1.f, DefaultMaterial, mat);
createGeometricTower(40, 4, dims, PxVec3(-20, 16 * 2 * dims.y, -35.5), 0.74f, DefaultMaterial, mat);
createGeometricTower(40, 4, dims, PxVec3(20, 16 * 2 * dims.y, -35.5), 0.74f, DefaultMaterial, mat);
createGeometricTower(15, 4, dims, PxVec3(-20, 0, -9.5), 1.f, DefaultMaterial, mat);
createGeometricTower(15, 4, dims, PxVec3(20, 0, -9.5), 1.f, DefaultMaterial, mat);
createGeometricTower(40, 4, dims, PxVec3(-20, 16 * 2 * dims.y, -9.5), 0.74f, DefaultMaterial, mat);
createGeometricTower(40, 4, dims, PxVec3(20, 16 * 2 * dims.y, -9.5), 0.74f, DefaultMaterial, mat);
createCommunicationWire(PxVec3(-20, dims.y / 2.f + 15 * 2 * dims.y, -35.5), PxVec3(20, dims.y / 2.f + 15 * 2 * dims.y, -35.5), 0.15f, 0.75f, 0.05f, capRadius,
cylinder0, cylinder1, DefaultMaterial, mat, PxQuat(3.14159f/2.f, PxVec3(0,1,0)));
createCommunicationWire(PxVec3(-20, dims.y / 2.f + 15 * 2 * dims.y, -9.5), PxVec3(20, dims.y / 2.f + 15 * 2 * dims.y, -9.5), 0.15f, 0.75f, 0.05f, capRadius,
cylinder2, cylinder3, DefaultMaterial, mat, PxQuat(3.14159f / 2.f, PxVec3(0, 1, 0)));
createCommunicationWire(PxVec3(-20, dims.y / 2.f + 15 * 2 * dims.y, -35.5), PxVec3(-20, dims.y / 2.f + 15 * 2 * dims.y, -9.5), 0.15f, 0.75f, 0.05f, capRadius,
cylinder0, cylinder2, DefaultMaterial, mat, PxQuat(PxIdentity));
createCommunicationWire(PxVec3(20, dims.y / 2.f + 15 * 2 * dims.y, -35.5), PxVec3(20, dims.y / 2.f + 15 * 2 * dims.y, -9.5), 0.15f, 0.75f, 0.05f, capRadius,
cylinder1, cylinder3, DefaultMaterial, mat, PxQuat(PxIdentity));
createRectangularTower(27, 19, 6, dims, PxVec3(0.f, 0.f, -20.f), DefaultMaterial, mat);
}
void SceneKaplaTower::createCommunicationWire(PxVec3 startPos, PxVec3 endPos,
PxReal connectRadius, PxReal connectHeight, PxReal density, PxReal offset, PxRigidDynamic* startBody, PxRigidDynamic* endBody, PxMaterial* material, ShaderMaterial& mat,
PxQuat& rot)
{
mSimScene->getCompoundCreator()->createCylinder(connectRadius, connectHeight, 8);
PxVec3 layDir = (endPos - startPos).getNormalized();
PxReal distance = (startPos - endPos).magnitude() - 2.f * offset;
PxU32 nbToConnect = (distance) / connectHeight;
PxReal gap = distance / nbToConnect;
PxVec3 pos = startPos + layDir* (offset + connectHeight / 2.f);
PxRigidDynamic* rootActor = startBody;
PxVec3 anchorPos = startPos + layDir * offset;
PxPhysics* physics = getSimScene()->getPxPhysics();
PxRigidDynamic** dyns = new PxRigidDynamic*[nbToConnect];
for (PxU32 a = 0; a < nbToConnect; ++a)
{
Compound* compound = createObject(PxTransform(pos, rot), PxVec3(0), PxVec3(0), false, mat);
PxRigidDynamic* dyn = compound->getPxActor();
dyns[a] = dyn;
finishBody(dyn, density, 10.f);
dyn->setLinearDamping(0.1f);
dyn->setAngularDamping(0.15f);
dyn->setStabilizationThreshold(0.f);
//Now create the constraint
PxD6Joint *joint = PxD6JointCreate(*physics, rootActor,
PxTransform(rootActor->getGlobalPose().transformInv(anchorPos)), dyn, PxTransform(dyn->getGlobalPose().transformInv(anchorPos)));
joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
//if (a == 0)
{
joint->setBreakForce((dyn->getMass() + rootActor->getMass()) * 3000.f, (dyn->getMass() + rootActor->getMass()) * 2000.f);
}
joint->setDrive(PxD6Drive::eSWING, PxD6JointDrive(0.f, 0.15f, PX_MAX_F32));
joint->setDrive(PxD6Drive::eTWIST, PxD6JointDrive(0.f, 0.15f, PX_MAX_F32));
pos += layDir * gap;
anchorPos += layDir * gap;
rootActor = dyn;
}
PxD6Joint *joint = PxD6JointCreate(*physics, rootActor,
PxTransform(rootActor->getGlobalPose().transformInv(anchorPos)), endBody, PxTransform(endBody->getGlobalPose().transformInv(anchorPos)));
joint->setBreakForce((endBody->getMass() + rootActor->getMass()) * 3000.f, (endBody->getMass() + rootActor->getMass()) * 2000.f);
joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
joint->setDrive(PxD6Drive::eSWING, PxD6JointDrive(0.f, 0.15f, PX_MAX_F32));
joint->setDrive(PxD6Drive::eTWIST, PxD6JointDrive(0.f, 0.15f, PX_MAX_F32));
//Now add some bunting to the connections...
mSimScene->getCompoundCreator()->createBox(PxVec3(connectRadius, connectHeight, connectHeight));
for (PxU32 a = 2; a < nbToConnect; a += 3)
{
//Create a little box to attach
PxRigidDynamic* rootActor = dyns[a];
PxTransform transform = rootActor->getGlobalPose();
transform.p += PxVec3(0.f, -(connectRadius + 0.5*connectHeight), 0.f);
Compound* compound = createObject(transform, PxVec3(0), PxVec3(0), false, mat);
PxRigidDynamic* dyn = compound->getPxActor();
finishBody(dyn, density*0.5f, 10.f);
dyn->setLinearDamping(0.1f);
dyn->setAngularDamping(0.15f);
dyn->setStabilizationThreshold(0.f);
anchorPos = transform.p + PxVec3(0, 0.5f*connectHeight, 0);
PxD6Joint *joint = PxD6JointCreate(*physics, rootActor,
PxTransform(rootActor->getGlobalPose().transformInv(anchorPos)), dyn, PxTransform(dyn->getGlobalPose().transformInv(anchorPos)));
joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eLOCKED);
joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eLOCKED);
joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eLOCKED);
}
delete dyns;
}
void SceneKaplaTower::createGeometricTower(PxU32 height, PxU32 nbFacets, PxVec3 dims, PxVec3 startPos, PxReal startDensity, PxMaterial* material, ShaderMaterial& mat)
{
PX_UNUSED(nbFacets);
//Create a tower of geometric shaps
PxReal angle = (3.14159 / 2.f); //the angle between each facet...
PxQuat zRot(3.1415 / 2.f, PxVec3(0, 1, 0));
PxQuat rotation[] = { PxQuat(PxIdentity), PxQuat(3.1415 / 4.f, PxVec3(0, 1, 0)) };
PxReal offset = dims.z;
PxReal density = startDensity;
PxShape* shape;
PxVec3 vel(0), omega(0);
mSimScene->getCompoundCreator()->createBox(2.f*dims);//0.5f, 0.2f, 20, 20);
for (PxU32 i = 0; i < height; ++i)
{
PxVec3 yOffset(0, dims.y + i * dims.y * 2, 0);
PxQuat rot = rotation[i & 1];
PxVec3 basis0 = rot.getBasisVector0();
PxVec3 basis2 = rot.getBasisVector2();
PxVec3 pos0 = -basis0 * offset + basis2 * dims.x;
PxVec3 pos1 = basis0 * offset - basis2 * dims.x;
PxVec3 pos2 = basis0 * dims.x + basis2 * offset;
PxVec3 pos3 = -basis0 * dims.x - basis2 * offset;
//PxRigidDynamic* box0 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos0 + startPos + yOffset, rot, dims);
//PxRigidDynamic* box1 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos1 + startPos + yOffset, rot, dims);
//PxRigidDynamic* box2 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos2 + startPos + yOffset, zRot * rot, dims);
//PxRigidDynamic* box3 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos3 + startPos + yOffset, zRot * rot, dims);
Compound* compound0 = createObject(PxTransform(pos0 + startPos + yOffset, rot), vel, omega, false, mat);
PxRigidDynamic* box0 = compound0->getPxActor();
box0->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
Compound* compound1 = createObject(PxTransform(pos1 + startPos + yOffset, rot), vel, omega, false, mat);
PxRigidDynamic* box1 = compound1->getPxActor();
box1->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
Compound* compound2 = createObject(PxTransform(pos2 + startPos + yOffset, zRot * rot), vel, omega, false, mat);
PxRigidDynamic* box2 = compound2->getPxActor();
box2->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
Compound* compound3 = createObject(PxTransform(pos3 + startPos + yOffset, zRot * rot), vel, omega, false, mat);
PxRigidDynamic* box3 = compound3->getPxActor();
box3->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
box0->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box0->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box0, density);
box0->setMassSpaceInertiaTensor(box0->getMassSpaceInertiaTensor() * 4.f);
box1->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box1->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box1, density);
box1->setMassSpaceInertiaTensor(box1->getMassSpaceInertiaTensor() * 4.f);
box2->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box2->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box2, density);
box2->setMassSpaceInertiaTensor(box2->getMassSpaceInertiaTensor() * 4.f);
box3->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box3->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box3, density);
box3->setMassSpaceInertiaTensor(box3->getMassSpaceInertiaTensor() * 4.f);
density = density * 0.98f;
}
}
void SceneKaplaTower::createTwistTower(PxU32 height, PxU32 nbBlocksPerLayer, PxVec3 dims, PxVec3 startPos, PxMaterial* material, ShaderMaterial& mat)
{
PxQuat rotation(PxIdentity);//3.14/2.f, PxVec3(0,0,1));
PxQuat rotationDelta(3.14 / 10.f, PxVec3(0, 1, 0));
PxReal density = 1.f;
PxShape* shape;
PxVec3 vel(0), omega(0);
mSimScene->getCompoundCreator()->createBox(2.f*dims);//0.5f, 0.2f, 20, 20);
for (PxU32 i = 0; i < height; ++i)
{
PxReal startY = i * dims.y * 2 + dims.y;
PxVec3 xVec = rotation.getBasisVector0();
for (PxU32 a = 0; a < nbBlocksPerLayer; ++a)
{
PxVec3 pos = xVec * dims.x * 2 * (PxReal(a) - PxReal(nbBlocksPerLayer) / 2.f) + PxVec3(0, startY, 0);
//PxRigidDynamic* box = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos + startPos, rotation, dims);
Compound* compound = createObject(PxTransform(pos + startPos, rotation), vel, omega, false, mat);
PxRigidDynamic* box = compound->getPxActor();
box->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
box->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box, density);
box->setMassSpaceInertiaTensor(box->getMassSpaceInertiaTensor() * 4.f);
}
rotation = rotationDelta * rotation;
density *= 0.95f;
}
}
void SceneKaplaTower::createRectangularTower(PxU32 nbX, PxU32 nbZ, PxU32 height, PxVec3 dims, PxVec3 centerPos, PxMaterial* material, ShaderMaterial& mat)
{
PxReal startHeight = 0.f;
PxReal density = 1.f;
PxU32 nbXSupports = 1 + 2 * nbX;
PxReal xSpacing = dims.z;
PxU32 nbZSlabs = (2.f*dims.z * nbZ) / (2.f*dims.y);
PxQuat rotation = PxQuat(3.14 / 2.f, PxVec3(0, 1, 0)) * PxQuat(3.14 / 2.f, PxVec3(0, 0, 1));
mSimScene->getCompoundCreator()->createBox(2.f*dims);//0.5f, 0.2f, 20, 20);
PxVec3 pos(-2.0f, 1.5f, 0.0f);
PxVec3 vel(0.0f, 0.0f, 0.0f);
PxVec3 omega(0.0f, 0.0f, 0.0f);
for (PxU32 i = 0; i < height; ++i)
{
//First, lets lay down the supports...
PxVec3 rowColExtents((nbX)* dims.z, 0.f, (nbZ)* dims.z);
PxShape* shape;
//Back row
for (PxU32 a = 0; a < nbXSupports; ++a)
{
PxVec3 pos(a * xSpacing - rowColExtents.x, startHeight + dims.y, -rowColExtents.z);
PxVec3 pos2(a * xSpacing - rowColExtents.x, startHeight + dims.y, rowColExtents.z);
Compound* compound = createObject(PxTransform(pos + centerPos), vel, omega, false, mat);
PxRigidDynamic* box = compound->getPxActor();
box->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
box->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box, density);
box->setMassSpaceInertiaTensor(box->getMassSpaceInertiaTensor() * 4.f);
Compound* compound2 = createObject(PxTransform(pos2 + centerPos), vel, omega, false, mat);
PxRigidDynamic* box2 = compound2->getPxActor();
box2->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
box2->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box2->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box2, density);
box2->setMassSpaceInertiaTensor(box2->getMassSpaceInertiaTensor() * 4.f);
}
for (PxU32 a = 0; a < nbX; ++a)
{
PxVec3 pos(dims.z + a * dims.z * 2 - rowColExtents.x, startHeight + 2 * dims.y + dims.x, -rowColExtents.z - dims.y);
PxVec3 pos2(dims.z + a * dims.z * 2 - rowColExtents.x, startHeight + 2 * dims.y + dims.x, -rowColExtents.z + dims.y);
Compound* compound = createObject(PxTransform(pos + centerPos, rotation), vel, omega, false, mat);
PxRigidDynamic* box = compound->getPxActor();
box->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
//PxRigidDynamic* box2 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos2 + centerPos, rotation, dims);
Compound* compound2 = createObject(PxTransform(pos2 + centerPos, rotation), vel, omega, false, mat);
PxRigidDynamic* box2 = compound2->getPxActor();
box2->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
box->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box, density);
box->setMassSpaceInertiaTensor(box->getMassSpaceInertiaTensor() * 4.f);
box2->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box2->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box2, density);
box2->setMassSpaceInertiaTensor(box2->getMassSpaceInertiaTensor() * 4.f);
PxVec3 pos3(dims.z + a * dims.z * 2 - rowColExtents.x, startHeight + 2 * dims.y + dims.x, rowColExtents.z - dims.y);
PxVec3 pos4(dims.z + a * dims.z * 2 - rowColExtents.x, startHeight + 2 * dims.y + dims.x, rowColExtents.z + dims.y);
//PxRigidDynamic* box3 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos3 + centerPos, rotation, dims);
Compound* compound3 = createObject(PxTransform(pos3 + centerPos, rotation), vel, omega, false, mat);
PxRigidDynamic* box3 = compound3->getPxActor();
box3->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
//PxRigidDynamic* box4 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos4 + centerPos, rotation, dims);
Compound* compound4 = createObject(PxTransform(pos4 + centerPos, rotation), vel, omega, false, mat);
PxRigidDynamic* box4 = compound4->getPxActor();
box4->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
box3->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box3->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box3, density);
box3->setMassSpaceInertiaTensor(box3->getMassSpaceInertiaTensor() * 4.f);
box4->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box4->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box4, density);
box4->setMassSpaceInertiaTensor(box4->getMassSpaceInertiaTensor() * 4.f);
}
//Sides...
for (PxU32 a = 1; a < nbZ; ++a)
{
for (PxU32 b = 0; b < 3; b++)
{
PxVec3 pos(b * xSpacing - rowColExtents.x, startHeight + dims.y, -rowColExtents.z + a * dims.z * 2);
PxVec3 pos2(rowColExtents.x - b * xSpacing, startHeight + dims.y, -rowColExtents.z + a * dims.z * 2);
//PxRigidDynamic* box = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos + centerPos, PxQuat(PxIdentity), dims);
Compound* compound = createObject(PxTransform(pos + centerPos), vel, omega, false, mat);
PxRigidDynamic* box = compound->getPxActor();
box->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
box->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box, density);
box->setMassSpaceInertiaTensor(box->getMassSpaceInertiaTensor() * 4.f);
//PxRigidDynamic* box2 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos2 + centerPos, PxQuat(PxIdentity), dims);
Compound* compound2 = createObject(PxTransform(pos2 + centerPos), vel, omega, false, mat);
PxRigidDynamic* box2 = compound2->getPxActor();
box2->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
box2->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box2->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box2, density);
box2->setMassSpaceInertiaTensor(box2->getMassSpaceInertiaTensor() * 4.f);
}
}
for (PxU32 a = 1; a < nbZSlabs - 1; a++)
{
PxVec3 pos(dims.z - rowColExtents.x, startHeight + 2 * dims.y + dims.x, -rowColExtents.z + dims.y + 2 * dims.y*a);
//PxRigidDynamic* box = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos + centerPos, rotation, dims);
Compound* compound = createObject(PxTransform(pos + centerPos, rotation), vel, omega, false, mat);
PxRigidDynamic* box = compound->getPxActor();
box->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
box->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box, density);
box->setMassSpaceInertiaTensor(box->getMassSpaceInertiaTensor() * 4.f);
}
for (PxU32 a = 1; a < nbZSlabs - 1; a++)
{
PxVec3 pos(rowColExtents.x - dims.z, startHeight + 2 * dims.y + dims.x, -rowColExtents.z + dims.y + 2 * dims.y*a);
//PxRigidDynamic* box = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos + centerPos, rotation, dims);
Compound* compound = createObject(PxTransform(pos + centerPos, rotation), vel, omega, false, mat);
PxRigidDynamic* box = compound->getPxActor();
box->getShapes(&shape, 1);
shape->setMaterials(&material, 1);
box->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
box->setMaxDepenetrationVelocity(2.f);
PxRigidBodyExt::updateMassAndInertia(*box, density);
box->setMassSpaceInertiaTensor(box->getMassSpaceInertiaTensor() * 4.f);
}
startHeight += 2 * (dims.y + dims.x);
density *= 0.975f;
}
}
// ----------------------------------------------------------------------------------------------
void SceneKaplaTower::handleKeyDown(unsigned char key, int x, int y)
{
switch (key) {
case 'b':
case 'B':
{
if (gMaxNbPermittedProjectiles == 0)
gMaxNbPermittedProjectiles = 512;
else
gMaxNbPermittedProjectiles = 0;
break;
}
}
SceneKapla::handleKeyDown(key, x, y);
}

View File

@ -0,0 +1,68 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#ifndef SCENE_KAPLA_TOWER_H
#define SCENE_KAPLA_TOWER_H
#include "SceneKapla.h"
using namespace physx;
// ---------------------------------------------------------------------
class SceneKaplaTower : public SceneKapla
{
public:
SceneKaplaTower(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
Shader *defaultShader, const char *resourcePath, float slowMotionFactor);
virtual ~SceneKaplaTower(){}
virtual void handleKeyDown(unsigned char key, int x, int y);
virtual void preSim(float dt);
virtual void postSim(float dt);
virtual void onInit(PxScene* pxScene);
private:
void createGeometricTower(PxU32 height, PxU32 nbFacets, PxVec3 dims, PxVec3 startPos, PxReal startDensity, PxMaterial* material, ShaderMaterial& mat);
void createCommunicationWire(PxVec3 startPos, PxVec3 endPos,PxReal connectRadius, PxReal connectHeight, PxReal density, PxReal offset, PxRigidDynamic* startBody,
PxRigidDynamic* endBody, PxMaterial* material, ShaderMaterial& mat, PxQuat& rot);
void createTwistTower(PxU32 height, PxU32 nbBlocksPerLayer, PxVec3 dims, PxVec3 startPos, PxMaterial* material, ShaderMaterial& mat);
void createRectangularTower(PxU32 nbX, PxU32 nbZ, PxU32 height, PxVec3 dims, PxVec3 centerPos, PxMaterial* material, ShaderMaterial& mat);
//void createCylindricalTower(PxU32 nbRadialPoints, PxReal maxRadius, PxReal minRadius, PxU32 height, PxVec3 dims, PxVec3 centerPos, PxMaterial* material, ShaderMaterial& mat);
PxReal mAccumulatedTime;
bool hadInteraction;
PxU32 nbProjectiles;
};
#endif // SCENE_BOXES_H

View File

@ -0,0 +1,133 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "SceneRagdollWashingMachine.h"
#include "Convex.h"
#include "PxSimpleFactory.h"
#include "PxRigidStatic.h"
#include "PxShape.h"
#include "foundation/PxMathUtils.h"
#include "foundation/PxMat44.h"
#include <stdio.h>
#include <GL/glut.h>
#include "SimScene.h"
#include "CompoundCreator.h"
#include "Mesh.h"
#include "TerrainMesh.h"
#include "PhysXMacros.h"
#include "MathUtils.h"
#include "PxRigidBodyExt.h"
#include "PxD6Joint.h"
using namespace physx;
using namespace physx::shdfnd;
static PxReal speeds[] = { 3.141692f*0.125f, 3.141592f*0.25f, 3.141592f*0.75f, 3.141592f*0.5f, 3.141592f*0.25f };
static PxReal spinDurations[] = { 10, 15, 5, 5, 10 };
SceneRagdollWashingMachine::SceneRagdollWashingMachine(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
Shader *defaultShader, const char *resourcePath, float slowMotionFactor) : SceneKapla(pxPhysics, pxCooking, isGrb, defaultShader, resourcePath, slowMotionFactor),
mWashingMachine(NULL)
{
mChangeSpeedTime = 15.f;
mSpeedState = 0;
}
void SceneRagdollWashingMachine::preSim(float dt)
{
mChangeSpeedTime -= dt;
if (mChangeSpeedTime < 0.f)
{
mSpeedState = (mSpeedState + 1)%5;
mChangeSpeedTime = spinDurations[mSpeedState];
}
PxQuat rotationPerFrame(speeds[mSpeedState]*dt, PxVec3(0,0,1));
PxTransform trans = mWashingMachine->getGlobalPose();
trans.q = trans.q * rotationPerFrame;
mWashingMachine->setKinematicTarget(trans);
SceneKapla::preSim(dt);
}
void SceneRagdollWashingMachine::onInit(PxScene* pxScene)
{
//(1) Create the washing machine :)
SceneKapla::onInit(pxScene);
ShaderMaterial mat;
mat.init();
PxVec3 dims(3.f, 1.f, 35.f);
PxReal radius = 7.f;
PxReal circumference = 2.f * radius * 3.141592f;
//Now work out how many slabs you need to satisfy this...
PxU32 nbSlabs = PxU32((circumference / dims.x)) + 5;
PxVec3 offset(0, radius, 0);
for (PxU32 a = 0; a < nbSlabs; ++a)
{
PxQuat rotation(a*2.f*3.141592 / PxReal(nbSlabs), PxVec3(0, 0, 1));
PxTransform localTransform(rotation.rotate(offset), rotation);
mSimScene->getCompoundCreator()->createBox(dims, &localTransform, a == 0);
}
PxTransform localTransform(PxVec3(0, radius - dims.x/2.f, 0.f), PxQuat(3.141592*0.5f, PxVec3(0, 0, 1)));
mSimScene->getCompoundCreator()->createBox(dims, &localTransform, false);
Compound* compound = createObject(PxTransform(PxVec3(0, radius+5.f, -dims.z)), PxVec3(0), PxVec3(0), false, mat,false);
mWashingMachine = compound->getPxActor();
mWashingMachine->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
for (PxU32 a = 0; a < 20; ++a)
{
for (PxU32 b = 0; b < 35; ++b)
{
createRagdoll(PxVec3(-radius + 2.f + a * 0.5f, radius+5.f, -dims.z*0.8f - b * 0.5f), PxVec3(0), mat);
}
}
createGroundPlane(PxFilterData(), PxVec3(0, -2.f, 0));
mSimScene->getCompoundCreator()->createBox(PxVec3(20.f, 20.f, 2.f));
Compound* staticCompound = createObject(PxTransform(PxVec3(0.f, radius+5.f, -1.5f*dims.z)), PxVec3(0), PxVec3(0),false,mat,false);
staticCompound->getPxActor()->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
}

View File

@ -0,0 +1,52 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#ifndef SCENE_RAGDOLL_WASHING_MACHINE_H
#define CENE_RAGDOLL_WASHING_MACHINE_H
#include "SceneKapla.h"
using namespace physx;
// ---------------------------------------------------------------------
class SceneRagdollWashingMachine : public SceneKapla
{
PxReal mChangeSpeedTime;
PxU32 mSpeedState;
PxRigidDynamic* mWashingMachine;
public:
SceneRagdollWashingMachine(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
Shader *defaultShader, const char *resourcePath, float slowMotionFactor);
virtual ~SceneRagdollWashingMachine(){}
virtual void preSim(float dt);
virtual void onInit(PxScene* pxScene);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,125 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef SCENE_VEHICLE_H
#define SCENE_VEHICLE_H
#include "SceneKapla.h"
#include "vehicle/PxVehicleWheels.h"
#include "RawLoader.h"
#include "VehicleManager.h"
#include "VehicleController.h"
#include "VehicleControlInputs.h"
#include "VehicleCameraController.h"
using namespace physx;
// ---------------------------------------------------------------------
class SceneVehicle : public SceneKapla, public RAWImportCallback
{
public:
SceneVehicle(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
Shader *defaultShader, const char *resourcePath, float slowMotionFactor);
virtual ~SceneVehicle(){}
///////////////////////////////////////////////////////////////////////////////
// Implements RAWImportCallback
virtual void newMaterial(const RAWMaterial&);
virtual void newMesh(const RAWMesh&);
virtual void newTexture(const RAWTexture&);
virtual void newShape(const RAWShape&){}
virtual void newHelper(const RAWHelper&){}
///////////////////////////////////////////////////////////////////////////////
virtual void handleMouseButton(int button, int state, int x, int y);
virtual void handleMouseMotion(int x, int y);
virtual void handleKeyDown(unsigned char key, int x, int y);
virtual void handleKeyUp(unsigned char key, int x, int y);
virtual void handleSpecialKey(unsigned char key, int x, int y);
virtual void handleGamepadButton(int button, bool state);
virtual void handleGamepadAxis(int axis, float x);
virtual void handleGamepadTrigger(int trigger, float x);
virtual void getCamera(PxVec3& pos, PxVec3& dir);
virtual void preSim(float dt);
virtual void postSim(float dt);
virtual void render(bool useShader);
virtual void customizeSceneDesc(PxSceneDesc& desc);
virtual void onInit(PxScene* pxScene);
virtual void setScene(PxScene* pxScene);
private:
void renderCar(bool useShader);
void createStandardMaterials();
void createVehicle(PxPhysics* pxPhysics);
void createTerrain(PxU32 size, float width, float chaos);
void importRAWFile(const char* relativePath, PxReal scale, bool recook = false);
enum
{
MAX_NUM_INDEX_BUFFERS = 16
};
PxU32 mNbIB;
PxU32* mIB[MAX_NUM_INDEX_BUFFERS];
PxU32 mNbTriangles[MAX_NUM_INDEX_BUFFERS];
PxU32 mRenderMaterial[MAX_NUM_INDEX_BUFFERS];
PxVehicleDrivableSurfaceType mVehicleDrivableSurfaceTypes[MAX_NUM_INDEX_BUFFERS];
PxMaterial* mStandardMaterials[MAX_NUM_INDEX_BUFFERS];
PxMaterial* mChassisMaterialDrivable;
PxMaterial* mChassisMaterialNonDrivable;
VehicleManager mVehicleManager;
VehicleController mVehicleController;
VehicleControlInputs mControlInputs;
VehicleCameraController mCameraController;
//Terrain
PxF32* mTerrainVB;
PxU32 mNbTerrainVerts;
//render car
GLuint mTextureIds[2];
ShaderMaterial mCarPartMaterial[2];
PxU32 mNumMaterials;
PxU32 mNumTextures;
};
#endif // SCENE_BOXES_H

View File

@ -0,0 +1,214 @@
//
// 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-2018 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 "SceneVehicleCooking.h"
#include "PxTkStream.h"
#include "extensions/PxDefaultStreams.h"
#include "glmesh.h"
#include "RawLoader.h"
using namespace physx;
PxConvexMesh* createConvexMesh(const PxVec3* verts, const PxU32 numVerts, PxPhysics& physics, PxCooking& cooking)
{
// Create descriptor for convex mesh
PxConvexMeshDesc convexDesc;
convexDesc.points.count = numVerts;
convexDesc.points.stride = sizeof(PxVec3);
convexDesc.points.data = verts;
convexDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
PxConvexMesh* convexMesh = NULL;
PxDefaultMemoryOutputStream buf;
if (cooking.cookConvexMesh(convexDesc, buf))
{
PxDefaultMemoryInputData id(buf.getData(), buf.getSize());
convexMesh = physics.createConvexMesh(id);
}
return convexMesh;
}
PxConvexMesh* createCuboidConvexMesh(const PxVec3& halfExtents, PxPhysics& physics, PxCooking& cooking)
{
PxVec3 verts[8] =
{
PxVec3(-halfExtents.x, -halfExtents.y, -halfExtents.z),
PxVec3(-halfExtents.x, -halfExtents.y, +halfExtents.z),
PxVec3(-halfExtents.x, +halfExtents.y, -halfExtents.z),
PxVec3(-halfExtents.x, +halfExtents.y, +halfExtents.z),
PxVec3(+halfExtents.x, -halfExtents.y, -halfExtents.z),
PxVec3(+halfExtents.x, -halfExtents.y, +halfExtents.z),
PxVec3(+halfExtents.x, +halfExtents.y, -halfExtents.z),
PxVec3(+halfExtents.x, +halfExtents.y, +halfExtents.z)
};
PxU32 numVerts = 8;
return createConvexMesh(verts, numVerts, physics, cooking);
}
PxConvexMesh* createWedgeConvexMesh(const PxVec3& halfExtents, PxPhysics& physics, PxCooking& cooking)
{
PxVec3 verts[6] =
{
PxVec3(-halfExtents.x, -halfExtents.y, -halfExtents.z),
PxVec3(-halfExtents.x, -halfExtents.y, +halfExtents.z),
PxVec3(-halfExtents.x, +halfExtents.y, -halfExtents.z),
PxVec3(+halfExtents.x, -halfExtents.y, -halfExtents.z),
PxVec3(+halfExtents.x, -halfExtents.y, +halfExtents.z),
PxVec3(+halfExtents.x, +halfExtents.y, -halfExtents.z)
};
PxU32 numVerts = 6;
return createConvexMesh(verts, numVerts, physics, cooking);
}
PxConvexMesh* createCylinderConvexMesh(const PxF32 width, const PxF32 radius, const PxU32 numCirclePoints, PxPhysics& physics, PxCooking& cooking)
{
#define MAX_NUM_VERTS_IN_CIRCLE 16
PX_ASSERT(numCirclePoints<MAX_NUM_VERTS_IN_CIRCLE);
PxVec3 verts[2 * MAX_NUM_VERTS_IN_CIRCLE];
PxU32 numVerts = 2 * numCirclePoints;
const PxF32 dtheta = 2 * PxPi / (1.0f*numCirclePoints);
for (PxU32 i = 0; i<MAX_NUM_VERTS_IN_CIRCLE; i++)
{
const PxF32 theta = dtheta*i;
const PxF32 cosTheta = radius*PxCos(theta);
const PxF32 sinTheta = radius*PxSin(theta);
verts[2 * i + 0] = PxVec3(-0.5f*width, cosTheta, sinTheta);
verts[2 * i + 1] = PxVec3(+0.5f*width, cosTheta, sinTheta);
}
return createConvexMesh(verts, numVerts, physics, cooking);
}
PxConvexMesh* createSquashedCuboidMesh(const PxF32 baseLength, const PxF32 baseDepth, const PxF32 height1, const PxF32 height2, PxPhysics& physics, PxCooking& cooking)
{
const PxF32 x = baseLength*0.5f;
const PxF32 z = baseDepth*0.5f;
PxVec3 verts[8] =
{
PxVec3(-x, -0.5f*height1, -z),
PxVec3(-x, -0.5f*height1, +z),
PxVec3(+x, -0.5f*height1, -z),
PxVec3(+x, -0.5f*height1, +z),
PxVec3(-x, -0.5f*height1 + height2, -z),
PxVec3(-x, +0.5f*height1, +z),
PxVec3(+x, -0.5f*height1 + height2, -z),
PxVec3(+x, +0.5f*height1, +z)
};
PxU32 numVerts = 8;
return createConvexMesh(verts, numVerts, physics, cooking);
}
PxConvexMesh* createPrismConvexMesh(const PxF32 baseLength, const PxF32 baseDepth, const PxF32 height, PxPhysics& physics, PxCooking& cooking)
{
const PxF32 x = baseLength*0.5f;
const PxF32 z = baseDepth*0.5f;
PxVec3 verts[6] =
{
PxVec3(-x, 0, -z),
PxVec3(-x, 0, +z),
PxVec3(+x, 0, -z),
PxVec3(+x, 0, +z),
PxVec3(-x, height, 0),
PxVec3(+x, height, 0),
};
PxU32 numVerts = 6;
return createConvexMesh(verts, numVerts, physics, cooking);
}
PxConvexMesh* createChassisConvexMesh(const PxVec3* verts, const PxU32 numVerts, PxPhysics& physics, PxCooking& cooking)
{
return createConvexMesh(verts, numVerts, physics, cooking);
}
PxConvexMesh* createWheelConvexMesh(const PxVec3* verts, const PxU32 numVerts, PxPhysics& physics, PxCooking& cooking)
{
//Extract the wheel radius and width from the aabb of the wheel convex mesh.
PxVec3 wheelMin(PX_MAX_F32, PX_MAX_F32, PX_MAX_F32);
PxVec3 wheelMax(-PX_MAX_F32, -PX_MAX_F32, -PX_MAX_F32);
for (PxU32 i = 0; i<numVerts; i++)
{
wheelMin.x = PxMin(wheelMin.x, verts[i].x);
wheelMin.y = PxMin(wheelMin.y, verts[i].y);
wheelMin.z = PxMin(wheelMin.z, verts[i].z);
wheelMax.x = PxMax(wheelMax.x, verts[i].x);
wheelMax.y = PxMax(wheelMax.y, verts[i].y);
wheelMax.z = PxMax(wheelMax.z, verts[i].z);
}
const PxF32 wheelWidth = wheelMax.x - wheelMin.x;
const PxF32 wheelRadius = PxMax(wheelMax.y, wheelMax.z);
return createCylinderConvexMesh(wheelWidth, wheelRadius, 8, physics, cooking);
}
GLMesh* createRenderMesh(const RAWMesh& data)
{
GLMesh* mesh =new GLMesh(GL_TRIANGLES);
const PxU32 nbVerts = data.mNbVerts;
const PxU32 nbTris = data.mNbFaces;
mesh->vertices.resize(nbVerts);
mesh->normals.resize(nbVerts);
mesh->texCoords.resize(nbVerts * 2);
mesh->indices.resize(nbTris*3);
const PxU32* src = data.mIndices;
PxU32* indices = new PxU32[sizeof(PxU16)*nbTris * 3];
for (PxU32 i = 0; i<nbTris; i++)
{
indices[i * 3 + 0] = src[i * 3 + 0];
indices[i * 3 + 1] = src[i * 3 + 1];
indices[i * 3 + 2] = src[i * 3 + 2];
}
for (PxU32 i = 0; i < nbVerts; ++i)
{
mesh->vertices[i] = data.mVerts[i];
mesh->normals[i] = data.mVertexNormals[i];
mesh->texCoords[i*2] = data.mUVs[i*2];
mesh->texCoords[i * 2 + 1] = 1.f-data.mUVs[i*2+1];
}
for (PxU32 i = 0; i < nbTris * 3; ++i)
{
mesh->indices[i] = indices[i];
}
mesh->genVBOIBO();
mesh->updateVBOIBO(true);
return mesh;
}

View File

@ -0,0 +1,50 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2018 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 VEHICLE_COOKING_H
#define VEHICLE_COOKING_H
#include "PxPhysicsAPI.h"
class RAWMesh;
class GLMesh;
physx::PxConvexMesh* createConvexMesh(const physx::PxVec3* verts, const physx::PxU32 numVerts, physx::PxPhysics& physics, physx::PxCooking& cooking);
physx::PxConvexMesh* createCuboidConvexMesh(const physx::PxVec3& halfExtents, physx::PxPhysics& physics, physx::PxCooking& cooking);
physx::PxConvexMesh* createWedgeConvexMesh(const physx::PxVec3& halfExtents, physx::PxPhysics& physics, physx::PxCooking& cooking);
physx::PxConvexMesh* createCylinderConvexMesh(const physx::PxF32 width, const physx::PxF32 radius, const physx::PxU32 numCirclePoints, physx::PxPhysics& physics, physx::PxCooking& cooking);
physx::PxConvexMesh* createSquashedCuboidMesh(const physx::PxF32 baseLength, const physx::PxF32 baseDepth, const physx::PxF32 height1, const physx::PxF32 height2, physx::PxPhysics& physics, physx::PxCooking& cooking);
physx::PxConvexMesh* createPrismConvexMesh(const physx::PxF32 baseLength, const physx::PxF32 baseDepth, const physx::PxF32 height, physx::PxPhysics& physics, physx::PxCooking& cooking);
physx::PxConvexMesh* createWheelConvexMesh(const physx::PxVec3* verts, const physx::PxU32 numVerts, physx::PxPhysics& physics, physx::PxCooking& cooking);
physx::PxConvexMesh* createChassisConvexMesh(const physx::PxVec3* verts, const physx::PxU32 numVerts, physx::PxPhysics& physics, physx::PxCooking& cooking);
GLMesh* createRenderMesh(const RAWMesh& data);
#endif //VEHICLE_COOKING_H

View File

@ -0,0 +1,100 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2018 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 "SceneVehicleSceneQuery.h"
#include "vehicle/PxVehicleSDK.h"
#include "PxFiltering.h"
#include "PsFoundation.h"
#include "PsUtilities.h"
#define CHECK_MSG(exp, msg) (!!(exp) || (physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, msg), 0) )
#define SIZEALIGN16(size) (((unsigned)(size)+15)&((unsigned)(~15)));
void VehicleSetupDrivableShapeQueryFilterData(PxFilterData* qryFilterData)
{
CHECK_MSG(0 == qryFilterData->word3, "word3 is reserved for filter data for vehicle raycast queries");
qryFilterData->word3 = (PxU32)VEHICLE_DRIVABLE_SURFACE;
}
void VehicleSetupNonDrivableShapeQueryFilterData(PxFilterData* qryFilterData)
{
CHECK_MSG(0 == qryFilterData->word3, "word3 is reserved for filter data for vehicle raycast queries");
qryFilterData->word3 = (PxU32)VEHICLE_UNDRIVABLE_SURFACE;
}
void VehicleSetupVehicleShapeQueryFilterData(PxFilterData* qryFilterData)
{
CHECK_MSG(0 == qryFilterData->word3, "word3 is reserved for filter data for vehicle raycast queries");
qryFilterData->word3 = (PxU32)VEHICLE_UNDRIVABLE_SURFACE;
}
VehicleSceneQueryData* VehicleSceneQueryData::allocate(const PxU32 maxNumWheels)
{
VehicleSceneQueryData* sqData = (VehicleSceneQueryData*)PX_ALLOC(sizeof(VehicleSceneQueryData), "PxVehicleNWSceneQueryData");
sqData->init();
sqData->mSqResults = (PxRaycastQueryResult*)PX_ALLOC(sizeof(PxRaycastQueryResult)*maxNumWheels, "PxRaycastQueryResult");
sqData->mNbSqResults = maxNumWheels;
sqData->mSqHitBuffer = (PxRaycastHit*)PX_ALLOC(sizeof(PxRaycastHit)*maxNumWheels, "PxRaycastHit");
sqData->mNumQueries = maxNumWheels;
sqData->mSqSweepResults = (PxSweepQueryResult*)PX_ALLOC(sizeof(PxSweepQueryResult) * maxNumWheels, "PxSweepQueryResult");
sqData->mNbSqSweepResults = maxNumWheels;
sqData->mSqSweepHitBuffer = (PxSweepHit*)PX_ALLOC(sizeof(PxSweepHit) * maxNumWheels, "PxSweepHit");
sqData->mNumSweepQueries = maxNumWheels;
return sqData;
}
void VehicleSceneQueryData::free()
{
PX_FREE(this);
}
PxBatchQuery* VehicleSceneQueryData::setUpBatchedSceneQuery(PxScene* scene)
{
PxBatchQueryDesc sqDesc(mNbSqResults, 0, 0);
sqDesc.queryMemory.userRaycastResultBuffer = mSqResults;
sqDesc.queryMemory.userRaycastTouchBuffer = mSqHitBuffer;
sqDesc.queryMemory.raycastTouchBufferSize = mNumQueries;
sqDesc.preFilterShader = mPreFilterShader;
return scene->createBatchQuery(sqDesc);
}
PxBatchQuery* VehicleSceneQueryData::setUpBatchedSceneQuerySweep(PxScene* scene)
{
PxBatchQueryDesc sqDesc(0, mNbSqResults, 0);
sqDesc.queryMemory.userSweepResultBuffer = mSqSweepResults;
sqDesc.queryMemory.userSweepTouchBuffer = mSqSweepHitBuffer;
sqDesc.queryMemory.sweepTouchBufferSize = mNumQueries;
sqDesc.preFilterShader = mPreFilterShader;
return scene->createBatchQuery(sqDesc);
}

View File

@ -0,0 +1,147 @@
//
// 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-2018 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 VEHICLE_UTILSCENEQUERY_H
#define VEHICLE_UTILSCENEQUERY_H
#include "common/PxPhysXCommonConfig.h"
#include "vehicle/PxVehicleSDK.h"
#include "foundation/PxPreprocessor.h"
#include "PxScene.h"
#include "PxBatchQueryDesc.h"
using namespace physx;
//Make sure that suspension raycasts only consider shapes flagged as drivable that don't belong to the owner vehicle.
enum
{
VEHICLE_DRIVABLE_SURFACE = 0xffff0000,
VEHICLE_UNDRIVABLE_SURFACE = 0x0000ffff
};
static PxQueryHitType::Enum SampleVehicleWheelRaycastPreFilter(
PxFilterData filterData0,
PxFilterData filterData1,
const void* constantBlock, PxU32 constantBlockSize,
PxHitFlags& queryFlags)
{
//filterData0 is the vehicle suspension raycast.
//filterData1 is the shape potentially hit by the raycast.
PX_UNUSED(queryFlags);
PX_UNUSED(constantBlockSize);
PX_UNUSED(constantBlock);
PX_UNUSED(filterData0);
return ((0 == (filterData1.word3 & VEHICLE_DRIVABLE_SURFACE)) ? PxQueryHitType::eNONE : PxQueryHitType::eBLOCK);
}
//Set up query filter data so that vehicles can drive on shapes with this filter data.
//Note that we have reserved word3 of the PxFilterData for vehicle raycast query filtering.
void VehicleSetupDrivableShapeQueryFilterData(PxFilterData* qryFilterData);
//Set up query filter data so that vehicles cannot drive on shapes with this filter data.
//Note that we have reserved word3 of the PxFilterData for vehicle raycast query filtering.
void VehicleSetupNonDrivableShapeQueryFilterData(PxFilterData* qryFilterData);
//Set up query filter data for the shapes of a vehicle to ensure that vehicles cannot drive on themselves
//but can drive on the shapes of other vehicles.
//Note that we have reserved word3 of the PxFilterData for vehicle raycast query filtering.
void VehicleSetupVehicleShapeQueryFilterData(PxFilterData* qryFilterData);
//Data structure for quick setup of scene queries for suspension raycasts.
class VehicleSceneQueryData
{
public:
//Allocate scene query data for up to maxNumWheels suspension raycasts.
static VehicleSceneQueryData* allocate(const PxU32 maxNumWheels);
//Free allocated buffer for scene queries of suspension raycasts.
void free();
//Create a PxBatchQuery instance that will be used as a single batched raycast of multiple suspension lines of multiple vehicles
PxBatchQuery* setUpBatchedSceneQuery(PxScene* scene);
PxBatchQuery* setUpBatchedSceneQuerySweep(PxScene* scene);
//Get the buffer of scene query results that will be used by PxVehicleNWSuspensionRaycasts
PxRaycastQueryResult* getRaycastQueryResultBuffer() { return mSqResults; }
//Get the number of scene query results that have been allocated for use by PxVehicleNWSuspensionRaycasts
PxU32 getRaycastQueryResultBufferSize() const { return mNumQueries; }
//Get the buffer of scene query results that will be used by PxVehicleNWSuspensionRaycasts
PxSweepQueryResult* getSweepQueryResultBuffer() { return mSqSweepResults; }
//Get the number of scene query results that have been allocated for use by PxVehicleNWSuspensionRaycasts
PxU32 getSweepQueryResultBufferSize() const { return mNumSweepQueries; }
//Set the pre-filter shader
void setPreFilterShader(PxBatchQueryPreFilterShader preFilterShader) { mPreFilterShader = preFilterShader; }
private:
//One result for each wheel.
PxRaycastQueryResult* mSqResults;
PxU32 mNbSqResults;
//One hit for each wheel.
PxRaycastHit* mSqHitBuffer;
PxSweepQueryResult* mSqSweepResults;
PxU32 mNbSqSweepResults;
PxSweepHit* mSqSweepHitBuffer;
//Filter shader used to filter drivable and non-drivable surfaces
PxBatchQueryPreFilterShader mPreFilterShader;
//Maximum number of suspension raycasts that can be supported by the allocated buffers
//assuming a single query and hit per suspension line.
PxU32 mNumQueries;
PxU32 mNumSweepQueries;
void init()
{
mPreFilterShader = SampleVehicleWheelRaycastPreFilter;
}
VehicleSceneQueryData()
{
init();
}
~VehicleSceneQueryData()
{
}
};
#endif //SAMPLEVEHICLE_UTILSCENEQUERY_H

View File

@ -0,0 +1,396 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include <algorithm>
#include "TerrainMesh.h"
#include "PxPhysics.h"
#include "PxCooking.h"
#include "PxScene.h"
#include "Shader.h"
#include "geometry/PxHeightFieldSample.h"
#include "geometry/PxHeightFieldDesc.h"
#include "geometry/PxHeightFieldGeometry.h"
#include "PxRigidStatic.h"
#include "Texture.h"
#include "TerrainMesh.h"
#include "PhysXMacros.h"
#include "SceneVehicleSceneQuery.h"
#include "VehicleManager.h"
#include "PxDefaultStreams.h"
#include"PxRigidActorExt.h"
#define USE_HEIGHTFIELD 1
TerrainMesh::~TerrainMesh() {
//myScene->removeActor(*hfActor);
hfActor->release();
if (mMesh) delete mMesh;
}
TerrainMesh::TerrainMesh(PxPhysics& physics, PxCooking& cooking, PxScene& scene, PxMaterial& material, PxVec3 midPoint, const char* heightMapName, const char* textureName, float hfScale, float maxHeight, Shader* shader,
bool invert) {
mShader = shader;
mMesh = 0;
myScene = &scene;
BmpLoaderBuffer heightMapFile;
if (!heightMapFile.loadFile(heightMapName)) {
fprintf(stderr, "Error loading bmp '%s'\n");
return;
}
const PxReal heightScale = 0.005f;
//const PxReal heightScale = 0.01f;
unsigned int hfWidth = heightMapFile.mWidth;
unsigned int hfHeight = heightMapFile.mHeight;
unsigned char* heightmap = heightMapFile.mRGB;
const double i255 = 1.0/255.0;
PxTransform pose = PX_TRANSFORM_ID;
pose.p = midPoint + PxVec3(-((hfWidth - 1)*0.5f*hfScale), 0, -((hfHeight - 1)*0.5f*hfScale));
mHFPose = pose;
PxU32 hfNumVerts = hfWidth*hfHeight;
PxHeightFieldSample* samples = new PxHeightFieldSample[hfNumVerts];
memset(samples,0,hfNumVerts*sizeof(PxHeightFieldSample));
PxFilterData simulationFilterData;
simulationFilterData.word0 = COLLISION_FLAG_GROUND;
simulationFilterData.word1 = COLLISION_FLAG_GROUND_AGAINST;
PxFilterData queryFilterData;
VehicleSetupDrivableShapeQueryFilterData(&queryFilterData);
static PxI32 maxH = -2000000;
static PxI32 minH = 20000000;
for(PxU32 y = 0; y < hfHeight; y++)
{
for(PxU32 x = 0; x < hfWidth; x++)
{
PxU8 heightVal = heightmap[(y + x*hfWidth) * 3];
if (invert)
heightVal = 255 - heightVal;
PxI32 h = PxI32((maxHeight*heightVal*i255) / heightScale);
//Do a snap-to-grid...
h = ((h >> 4) << 4);
maxH = PxMax(h, maxH);
minH = PxMin(h, minH);
//h = h & (~0x7f);
//printf("%d ", h);
PX_ASSERT(h<=0xffff);
const PxU32 Index = x + y*hfWidth;
samples[Index].height = (PxI16)(h);
samples[Index].materialIndex0 = 0;
samples[Index].materialIndex1 = 0;
samples[Index].clearTessFlag();
}
}
// texture
if (strcmp(textureName, "") == 0) hfTexture = 0; else
hfTexture = loadImgTexture(textureName);
mMesh = new GLMesh(GL_TRIANGLES);
mMesh->vertices.resize(hfNumVerts);
mMesh->normals.resize(hfNumVerts);
mMesh->texCoords.resize(hfNumVerts*2);
mMesh->indices.clear();
float us = 1.0f / hfWidth;
float vs = 1.0f / hfHeight;
terrainHeights.clear();
terrainNormals.clear();
for (int i = 0; i < hfHeight; i++)
{
for (int j = 0; j < hfWidth; j++)
{
PxReal height = PxReal(samples[i + j*hfWidth].height) * heightScale;
mMesh->vertices[i*hfWidth + j] = PxVec3(hfScale*j, height, hfScale*i) + pose.p;
terrainHeights.push_back(mMesh->vertices[i*hfWidth+j].y);
mMesh->texCoords[(i*hfWidth + j)*2] = j*us;
mMesh->texCoords[(i*hfWidth + j)*2+1] = i*vs;
}
}
xStart = pose.p.x;
zStart = pose.p.z;
dx = hfScale;
for (int i = 0; i < hfHeight-1; i++) {
for (int j = 0; j < hfWidth-1; j++) {
//mMesh->vertices[i*hfWidth + j] = PxVec3(hfScale*j, maxHeight*heightmap[(j+i*hfWidth)*3]*i255, hfScale*i);
mMesh->indices.push_back(j + i*hfWidth);
mMesh->indices.push_back(j + (i + 1)*hfWidth);
mMesh->indices.push_back((j + 1) + i*hfWidth);
mMesh->indices.push_back((j + 1) + i*hfWidth);
mMesh->indices.push_back(j + (i + 1)*hfWidth);
mMesh->indices.push_back((j + 1) + (i + 1)*hfWidth);
}
}
mMesh->normals.resize(hfNumVerts);
for (int i = 0; i < hfNumVerts; i++) {
mMesh->normals[i] = PxVec3(0.0f, 0.0f, 0.0f);
}
int numTris = mMesh->indices.size() / 3;
for (int i = 0; i < numTris; i++) {
int i0 = mMesh->indices[i*3];
int i1 = mMesh->indices[i*3+1];
int i2 = mMesh->indices[i*3+2];
PxVec3 p0 = mMesh->vertices[i0];
PxVec3 p1 = mMesh->vertices[i1];
PxVec3 p2 = mMesh->vertices[i2];
PxVec3 normal = (p1-p0).cross(p2-p0);
mMesh->normals[i0] += normal;
mMesh->normals[i1] += normal;
mMesh->normals[i2] += normal;
}
for (int i = 0; i < hfNumVerts; i++) {
mMesh->normals[i].normalize();
}
mMesh->genVBOIBO();
mMesh->updateVBOIBO(false);
mMaterial.init();
mMaterial.texId = hfTexture;
terrainNormals = mMesh->normals;
width = hfWidth;
height = hfHeight;
idx = 1.0f/dx;
#if USE_HEIGHTFIELD
PxHeightFieldDesc hfDesc;
//hfDesc.format = PxHeightFieldFormat::eS16_TM;
hfDesc.nbColumns = hfWidth;
hfDesc.nbRows = hfHeight;
hfDesc.samples.data = samples;
hfDesc.samples.stride = sizeof(PxHeightFieldSample);
PxHeightField* heightField = cooking.createHeightField(hfDesc, physics.getPhysicsInsertionCallback());
hfActor = physics.createRigidStatic(pose);
PxHeightFieldGeometry hfGeom(heightField, PxMeshGeometryFlags(), heightScale, hfScale, hfScale);
PxShape* hfShape = PxRigidActorExt::createExclusiveShape(*hfActor, hfGeom, material);
hfShape->setQueryFilterData(queryFilterData);
hfShape->setSimulationFilterData(simulationFilterData);
scene.addActor(*hfActor);
delete[] samples;
#else
PxTriangleMeshDesc meshDesc;
meshDesc.points.data = &mMesh->vertices[0];
meshDesc.points.count = mMesh->vertices.size();
meshDesc.points.stride = sizeof(PxVec3);
meshDesc.triangles.stride = sizeof(PxU32)*3;
meshDesc.triangles.count = mMesh->indices.size()/3;
meshDesc.triangles.data = &mMesh->indices[0];
meshDesc.flags = PxMeshFlags();
PxTriangleMeshGeometry geom;
PxCookingParams params = cooking.getParams();
params.buildGRBData = true;
cooking.setParams(params);
PxDefaultMemoryOutputStream writeBuffer;
bool status = cooking.cookTriangleMesh(meshDesc, writeBuffer);
PX_ASSERT(status);
PxDefaultMemoryInputData readBuffer(writeBuffer.getData(), writeBuffer.getSize());
PxTriangleMesh* triangleMesh = physics.createTriangleMesh(readBuffer);
geom.triangleMesh = triangleMesh;
hfActor = physics.createRigidStatic(PxTransform(PxIdentity));
PxShape* meshShape = hfActor->createShape(geom, material);
meshShape->setQueryFilterData(queryFilterData);
meshShape->setSimulationFilterData(simulationFilterData);
scene.addActor(*hfActor);
#endif
}
void TerrainMesh::draw(bool useShader) {
if (useShader) mShader->activate(mMaterial);
mMesh->drawVBOIBO();
if (useShader) mShader->deactivate();
}
float TerrainMesh::getHeight(float x, float z) {
float nx = (x-xStart)*idx;
float nz = (z-zStart)*idx;
int ix = floor(nx);
int iz = floor(nz);
float fx = nx-ix;
float fz = nz-iz;
int ixp1 = ix+1;
int izp1 = iz+1;
ix = min(max(ix,0), width-1);
iz = min(max(iz,0), height-1);
ixp1 = min(max(ixp1,0), width-1);
izp1 = min(max(izp1,0), height-1);
int i00 = ix+iz*width;
int i10 = ixp1+iz*width;
int i01 = ix+izp1*width;
int i11 = ixp1+izp1*width;
float w00 = (1.0f-fx)*(1.0f-fz);
float w10 = (fx)*(1.0f-fz);
float w01 = (1.0f-fx)*(fz);
float w11 = (fx)*(fz);
return w00*terrainHeights[i00] +
w10*terrainHeights[i10] +
w01*terrainHeights[i01] +
w11*terrainHeights[i11];
}
float TerrainMesh::getHeightNormal(float x, float z, PxVec3& normal) {
float nx = (x-xStart)*idx;
float nz = (z-zStart)*idx;
int ix = floor(nx);
int iz = floor(nz);
float fx = nx-ix;
float fz = nz-iz;
int ixp1 = ix+1;
int izp1 = iz+1;
ix = min(max(ix,0), width-1);
iz = min(max(iz,0), height-1);
ixp1 = min(max(ixp1,0), width-1);
izp1 = min(max(izp1,0), height-1);
int i00 = ix+iz*width;
int i10 = ixp1+iz*width;
int i01 = ix+izp1*width;
int i11 = ixp1+izp1*width;
float w00 = (1.0f-fx)*(1.0f-fz);
float w10 = (fx)*(1.0f-fz);
float w01 = (1.0f-fx)*(fz);
float w11 = (fx)*(fz);
normal = w00*terrainNormals[i00] +
w10*terrainNormals[i10] +
w01*terrainNormals[i01] +
w11*terrainNormals[i11];
normal.normalize();
return w00*terrainHeights[i00] +
w10*terrainHeights[i10] +
w01*terrainHeights[i01] +
w11*terrainHeights[i11];
}
float TerrainMesh::getHeightNormalCondition(float x, float y, float z, PxVec3& normal) {
float nx = (x-xStart)*idx;
float nz = (z-zStart)*idx;
int ix = floor(nx);
int iz = floor(nz);
float fx = nx-ix;
float fz = nz-iz;
int ixp1 = ix+1;
int izp1 = iz+1;
ix = min(max(ix,0), width-1);
iz = min(max(iz,0), height-1);
ixp1 = min(max(ixp1,0), width-1);
izp1 = min(max(izp1,0), height-1);
int i00 = ix+iz*width;
int i10 = ixp1+iz*width;
int i01 = ix+izp1*width;
int i11 = ixp1+izp1*width;
float w00 = (1.0f-fx)*(1.0f-fz);
float w10 = (fx)*(1.0f-fz);
float w01 = (1.0f-fx)*(fz);
float w11 = (fx)*(fz);
float h = w00*terrainHeights[i00] +
w10*terrainHeights[i10] +
w01*terrainHeights[i01] +
w11*terrainHeights[i11];
if (h <= y) {
normal = w00*terrainNormals[i00] +
w10*terrainNormals[i10] +
w01*terrainNormals[i01] +
w11*terrainNormals[i11];
normal.normalize();
}
return h;
}

View File

@ -0,0 +1,66 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#pragma once
#include "BmpFile.h"
#include "glmesh.h"
#include "Shader.h"
#include "PxCooking.h"
#include <vector>
using namespace std;
class TerrainMesh{
public:
// Able to render mesh
// Able to generate physX
PxRigidStatic* hfActor;
PxTransform mHFPose;
GLuint hfTexture;
GLMesh* mMesh;
PxScene* myScene;
Shader* mShader;
ShaderMaterial mMaterial;
~TerrainMesh();
TerrainMesh(PxPhysics& physics, PxCooking& cooking, PxScene& scene, PxMaterial& material, PxVec3 midPoint, const char* heightMapName, const char* textureName,
float hfScale, float maxHeight, Shader* shader, bool invert = false);
void draw(bool useShader);
float xStart;
float zStart;
float dx, idx;
vector<float> terrainHeights;
vector<PxVec3> terrainNormals;
int width;
int height;
float getHeight(float x, float z);
float getHeightNormal(float x, float z, PxVec3& normal);
float getHeightNormalCondition(float x, float y, float z, PxVec3& normal);
};

View File

@ -0,0 +1,92 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2018 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 "TerrainRandomSamplePrecompute.h"
#include "SceneVehicle.h"
#include "PxTkStream.h"
#include "MediaPath.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;
}
TerrainRandomSamplePrecompute::TerrainRandomSamplePrecompute(SceneVehicle& app, const char* resourcePath)
: mPrecomputedRandomSequence(NULL),
mPrecomputedRandomSequenceCount(0)
{
mPrecomputedRandomSequence = new PxF32[(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 = FindMediaFile("SampleBaseRandomSequence", resourcePath);
PxDefaultFileInputData stream(filename);
if (!stream.isValid())
printf("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
}
TerrainRandomSamplePrecompute::~TerrainRandomSamplePrecompute()
{
delete[] mPrecomputedRandomSequence;
mPrecomputedRandomSequenceCount = 0;
}

View File

@ -0,0 +1,64 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2018 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 TERRAIN_RANDOM_SAMPLE_PRECOMPUTED_H
#define TERRAIN_RANDOM_SAMPLE_PRECOMPUTED_H
#include "common/PxPhysXCommonConfig.h"
#include "foundation/PxAssert.h"
using namespace physx;
class SceneVehicle;
class TerrainRandomSamplePrecompute
{
public:
TerrainRandomSamplePrecompute(SceneVehicle& app, const char* resourcePath);
~TerrainRandomSamplePrecompute();
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 //TERRAIN_RANDOM_SAMPLE_PRECOMPUTED_H

View File

@ -0,0 +1,63 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include <stdio.h>
#define NOMINMAX
#include <windows.h>
#include "Timing.h"
unsigned long getTime()
{
return timeGetTime();
}
float getCurrentTime()
{
unsigned int currentTime = timeGetTime();
return (float)(currentTime)*0.001f;
}
float getElapsedTime()
{
static LARGE_INTEGER previousTime;
static LARGE_INTEGER freq;
static bool init = false;
if(!init){
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&previousTime);
init=true;
}
LARGE_INTEGER currentTime;
QueryPerformanceCounter(&currentTime);
unsigned long long elapsedTime = currentTime.QuadPart - previousTime.QuadPart;
previousTime = currentTime;
return (float)(elapsedTime)/(freq.QuadPart);
}

View File

@ -0,0 +1,35 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef TIMING_H
#define TIMING_H
unsigned long getTime();
float getCurrentTime();
float getElapsedTime();
#endif

View File

@ -0,0 +1,209 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef BOUNDS3_H
#define BOUNDS3_H
#include "Vec3.h"
// Singe / VecVecReal Precision Vec 3
// Matthias Mueller
// derived from Vec3.h
namespace M
{
class Bounds3
{
public:
Vec3 minimum, maximum;
Bounds3()
{
// Default to empty boxes for compatibility TODO: PT: remove this if useless
setEmpty();
}
~Bounds3()
{
//nothing
}
void setEmpty()
{
// We know use this particular pattern for empty boxes
set(MAX_VEC_REAL, MAX_VEC_REAL, MAX_VEC_REAL,
MIN_VEC_REAL, MIN_VEC_REAL, MIN_VEC_REAL);
}
void setInfinite()
{
set(MIN_VEC_REAL, MIN_VEC_REAL, MIN_VEC_REAL,
MAX_VEC_REAL, MAX_VEC_REAL, MAX_VEC_REAL);
}
void set(VecReal mi, VecReal miny, VecReal minz, VecReal maxx, VecReal maxy,VecReal maxz)
{
minimum.set(mi, miny, minz);
maximum.set(maxx, maxy, maxz);
}
void set(const Vec3& _min, const Vec3& _max)
{
minimum = _min;
maximum = _max;
}
void include(const Vec3& v)
{
maximum.max(v);
minimum.min(v);
}
void combine(const Bounds3& b2)
{
// - if we're empty, min = MAX,MAX,MAX => min will be b2 in all cases => it will copy b2, ok
// - if b2 is empty, the opposite happens => keep us unchanged => ok
// => same behavior as before, automatically
minimum.min(b2.minimum);
maximum.max(b2.maximum);
}
//void boundsOfOBB(const Mat33& orientation, const Vec3& translation, const Vec3& halfDims)
//{
//VecReal dimx = halfDims[0];
//VecReal dimy = halfDims[1];
//VecReal dimz = halfDims[2];
//VecReal x = Math::abs(orientation(0,0) * dimx) + Math::abs(orientation(0,1) * dimy) + Math::abs(orientation(0,2) * dimz);
//VecReal y = Math::abs(orientation(1,0) * dimx) + Math::abs(orientation(1,1) * dimy) + Math::abs(orientation(1,2) * dimz);
//VecReal z = Math::abs(orientation(2,0) * dimx) + Math::abs(orientation(2,1) * dimy) + Math::abs(orientation(2,2) * dimz);
//set(-x + translation[0], -y + translation[1], -z + translation[2], x + translation[0], y + translation[1], z + translation[2]);
//}
//void transform(const Mat33& orientation, const Vec3& translation)
//{
//// convert to center and extents form
//Vec3 center, extents;
//getCenter(center);
//getExtents(extents);
//center = orientation * center + translation;
//boundsOfOBB(orientation, center, extents);
//}
bool isEmpty() const
{
// Consistency condition for (Min, Max) boxes: min < max
// TODO: PT: should we test against the explicit pattern ?
if(minimum.x < maximum.x) return false;
if(minimum.y < maximum.y) return false;
if(minimum.z < maximum.z) return false;
return true;
}
bool intersects(const Bounds3& b) const
{
if ((b.minimum.x > maximum.x) || (minimum.x > b.maximum.x)) return false;
if ((b.minimum.y > maximum.y) || (minimum.y > b.maximum.y)) return false;
if ((b.minimum.z > maximum.z) || (minimum.z > b.maximum.z)) return false;
return true;
}
bool intersects2D(const Bounds3& b, unsigned axis) const
{
// TODO: PT: could be static and like this:
// static unsigned i[3] = { 1,2,0,1 };
// const unsigned ii = i[axis];
// const unsigned jj = i[axis+1];
const unsigned i[3] = { 1,0,0 };
const unsigned j[3] = { 2,2,1 };
const unsigned ii = i[axis];
const unsigned jj = j[axis];
if ((b.minimum[ii] > maximum[ii]) || (minimum[ii] > b.maximum[ii])) return false;
if ((b.minimum[jj] > maximum[jj]) || (minimum[jj] > b.maximum[jj])) return false;
return true;
}
bool contain(const Vec3& v) const
{
if ((v.x < minimum.x) || (v.x > maximum.x)) return false;
if ((v.y < minimum.y) || (v.y > maximum.y)) return false;
if ((v.z < minimum.z) || (v.z > maximum.z)) return false;
return true;
}
void getCenter(Vec3& center) const
{
center.add(minimum,maximum);
center *= VecReal(0.5);
}
void getDimensions(Vec3& dims) const
{
dims.subtract(maximum,minimum);
}
void getExtents(Vec3& extents) const
{
extents.subtract(maximum,minimum);
extents *= VecReal(0.5);
}
void setCenterExtents(const Vec3& c, const Vec3& e)
{
minimum = c - e;
maximum = c + e;
}
void scale(VecReal _scale)
{
Vec3 center, extents;
getCenter(center);
getExtents(extents);
setCenterExtents(center, extents * _scale);
}
void fatten(VecReal distance)
{
minimum.x -= distance;
minimum.y -= distance;
minimum.z -= distance;
maximum.x += distance;
maximum.y += distance;
maximum.z += distance;
}
};
}
#endif

View File

@ -0,0 +1,100 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#ifndef PLANE_H
#define PLANE_H
#include "Vec3.H"
// Singe / VecReal Precision Vec 3
// Matthias Mueller
// derived from Plane
namespace M
{
class Plane
{
public:
Plane() {}
Plane(VecReal nx, VecReal ny, VecReal nz, VecReal distance)
: n(nx, ny, nz)
, d(distance)
{}
Plane(const Vec3& normal, VecReal distance)
: n(normal)
, d(distance)
{}
Plane(const Vec3& point, const Vec3& normal)
: n(normal)
, d(-point.dot(n)) // p satisfies normal.dot(p) + d = 0
{
}
Plane(const Vec3& p0, const Vec3& p1, const Vec3& p2)
{
n = (p1 - p0).cross(p2 - p0).getNormalized();
d = -p0.dot(n);
}
VecReal distance(const Vec3& p) const
{
return p.dot(n) + d;
}
bool contains(const Vec3& p) const
{
return vecAbs(distance(p)) < (1.0e-7f);
}
Vec3 project(const Vec3 & p) const
{
return p - n * distance(p);
}
Vec3 pointInPlane() const
{
return -n*d;
}
void normalize()
{
VecReal denom = 1.0f / n.magnitude();
n *= denom;
d *= denom;
}
Vec3 n; //!< The normal to the plane
VecReal d; //!< The distance from the origin
};
}
#endif

View File

@ -0,0 +1,328 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef QUAT_H
#define QUAT_H
// Singe / VecReal Precision Vec 3
// Matthias Mueller
// derived from Quat.h
#include "Vec3.h"
namespace M
{
class Quat
{
public:
Quat() { }
VecReal x,y,z,w;
Quat(VecReal nx, VecReal ny, VecReal nz, VecReal nw) : x(nx),y(ny),z(nz),w(nw) {}
Quat(VecReal angleRadians, const Vec3& unitAxis)
{
const VecReal a = angleRadians * 0.5f;
const VecReal s = vecSin(a);
w = cos(a);
x = unitAxis.x * s;
y = unitAxis.y * s;
z = unitAxis.z * s;
}
Quat(const Quat& v): x(v.x), y(v.y), z(v.z), w(v.w) {}
void toRadiansAndUnitAxis(VecReal& angle, Vec3& axis) const
{
const VecReal quatEpsilon = VecReal(1.0e-8f);
const VecReal s2 = x*x+y*y+z*z;
if(s2<quatEpsilon*quatEpsilon) // can't extract a sensible axis
{
angle = 0;
axis = Vec3(1,0,0);
}
else
{
const VecReal s = 1.0f / vecSqrt(s2);
axis = Vec3(x,y,z) * s;
angle = vecAbs(w)<quatEpsilon ? VEC_PI : vecAtan2(s2*s, w) * 2;
}
}
/**
\brief Gets the angle between this quat and the identity quaternion.
<b>Unit:</b> Radians
*/
VecReal getAngle() const
{
return vecACos(w) * VecReal(2);
}
/**
\brief Gets the angle between this quat and the argument
<b>Unit:</b> Radians
*/
VecReal getAngle(const Quat& q) const
{
return vecACos(dot(q)) * VecReal(2);
}
/**
\brief This is the squared 4D vector length, should be 1 for unit quaternions.
*/
VecReal magnitudeSquared() const
{
return x*x + y*y + z*z + w*w;
}
/**
\brief returns the scalar product of this and other.
*/
VecReal dot(const Quat& v) const
{
return x * v.x + y * v.y + z * v.z + w * v.w;
}
Quat getNormalized() const
{
const VecReal s = (VecReal)1.0/magnitude();
return Quat(x*s, y*s, z*s, w*s);
}
VecReal magnitude() const
{
return vecSqrt(magnitudeSquared());
}
//modifiers:
/**
\brief maps to the closest unit quaternion.
*/
VecReal normalize() // convert this Quat to a unit quaternion
{
const VecReal mag = magnitude();
if (mag)
{
const VecReal imag = VecReal(1) / mag;
x *= imag;
y *= imag;
z *= imag;
w *= imag;
}
return mag;
}
/*
\brief returns the conjugate.
\note for unit quaternions, this is the inverse.
*/
Quat getConjugate() const
{
return Quat(-x,-y,-z,w);
}
/*
\brief returns imaginary part.
*/
Vec3 getImaginaryPart() const
{
return Vec3(x,y,z);
}
/** brief computes rotation of x-axis */
Vec3 getBasisVector0() const
{
// return rotate(Vec3(1,0,0));
const VecReal x2 = x*(VecReal)2.0;
const VecReal w2 = w*(VecReal)2.0;
return Vec3( (w * w2) - 1.0f + x*x2,
(z * w2) + y*x2,
(-y * w2) + z*x2);
}
/** brief computes rotation of y-axis */
Vec3 getBasisVector1() const
{
// return rotate(Vec3(0,1,0));
const VecReal y2 = y*(VecReal)2.0;
const VecReal w2 = w*(VecReal)2.0;
return Vec3( (-z * w2) + x*y2,
(w * w2) - 1.0f + y*y2,
(x * w2) + z*y2);
}
/** brief computes rotation of z-axis */
Vec3 getBasisVector2() const
{
// return rotate(Vec3(0,0,1));
const VecReal z2 = z*(VecReal)2.0;
const VecReal w2 = w*(VecReal)2.0;
return Vec3( (y * w2) + x*z2,
(-x * w2) + y*z2,
(w * w2) - 1.0f + z*z2);
}
/**
rotates passed vec by this (assumed unitary)
*/
const Vec3 rotate(const Vec3& v) const
// const Vec3 rotate(const Vec3& v) const
{
const VecReal vx = (VecReal)2.0*v.x;
const VecReal vy = (VecReal)2.0*v.y;
const VecReal vz = (VecReal)2.0*v.z;
const VecReal w2 = w*w-(VecReal)0.5;
const VecReal dot2 = (x*vx + y*vy +z*vz);
return Vec3
(
(vx*w2 + (y * vz - z * vy)*w + x*dot2),
(vy*w2 + (z * vx - x * vz)*w + y*dot2),
(vz*w2 + (x * vy - y * vx)*w + z*dot2)
);
/*
const Vec3 qv(x,y,z);
return (v*(w*w-0.5f) + (qv.cross(v))*w + qv*(qv.dot(v)))*2;
*/
}
/**
inverse rotates passed vec by this (assumed unitary)
*/
const Vec3 rotateInv(const Vec3& v) const
// const Vec3 rotateInv(const Vec3& v) const
{
const VecReal vx = (VecReal)2.0*v.x;
const VecReal vy = (VecReal)2.0*v.y;
const VecReal vz = (VecReal)2.0*v.z;
const VecReal w2 = w*w-(VecReal)0.5;
const VecReal dot2 = (x*vx + y*vy +z*vz);
return Vec3
(
(vx*w2 - (y * vz - z * vy)*w + x*dot2),
(vy*w2 - (z * vx - x * vz)*w + y*dot2),
(vz*w2 - (x * vy - y * vx)*w + z*dot2)
);
// const Vec3 qv(x,y,z);
// return (v*(w*w-0.5f) - (qv.cross(v))*w + qv*(qv.dot(v)))*2;
}
/**
\brief Assignment operator
*/
Quat& operator=(const Quat& p) { x = p.x; y = p.y; z = p.z; w = p.w; return *this; }
Quat& operator*= (const Quat& q)
{
const VecReal tx = w*q.x + q.w*x + y*q.z - q.y*z;
const VecReal ty = w*q.y + q.w*y + z*q.x - q.z*x;
const VecReal tz = w*q.z + q.w*z + x*q.y - q.x*y;
w = w*q.w - q.x*x - y*q.y - q.z*z;
x = tx;
y = ty;
z = tz;
return *this;
}
Quat& operator+= (const Quat& q)
{
x+=q.x;
y+=q.y;
z+=q.z;
w+=q.w;
return *this;
}
Quat& operator-= (const Quat& q)
{
x-=q.x;
y-=q.y;
z-=q.z;
w-=q.w;
return *this;
}
Quat& operator*= (const VecReal s)
{
x*=s;
y*=s;
z*=s;
w*=s;
return *this;
}
/** quaternion multiplication */
Quat operator*(const Quat& q) const
{
return Quat(w*q.x + q.w*x + y*q.z - q.y*z,
w*q.y + q.w*y + z*q.x - q.z*x,
w*q.z + q.w*z + x*q.y - q.x*y,
w*q.w - x*q.x - y*q.y - z*q.z);
}
/** quaternion addition */
Quat operator+(const Quat& q) const
{
return Quat(x+q.x,y+q.y,z+q.z,w+q.w);
}
/** quaternion subtraction */
Quat operator-() const
{
return Quat(-x,-y,-z,-w);
}
Quat operator-(const Quat& q) const
{
return Quat(x-q.x,y-q.y,z-q.z,w-q.w);
}
Quat operator*(VecReal r) const
{
return Quat(x*r,y*r,z*r,w*r);
}
static Quat createIdentity() { return Quat(0,0,0,1); }
};
}
#endif

View File

@ -0,0 +1,121 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#ifndef TRANSFORM_H
#define TRANSFORM_H
#include "Vec3.h"
#include "Quat.h"
#include "Plane.h"
// Singe / VecVecReal Precision Vec 3
// Matthias Mueller
// derived from NxVec3.h
namespace M
{
class Transform
{
public:
Quat q;
Vec3 p;
Transform() {};
Transform(const Vec3& position): q(0, 0, 0, 1), p(position) {}
Transform(const Quat& orientation): q(orientation), p(0, 0, 0) {}
Transform(const Vec3& p0, const Quat& q0): q(q0), p(p0) {}
Transform operator*(const Transform& x) const
{
return transform(x);
}
Transform getInverse() const
{
return Transform(q.rotateInv(-p),q.getConjugate());
}
Vec3 transform(const Vec3& input) const
{
return q.rotate(input) + p;
}
Vec3 transformInv(const Vec3& input) const
{
return q.rotateInv(input-p);
}
Vec3 rotate(const Vec3& input) const
{
return q.rotate(input);
}
Vec3 rotateInv(const Vec3& input) const
{
return q.rotateInv(input);
}
Transform transform(const Transform& src) const
{
return Transform(q.rotate(src.p) + p, q*src.q);
}
Transform transformInv(const Transform& src) const
{
Quat qinv = q.getConjugate();
return Transform(qinv.rotate(src.p - p), qinv*src.q);
}
static Transform createIdentity()
{
return Transform(Vec3(0));
}
Plane transform(const Plane& plane) const
{
Vec3 transformedNormal = rotate(plane.n);
return Plane(transformedNormal, plane.d - p.dot(transformedNormal));
}
Plane inverseTransform(const Plane& plane) const
{
Vec3 transformedNormal = rotateInv(plane.n);
return Plane(transformedNormal, plane.d + p.dot(plane.n));
}
Transform getNormalized() const
{
return Transform(p, q.getNormalized());
}
};
}
#endif

View File

@ -0,0 +1,517 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef VEC3_H
#define VEC3_H
#include <math.h>
// Singe / VecReal Precision Vec 3
// Matthias Mueller
// derived from NxVec3.h
namespace M
{
#define VEC3_DOUBLE 0
#if VEC3_DOUBLE
typedef double VecReal;
#define MAX_VEC_REAL DBL_MAX
#define MIN_VEC_REAL -DBL_MAX
#define VEC_PI 3.14159265358979323846
inline int vecFloor(VecReal f ) { return (int)::floor(f); }
inline VecReal vecSqrt(VecReal f) { return ::sqrt(f); }
inline VecReal vecSin(VecReal f) { return ::sin(f); }
inline VecReal vecCos(VecReal f) { return ::cos(f); }
inline VecReal vecAbs(VecReal f) { return ::abs(f); }
inline VecReal vecAtan2(VecReal y, VecReal x) { return ::atan2(y, x); }
inline VecReal vecASin(VecReal f) { return ::asin(f); }
inline VecReal vecACos(VecReal f) { return ::acos(f); }
inline VecReal vecATan(VecReal f) { return ::atan(f); }
#else
typedef float VecReal;
#define MAX_VEC_REAL FLT_MAX
#define MIN_VEC_REAL -FLT_MAX
#define VEC_PI 3.14159265358979323846f
inline int vecFloor(VecReal f ) { return (int)::floorf(f); }
inline VecReal vecSqrt(VecReal f) { return ::sqrtf(f); }
inline VecReal vecSin(VecReal f) { return ::sinf(f); }
inline VecReal vecCos(VecReal f) { return ::cosf(f); }
inline VecReal vecAbs(VecReal f) { return ::fabs(f); }
inline VecReal vecAtan2(VecReal y, VecReal x) { return ::atan2f(y, x); }
inline VecReal vecASin(VecReal f) { return ::asinf(f); }
inline VecReal vecACos(VecReal f) { return ::acosf(f); }
inline VecReal vecATan(VecReal f) { return ::atanf(f); }
#endif
/**
\brief Enum to classify an axis.
*/
enum DAxisType
{
D_AXIS_PLUS_X,
D_AXIS_MINUS_X,
D_AXIS_PLUS_Y,
D_AXIS_MINUS_Y,
D_AXIS_PLUS_Z,
D_AXIS_MINUS_Z,
D_AXIS_ARBITRARY
};
// -------------------------------------------------------------------------------------
class Vec3
{
public:
VecReal x,y,z;
Vec3() {};
Vec3(VecReal _x, VecReal _y, VecReal _z) : x(_x), y(_y), z(_z) {}
Vec3(const VecReal v[]) : x(v[0]), y(v[1]), z(v[2]) {}
const VecReal* Vec3::get() const { return &x;}
VecReal* get() { return &x; }
void get(VecReal * v) const
{
v[0] = x;
v[1] = y;
v[2] = z;
}
VecReal& operator[](int index)
{
return (&x)[index];
}
const VecReal operator[](int index) const
{
return (&x)[index];
}
void setx(const VecReal & d)
{
x = d;
}
void sety(const VecReal & d)
{
y = d;
}
void setz(const VecReal & d)
{
z = d;
}
Vec3 getNormalized() const
{
const VecReal m = magnitudeSquared();
return m>0 ? *this * 1.0 / vecSqrt(m) : Vec3(0,0,0);
}
//Operators
bool operator< (const Vec3&v) const
{
return ((x < v.x)&&(y < v.y)&&(z < v.z));
}
bool operator==(const Vec3& v) const
{
return ((x == v.x)&&(y == v.y)&&(z == v.z));
}
bool operator!=(const Vec3& v) const
{
return ((x != v.x)||(y != v.y)||(z != v.z));
}
//Methods
void set(const Vec3 & v)
{
x = v.x;
y = v.y;
z = v.z;
}
void setNegative(const Vec3 & v)
{
x = -v.x;
y = -v.y;
z = -v.z;
}
void setNegative()
{
x = -x;
y = -y;
z = -z;
}
void set(const VecReal * v)
{
x = v[0];
y = v[1];
z = v[2];
}
void set(VecReal _x, VecReal _y, VecReal _z)
{
this->x = _x;
this->y = _y;
this->z = _z;
}
void set(VecReal v)
{
x = v;
y = v;
z = v;
}
void zero()
{
x = y = z = 0.0;
}
void setPlusInfinity()
{
x = y = z = MAX_VEC_REAL;
}
void setMinusInfinity()
{
x = y = z = MIN_VEC_REAL;
}
void max(const Vec3 & v)
{
x = x > v.x ? x : v.x;
y = y > v.y ? y : v.y;
z = z > v.z ? z : v.z;
}
void min(const Vec3 & v)
{
x = x < v.x ? x : v.x;
y = y < v.y ? y : v.y;
z = z < v.z ? z : v.z;
}
void add(const Vec3 & a, const Vec3 & b)
{
x = a.x + b.x;
y = a.y + b.y;
z = a.z + b.z;
}
void subtract(const Vec3 &a, const Vec3 &b)
{
x = a.x - b.x;
y = a.y - b.y;
z = a.z - b.z;
}
void arrayMultiply(const Vec3 &a, const Vec3 &b)
{
x = a.x * b.x;
y = a.y * b.y;
z = a.z * b.z;
}
void multiply(VecReal s, const Vec3 & a)
{
x = a.x * s;
y = a.y * s;
z = a.z * s;
}
void multiplyAdd(VecReal s, const Vec3 & a, const Vec3 & b)
{
x = s * a.x + b.x;
y = s * a.y + b.y;
z = s * a.z + b.z;
}
VecReal normalize()
{
VecReal m = magnitude();
if (m)
{
const VecReal il = VecReal(1.0) / m;
x *= il;
y *= il;
z *= il;
}
return m;
}
void setMagnitude(VecReal length)
{
VecReal m = magnitude();
if(m)
{
VecReal newLength = length / m;
x *= newLength;
y *= newLength;
z *= newLength;
}
}
DAxisType snapToClosestAxis()
{
const VecReal almostOne = 0.999999f;
if(x >= almostOne) { set( 1.0f, 0.0f, 0.0f); return D_AXIS_PLUS_X ; }
else if(x <= -almostOne) { set(-1.0f, 0.0f, 0.0f); return D_AXIS_MINUS_X; }
else if(y >= almostOne) { set( 0.0f, 1.0f, 0.0f); return D_AXIS_PLUS_Y ; }
else if(y <= -almostOne) { set( 0.0f, -1.0f, 0.0f); return D_AXIS_MINUS_Y; }
else if(z >= almostOne) { set( 0.0f, 0.0f, 1.0f); return D_AXIS_PLUS_Z ; }
else if(z <= -almostOne) { set( 0.0f, 0.0f, -1.0f); return D_AXIS_MINUS_Z; }
else return D_AXIS_ARBITRARY;
}
unsigned int closestAxis() const
{
const VecReal* vals = &x;
unsigned int m = 0;
if(abs(vals[1]) > abs(vals[m])) m = 1;
if(abs(vals[2]) > abs(vals[m])) m = 2;
return m;
}
//const methods
//bool isFinite() const
//{
// return NxMath::isFinite(x) && NxMath::isFinite(y) && NxMath::isFinite(z);
//}
VecReal dot(const Vec3 &v) const
{
return x * v.x + y * v.y + z * v.z;
}
bool sameDirection(const Vec3 &v) const
{
return x*v.x + y*v.y + z*v.z >= 0.0f;
}
VecReal magnitude() const
{
return sqrt(x * x + y * y + z * z);
}
VecReal magnitudeSquared() const
{
return x * x + y * y + z * z;
}
VecReal distance(const Vec3 & v) const
{
VecReal dx = x - v.x;
VecReal dy = y - v.y;
VecReal dz = z - v.z;
return sqrt(dx * dx + dy * dy + dz * dz);
}
VecReal distanceSquared(const Vec3 &v) const
{
VecReal dx = x - v.x;
VecReal dy = y - v.y;
VecReal dz = z - v.z;
return dx * dx + dy * dy + dz * dz;
}
void cross(const Vec3 &left, const Vec3 & right) //prefered version, w/o temp object.
{
// temps needed in case left or right is this.
VecReal a = (left.y * right.z) - (left.z * right.y);
VecReal b = (left.z * right.x) - (left.x * right.z);
VecReal c = (left.x * right.y) - (left.y * right.x);
x = a;
y = b;
z = c;
}
bool equals(const Vec3 & v, VecReal epsilon) const
{
return
abs(x - v.x) < epsilon &&
abs(y - v.y) < epsilon &&
abs(z - v.z) < epsilon;
}
Vec3 operator -() const
{
return Vec3(-x, -y, -z);
}
Vec3 operator +(const Vec3 & v) const
{
return Vec3(x + v.x, y + v.y, z + v.z); // RVO version
}
Vec3 operator -(const Vec3 & v) const
{
return Vec3(x - v.x, y - v.y, z - v.z); // RVO version
}
Vec3 operator *(VecReal f) const
{
return Vec3(x * f, y * f, z * f); // RVO version
}
Vec3 operator /(VecReal f) const
{
f = VecReal(1.0) / f; return Vec3(x * f, y * f, z * f);
}
Vec3& operator +=(const Vec3& v)
{
x += v.x;
y += v.y;
z += v.z;
return *this;
}
Vec3& operator -=(const Vec3& v)
{
x -= v.x;
y -= v.y;
z -= v.z;
return *this;
}
Vec3& operator *=(VecReal f)
{
x *= f;
y *= f;
z *= f;
return *this;
}
Vec3& operator /=(VecReal f)
{
f = 1.0f/f;
x *= f;
y *= f;
z *= f;
return *this;
}
Vec3 cross(const Vec3& v) const
{
Vec3 temp;
temp.cross(*this,v);
return temp;
}
Vec3 operator^(const Vec3& v) const
{
Vec3 temp;
temp.cross(*this,v);
return temp;
}
VecReal operator|(const Vec3& v) const
{
return x * v.x + y * v.y + z * v.z;
}
};
/**
scalar pre-multiplication
*/
inline Vec3 operator *(VecReal f, const Vec3& v)
{
return Vec3(f * v.x, f * v.y, f * v.z);
}
}
/** @} */
#endif

View File

@ -0,0 +1,165 @@
//
// 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-2018 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 "VehicleCameraController.h"
#include "PxRigidDynamic.h"
#include "PxQueryFiltering.h"
#include "PxScene.h"
#include "PxSceneLock.h"
#include "vehicle/PxVehicleWheels.h"
///////////////////////////////////////////////////////////////////////////////
VehicleCameraController::VehicleCameraController()
: mRotateInputY(0.0f),
mRotateInputZ(0.0f),
mMaxCameraRotateSpeed(5.0f),
mCameraRotateAngleY(0.0f),
mCameraRotateAngleZ(0.13f),
mCameraPos(PxVec3(0, 0, 0)),
mCameraTargetPos(PxVec3(0, 0, 0)),
mLastCarPos(PxVec3(0, 0, 0)),
mLastCarVelocity(PxVec3(0, 0, 0)),
mCameraInit(false),
mLockOnFocusVehTransform(true),
mLastFocusVehTransform(PxTransform(PxIdentity)),
mCamDist(5.f)
{
}
VehicleCameraController::~VehicleCameraController()
{
}
static void dampVec3(const PxVec3& oldPosition, PxVec3& newPosition, PxF32 timestep)
{
PxF32 t = 0.7f * timestep * 8.0f;
t = PxMin(t, 1.0f);
newPosition = oldPosition * (1 - t) + newPosition * t;
}
void VehicleCameraController::update(const PxReal dtime, const PxRigidDynamic* actor, PxScene& scene)
{
PxSceneReadLock scopedLock(scene);
PxTransform carChassisTransfm;
if (mLockOnFocusVehTransform)
{
carChassisTransfm = actor->getGlobalPose();
mLastFocusVehTransform = carChassisTransfm;
}
else
{
carChassisTransfm = mLastFocusVehTransform;
}
PxF32 camDist = 5.f;
PxF32 cameraYRotExtra = 0.0f;
PxVec3 velocity = mLastCarPos - carChassisTransfm.p;
if (mCameraInit)
{
//Work out the forward and sideways directions.
PxVec3 unitZ(0, 0, 1);
PxVec3 carDirection = carChassisTransfm.q.rotate(unitZ);
PxVec3 unitX(1, 0, 0);
PxVec3 carSideDirection = carChassisTransfm.q.rotate(unitX);
//Acceleration (note that is not scaled by time).
PxVec3 acclVec = mLastCarVelocity - velocity;
//Higher forward accelerations allow the car to speed away from the camera.
PxF32 velZ = PxAbs(carDirection.dot(velocity));
camDist = PxMin(PxMax(camDist + velZ*100.0f, 10.0f), 15.f);
//Higher sideways accelerations allow the car's rotation to speed away from the camera's rotation.
PxF32 acclX = carSideDirection.dot(acclVec);
cameraYRotExtra = -acclX*10.0f;
//At very small sideways speeds the camera greatly amplifies any numeric error in the body and leads to a slight jitter.
//Scale cameraYRotExtra by a value in range (0,1) for side speeds in range (0.1,1.0) and by zero for side speeds less than 0.1.
PxFixedSizeLookupTable<4> table;
table.addPair(0.0f, 0.0f);
table.addPair(0.1f*dtime, 0);
table.addPair(1.0f*dtime, 1);
PxF32 velX = carSideDirection.dot(velocity);
cameraYRotExtra *= table.getYVal(PxAbs(velX));
}
mCameraRotateAngleY += mRotateInputY*mMaxCameraRotateSpeed*dtime;
mCameraRotateAngleY = physx::intrinsics::fsel(mCameraRotateAngleY - 10 * PxPi, mCameraRotateAngleY - 10 * PxPi, physx::intrinsics::fsel(-mCameraRotateAngleY - 10 * PxPi, mCameraRotateAngleY + 10 * PxPi, mCameraRotateAngleY));
mCameraRotateAngleZ += mRotateInputZ*mMaxCameraRotateSpeed*dtime;
mCameraRotateAngleZ = PxClamp(mCameraRotateAngleZ, -PxPi*0.05f, PxPi*0.45f);
PxVec3 cameraDir = PxVec3(0, 0, 1)*PxCos(mCameraRotateAngleY + cameraYRotExtra) + PxVec3(1, 0, 0)*PxSin(mCameraRotateAngleY + cameraYRotExtra);
cameraDir = cameraDir*PxCos(mCameraRotateAngleZ) - PxVec3(0, 1, 0)*PxSin(mCameraRotateAngleZ);
const PxVec3 direction = carChassisTransfm.q.rotate(cameraDir);
PxVec3 target = carChassisTransfm.p;
target.y += 0.5f;
PxRaycastBuffer hit;
PxQueryFilterData filterData(PxQueryFlag::eSTATIC | PxQueryFlag::eDYNAMIC);
scene.raycast(target, -direction, camDist, hit, PxHitFlag::eDEFAULT, filterData);
if (hit.hasBlock && hit.block.shape != NULL)
{
camDist = hit.block.distance - 0.25f;
}
camDist = PxMax(4.0f, PxMin(camDist, 50.0f));
mCamDist += PxMax(camDist - mCamDist, 0.f)*0.05f + PxMin(0.f, camDist - mCamDist);
camDist = mCamDist;
PxVec3 position = target - direction*camDist;
if (mCameraInit)
{
dampVec3(mCameraPos, position, dtime);
dampVec3(mCameraTargetPos, target, dtime);
}
mCameraPos = position;
mCameraTargetPos = target;
mCameraInit = true;
mLastCarVelocity = velocity;
mLastCarPos = carChassisTransfm.p;
}
void VehicleCameraController::update(const PxReal dtime, const PxVehicleWheels& focusVehicle, PxScene& scene)
{
const PxRigidDynamic* actor = focusVehicle.getRigidDynamicActor();
update(dtime, actor, scene);
}

View File

@ -0,0 +1,93 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2018 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 VEHICLE_CAMERA_CONTROLLER_H
#define VEHICLE_CAMERA_CONTROLLER_H
#include "common/PxPhysXCommonConfig.h"
#include "foundation/PxVec3.h"
#include "foundation/PxTransform.h"
using namespace physx;
namespace physx
{
class PxScene;
class PxVehicleWheels;
class PxRigidDynamic;
}
;
class VehicleCameraController
{
public:
VehicleCameraController();
~VehicleCameraController();
void setInputs(const PxF32 rotateInputY, const PxF32 rotateInputZ)
{
mRotateInputY = rotateInputY;
mRotateInputZ = rotateInputZ;
}
void update(const PxF32 dtime, const PxVehicleWheels& focusVehicle, PxScene& scene);
void restart() {}
bool getIsLockedOnVehicleTransform() const { return mLockOnFocusVehTransform; }
void toggleLockOnVehTransform() { mLockOnFocusVehTransform = !mLockOnFocusVehTransform; }
const PxVec3& getCameraPos() const { return mCameraPos; }
const PxVec3& getCameraTar() const { return mCameraTargetPos; }
private:
PxF32 mRotateInputY;
PxF32 mRotateInputZ;
PxF32 mMaxCameraRotateSpeed;
PxF32 mCameraRotateAngleY;
PxF32 mCameraRotateAngleZ;
PxVec3 mCameraPos;
PxVec3 mCameraTargetPos;
PxVec3 mLastCarPos;
PxVec3 mLastCarVelocity;
bool mCameraInit;
bool mLockOnFocusVehTransform;
PxTransform mLastFocusVehTransform;
PxReal mCamDist;
void update(const PxReal dtime, const PxRigidDynamic* actor, PxScene& scene);
};
#endif //SAMPLE_VEHICLE_CAMERA_CONTROLLER_H

View File

@ -0,0 +1,65 @@
//
// 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-2018 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 "VehicleControlInputs.h"
///////////////////////////////////////////////////////////////////////////////
VehicleControlInputs::VehicleControlInputs()
: mCameraRotateInputY(0.0f),
mCameraRotateInputZ(0.0f),
mAccelKeyPressed(false),
mGearUpKeyPressed(false),
mGearDownKeyPressed(false),
mBrakeKeyPressed(false),
mHandbrakeKeyPressed(false),
mSteerLeftKeyPressed(false),
mSteerRightKeyPressed(false),
mBrakeLeftKeyPressed(false),
mBrakeRightKeyPressed(false),
mThrustLeftKeyPressed(false),
mThrustRightKeyPressed(false),
mAccel(0.0f),
mGearup(false),
mGeardown(false),
mBrake(0.0f),
mSteer(0.0f),
mHandbrake(false),
mThrustLeft(0.0f),
mThrustRight(0.0f),
mBrakeLeft(0.0f),
mBrakeRight(0.0f)
{
}
VehicleControlInputs::~VehicleControlInputs()
{
}

View File

@ -0,0 +1,145 @@
//
// 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-2018 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 VEHICLE_CONTROL_INPUTS_H
#define VEHICLE_CONTROL_INPUTS_H
#include "common/PxPhysXCommonConfig.h"
using namespace physx;
class VehicleControlInputs
{
public:
VehicleControlInputs();
~VehicleControlInputs();
//Camera inputs
void setRotateY(const PxF32 f) { mCameraRotateInputY = f; }
void setRotateZ(const PxF32 f) { mCameraRotateInputZ = f; }
PxF32 getRotateY() const { return mCameraRotateInputY; }
PxF32 getRotateZ() const { return mCameraRotateInputZ; }
//Keyboard driving inputs - (car + tank)
void setAccelKeyPressed(const bool b) { mAccelKeyPressed = b; }
void setGearUpKeyPressed(const bool b) { mGearUpKeyPressed = b; }
void setGearDownKeyPressed(const bool b) { mGearDownKeyPressed = b; }
bool getAccelKeyPressed() const { return mAccelKeyPressed; }
bool getGearUpKeyPressed() const { return mGearUpKeyPressed; }
bool getGearDownKeyPressed() const { return mGearDownKeyPressed; }
//Keyboard driving inputs - (car only)
void setBrakeKeyPressed(const bool b) { mBrakeKeyPressed = b; }
void setHandbrakeKeyPressed(const bool b) { mHandbrakeKeyPressed = b; }
void setSteerLeftKeyPressed(const bool b) { mSteerLeftKeyPressed = b; }
void setSteerRightKeyPressed(const bool b) { mSteerRightKeyPressed = b; }
bool getBrakeKeyPressed() const { return mBrakeKeyPressed; }
bool getHandbrakeKeyPressed() const { return mHandbrakeKeyPressed; }
bool getSteerLeftKeyPressed() const { return mSteerLeftKeyPressed; }
bool getSteerRightKeyPressed() const { return mSteerRightKeyPressed; }
//Keyboard driving inputs - (tank only)
void setBrakeLeftKeyPressed(const bool b) { mBrakeLeftKeyPressed = b; }
void setBrakeRightKeyPressed(const bool b) { mBrakeRightKeyPressed = b; }
void setThrustLeftKeyPressed(const bool b) { mThrustLeftKeyPressed = b; }
void setThrustRightKeyPressed(const bool b) { mThrustRightKeyPressed = b; }
bool getBrakeLeftKeyPressed() const { return mBrakeLeftKeyPressed; }
bool getBrakeRightKeyPressed() const { return mBrakeRightKeyPressed; }
bool getThrustLeftKeyPressed() const { return mThrustLeftKeyPressed; }
bool getThrustRightKeyPressed() const { return mThrustRightKeyPressed; }
//Gamepad driving inputs (car + tank)
void setAccel(const PxF32 f) { mAccel = f; }
void setGearUp(const bool b) { mGearup = b; }
void setGearDown(const bool b) { mGeardown = b; }
PxF32 getAccel() const { return mAccel; }
bool getGearUp() const { return mGearup; }
bool getGearDown() const { return mGeardown; }
//Gamepad driving inputs (car only)
void setBrake(const PxF32 f) { mBrake = f; }
void setSteer(const PxF32 f) { mSteer = f; }
void setHandbrake(const bool b) { mHandbrake = b; }
PxF32 getBrake() const { return mBrake; }
PxF32 getSteer() const { return mSteer; }
bool getHandbrake() const { return mHandbrake; }
//Gamepad driving inputs (tank only)
void setThrustLeft(const PxF32 f) { mThrustLeft = f; }
void setThrustRight(const PxF32 f) { mThrustRight = f; }
PxF32 getThrustLeft() const { return mThrustLeft; }
PxF32 getThrustRight() const { return mThrustRight; }
void setBrakeLeft(const PxF32 f) { mBrakeLeft = f; }
void setBrakeRight(const PxF32 f) { mBrakeRight = f; }
PxF32 getBrakeLeft() const { return mBrakeLeft; }
PxF32 getBrakeRight() const { return mBrakeRight; }
private:
//Camera inputs.
PxF32 mCameraRotateInputY;
PxF32 mCameraRotateInputZ;
//keyboard inputs (car and tank)
bool mAccelKeyPressed;
bool mGearUpKeyPressed;
bool mGearDownKeyPressed;
//keyboard inputs (car only)
bool mBrakeKeyPressed;
bool mHandbrakeKeyPressed;
bool mSteerLeftKeyPressed;
bool mSteerRightKeyPressed;
//keyboard inputs (tank only)
bool mBrakeLeftKeyPressed;
bool mBrakeRightKeyPressed;
bool mThrustLeftKeyPressed;
bool mThrustRightKeyPressed;
//gamepad inputs (car and tank)
PxF32 mAccel;
bool mGearup;
bool mGeardown;
//gamepad inputs (car only)
PxF32 mBrake;
PxF32 mSteer;
bool mHandbrake;
//gamepad inputs (tank only)
PxF32 mThrustLeft;
PxF32 mThrustRight;
PxF32 mBrakeLeft;
PxF32 mBrakeRight;
};
#endif //VEHICLE_CONTROL_INPUTS_H

View File

@ -0,0 +1,808 @@
//
// 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-2018 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 "VehicleController.h"
#include "vehicle/PxVehicleDrive4W.h"
#include "vehicle/PxVehicleDriveNW.h"
#include "vehicle/PxVehicleUtilControl.h"
#include "vehicle/PxVehicleUtil.h"
#include <stdio.h>
PxVehicleKeySmoothingData gKeySmoothingData =
{
{
5.0f, //rise rate eANALOG_INPUT_ACCEL
5.0f, //rise rate eANALOG_INPUT_BRAKE
10.0f, //rise rate eANALOG_INPUT_HANDBRAKE
2.5f, //rise rate eANALOG_INPUT_STEER_LEFT
2.5f, //rise rate eANALOG_INPUT_STEER_RIGHT
},
{
7.0f, //fall rate eANALOG_INPUT__ACCEL
7.0f, //fall rate eANALOG_INPUT__BRAKE
10.0f, //fall rate eANALOG_INPUT__HANDBRAKE
5.0f, //fall rate eANALOG_INPUT_STEER_LEFT
5.0f //fall rate eANALOG_INPUT_STEER_RIGHT
}
};
PxVehiclePadSmoothingData gCarPadSmoothingData =
{
{
6.0f, //rise rate eANALOG_INPUT_ACCEL
6.0f, //rise rate eANALOG_INPUT_BRAKE
12.0f, //rise rate eANALOG_INPUT_HANDBRAKE
2.5f, //rise rate eANALOG_INPUT_STEER_LEFT
2.5f, //rise rate eANALOG_INPUT_STEER_RIGHT
},
{
10.0f, //fall rate eANALOG_INPUT_ACCEL
10.0f, //fall rate eANALOG_INPUT_BRAKE
12.0f, //fall rate eANALOG_INPUT_HANDBRAKE
5.0f, //fall rate eANALOG_INPUT_STEER_LEFT
5.0f //fall rate eANALOG_INPUT_STEER_RIGHT
}
};
PxF32 gSteerVsForwardSpeedData[2 * 8] =
{
0.0f, 0.75f,
5.0f, 0.75f,
30.0f, 0.125f,
120.0f, 0.1f,
PX_MAX_F32, PX_MAX_F32,
PX_MAX_F32, PX_MAX_F32,
PX_MAX_F32, PX_MAX_F32,
PX_MAX_F32, PX_MAX_F32
};
PxFixedSizeLookupTable<8> gSteerVsForwardSpeedTable(gSteerVsForwardSpeedData, 4);
//Tank smoothing data.
PxVehiclePadSmoothingData gTankPadSmoothingData =
{
{
6.0f, //rise rate eTANK_ANALOG_INPUT_ACCEL
6.0f, //rise rate eTANK_ANALOG_INPUT_BRAKE_LEFT
6.0f, //rise rate eTANK_ANALOG_INPUT_BRAKE_RIGHT
2.5f, //rise rate eTANK_ANALOG_INPUT_THRUST_LEFT
2.5f, //rise rate eTANK_ANALOG_INPUT_THRUST_RIGHT
},
{
10.0f, //fall rate eTANK_ANALOG_INPUT_ACCEL
10.0f, //fall rate eTANK_ANALOG_INPUT_BRAKE_LEFT
10.0f, //fall rate eTANK_ANALOG_INPUT_BRAKE_RIGHT
5.0f, //fall rate eTANK_ANALOG_INPUT_THRUST_LEFT
5.0f //fall rate eTANK_ANALOG_INPUT_THRUST_RIGHT
}
};
///////////////////////////////////////////////////////////////////////////////
VehicleController::VehicleController()
{
clear();
}
VehicleController::~VehicleController()
{
}
void VehicleController::clear()
{
mKeyPressedAccel = false;
mKeyPressedGearUp = false;
mKeyPressedGearDown = false;
mKeyPressedBrake = false;
mKeyPressedHandbrake = false;
mKeyPressedSteerLeft = false;
mKeyPressedSteerRight = false;
mKeyPressedThrustLeft = false;
mKeyPressedThrustRight = false;
mKeyPressedBrakeLeft = false;
mKeyPressedBrakeRight = false;
mGamepadAccel = 0.0f;
mGamepadGearup = false;
mGamepadGeardown = false;
mGamepadCarBrake = 0.0f;
mGamepadCarSteer = 0.0f;
mGamepadCarHandbrake = false;
mTankThrustLeft = 0.0f;
mTankThrustRight = 0.0f;
mTankBrakeLeft = 0.0f;
mTankBrakeRight = 0.0f;
mRecord = false;
mReplay = false;
mNumSamples = 0;
mNumRecordedSamples = 0;
mUseKeyInputs = true;
mToggleAutoGears = false;
mIsMovingForwardSlowly = true;
mInReverseMode = false;
}
/*
bool SampleVehicle_VehicleController::processAutoReverse
(const PxF32 timestep, const bool isInAir, const PxF32 forwardSpeed, const PxF32 sidewaysSpeed, const PxVehicleDriveTankRawInputData& rawInputData)
{
//Keyboard controls for tank not implemented yet.
bool brakeLeft,brakeRight,accelLeft,accelRight;
if(mUseKeyInputs)
{
//Keyboard controls for tank not implemented yet.
brakeLeft=false;
brakeRight=false;
accelLeft=false;
accelRight=false;
}
else if(PxVehicleDriveTank::eDRIVE_MODEL_STANDARD==rawInputData.getDriveModel())
{
brakeLeft = mInReverseMode ? rawInputData.getAnalogLeftThrust() > 0 : rawInputData.getAnalogLeftBrake() > 0.0f;
brakeRight = mInReverseMode ? rawInputData.getAnalogRightThrust() > 0 : rawInputData.getAnalogRightBrake() > 0.0f;
accelLeft = mInReverseMode ? rawInputData.getAnalogLeftBrake() > 0 : rawInputData.getAnalogLeftThrust() > 0.0f;
accelRight = mInReverseMode ? rawInputData.getAnalogRightBrake() > 0 : rawInputData.getAnalogRightThrust() > 0.0f;
}
else
{
//Not much point in auto-reverse for tanks that can just spin both wheels backwards.
return false;
}
//If the car has been brought to rest by pressing the brake then raise a flag.
bool justRaisedFlag=false;
if(brakeLeft && brakeRight && !mAtRestUnderBraking)
{
if(!isInAir && forwardSpeed < THRESHOLD_FORWARD_SPEED && sidewaysSpeed < THRESHOLD_SIDEWAYS_SPEED)
{
justRaisedFlag=true;
mAtRestUnderBraking = true;
mTimeElapsedSinceAtRestUnderBraking = 0.0f;
}
}
//If the flag is raised and the player pressed accelerate then lower the flag.
if(mAtRestUnderBraking && (accelLeft || accelRight))
{
mAtRestUnderBraking = false;
mTimeElapsedSinceAtRestUnderBraking = 0.0f;
}
//If the flag is raised and the player doesn't press brake then increment the timer.
if(!brakeLeft && !brakeRight && mAtRestUnderBraking && !justRaisedFlag)
{
mTimeElapsedSinceAtRestUnderBraking += timestep;
}
//If the flag is raised and the player pressed brake again then switch auto-reverse.
if(brakeLeft && brakeRight && mAtRestUnderBraking && !justRaisedFlag && mTimeElapsedSinceAtRestUnderBraking > 0.0f)
{
mAtRestUnderBraking = false;
mTimeElapsedSinceAtRestUnderBraking = 0.0f;
return true;
}
return false;
}
*/
void VehicleController::processRawInputs
(const PxF32 dtime, const bool useAutoGears, PxVehicleDrive4WRawInputData& rawInputData)
{
// Keyboard
{
if (mRecord)
{
if (mNumSamples<MAX_NUM_RECORD_REPLAY_SAMPLES)
{
mKeyboardAccelValues[mNumSamples] = mKeyPressedAccel;
mKeyboardBrakeValues[mNumSamples] = mKeyPressedBrake;
mKeyboardHandbrakeValues[mNumSamples] = mKeyPressedHandbrake;
mKeyboardSteerLeftValues[mNumSamples] = mKeyPressedSteerLeft;
mKeyboardSteerRightValues[mNumSamples] = mKeyPressedSteerRight;
mKeyboardGearupValues[mNumSamples] = mKeyPressedGearUp;
mKeyboardGeardownValues[mNumSamples] = mKeyPressedGearDown;
}
}
else if (mReplay)
{
if (mNumSamples<mNumRecordedSamples)
{
mKeyPressedAccel = mKeyboardAccelValues[mNumSamples];
mKeyPressedBrake = mKeyboardBrakeValues[mNumSamples];
mKeyPressedHandbrake = mKeyboardHandbrakeValues[mNumSamples];
mKeyPressedSteerLeft = mKeyboardSteerLeftValues[mNumSamples];
mKeyPressedSteerRight = mKeyboardSteerRightValues[mNumSamples];
mKeyPressedGearUp = mKeyboardGearupValues[mNumSamples];
mKeyPressedGearDown = mKeyboardGeardownValues[mNumSamples];
}
}
rawInputData.setDigitalAccel(mKeyPressedAccel);
rawInputData.setDigitalBrake(mKeyPressedBrake);
rawInputData.setDigitalHandbrake(mKeyPressedHandbrake);
rawInputData.setDigitalSteerLeft(mKeyPressedSteerLeft);
rawInputData.setDigitalSteerRight(mKeyPressedSteerRight);
rawInputData.setGearUp(mKeyPressedGearUp);
rawInputData.setGearDown(mKeyPressedGearDown);
mUseKeyInputs =
(mKeyPressedAccel || mKeyPressedBrake || mKeyPressedHandbrake ||
mKeyPressedSteerLeft || mKeyPressedSteerRight ||
mKeyPressedGearUp || mKeyPressedGearDown);
}
// Gamepad
{
if (mRecord)
{
if (mNumSamples<MAX_NUM_RECORD_REPLAY_SAMPLES)
{
mGamepadAccelValues[mNumSamples] = mGamepadAccel;
mGamepadCarBrakeValues[mNumSamples] = mGamepadCarBrake;
mGamepadCarSteerValues[mNumSamples] = mGamepadCarSteer;
mGamepadGearupValues[mNumSamples] = mGamepadGearup;
mGamepadGeardownValues[mNumSamples] = mGamepadGeardown;
mGamepadCarHandbrakeValues[mNumSamples] = mGamepadCarHandbrake;
}
}
else if (mReplay)
{
if (mNumSamples<mNumRecordedSamples)
{
mGamepadAccel = mGamepadAccelValues[mNumSamples];
mGamepadCarBrake = mGamepadCarBrakeValues[mNumSamples];
mGamepadCarSteer = mGamepadCarSteerValues[mNumSamples];
mGamepadGearup = mGamepadGearupValues[mNumSamples];
mGamepadGeardown = mGamepadGeardownValues[mNumSamples];
mGamepadCarHandbrake = mGamepadCarHandbrakeValues[mNumSamples];
}
}
if (mGamepadAccel<0.0f || mGamepadAccel>1.01f)
printf("Illegal accel value from gamepad!\n");
if (mGamepadCarBrake<0.0f || mGamepadCarBrake>1.01f)
printf("Illegal brake value from gamepad!\n");
if (PxAbs(mGamepadCarSteer)>1.01f)
printf("Illegal steer value from gamepad!\n");
if (mUseKeyInputs && ((mGamepadAccel + mGamepadCarBrake + mGamepadCarSteer) != 0.0f || mGamepadGearup || mGamepadGeardown || mGamepadCarHandbrake))
{
mUseKeyInputs = false;
}
if (!mUseKeyInputs)
{
rawInputData.setAnalogAccel(mGamepadAccel);
rawInputData.setAnalogBrake(mGamepadCarBrake);
rawInputData.setAnalogHandbrake(mGamepadCarHandbrake ? 1.0f : 0.0f);
rawInputData.setAnalogSteer(mGamepadCarSteer);
rawInputData.setGearUp(mGamepadGearup);
rawInputData.setGearDown(mGamepadGeardown);
}
}
if (useAutoGears && (rawInputData.getGearDown() || rawInputData.getGearUp()))
{
rawInputData.setGearDown(false);
rawInputData.setGearUp(false);
}
mNumSamples++;
}
void VehicleController::processRawInputs
(const PxF32 dtime, const bool useAutoGears, PxVehicleDriveTankRawInputData& rawInputData)
{
// Keyboard
//Keyboard controls for tank not implemented yet.
{
/*
if(mRecord)
{
if(mNumSamples<MAX_NUM_RECORD_REPLAY_SAMPLES)
{
mKeyboardAccelValues[mNumSamples] = mAccelKeyPressed;
mKeyboardBrakeValues[mNumSamples] = mBrakeKeyPressed;
mKeyboardHandbrakeValues[mNumSamples] = mHandbrakeKeyPressed;
mKeyboardSteerLeftValues[mNumSamples] = mSteerLeftKeyPressed;
mKeyboardSteerRightValues[mNumSamples] = mSteerRightKeyPressed;
mKeyboardGearupValues[mNumSamples] = mGearUpKeyPressed;
mKeyboardGeardownValues[mNumSamples] = mGearDownKeyPressed;
}
}
else if(mReplay)
{
if(mNumSamples<mNumRecordedSamples)
{
mAccelKeyPressed = mKeyboardAccelValues[mNumSamples];
mBrakeKeyPressed = mKeyboardBrakeValues[mNumSamples];
mHandbrakeKeyPressed = mKeyboardHandbrakeValues[mNumSamples];
mSteerLeftKeyPressed = mKeyboardSteerLeftValues[mNumSamples];
mSteerRightKeyPressed = mKeyboardSteerRightValues[mNumSamples];
mGearUpKeyPressed = mKeyboardGearupValues[mNumSamples];
mGearDownKeyPressed = mKeyboardGeardownValues[mNumSamples];
}
}
*/
rawInputData.setDigitalAccel(mKeyPressedAccel);
rawInputData.setDigitalLeftThrust(mKeyPressedThrustLeft);
rawInputData.setDigitalRightThrust(mKeyPressedThrustRight);
rawInputData.setDigitalLeftBrake(mKeyPressedBrakeLeft);
rawInputData.setDigitalRightBrake(mKeyPressedBrakeRight);
rawInputData.setGearUp(mKeyPressedGearUp);
rawInputData.setGearDown(mKeyPressedGearDown);
mUseKeyInputs =
(mKeyPressedAccel || mKeyPressedThrustLeft || mKeyPressedThrustRight ||
mKeyPressedBrakeLeft || mKeyPressedBrakeRight ||
mKeyPressedGearUp || mKeyPressedGearDown);
}
// Gamepad
{
if (mRecord)
{
if (mNumSamples<MAX_NUM_RECORD_REPLAY_SAMPLES)
{
mGamepadAccelValues[mNumSamples] = mGamepadAccel;
mGamepadTankThrustLeftValues[mNumSamples] = mTankThrustLeft;
mGamepadTankThrustRightValues[mNumSamples] = mTankThrustRight;
mGamepadGearupValues[mNumSamples] = mGamepadGearup;
mGamepadGeardownValues[mNumSamples] = mGamepadGeardown;
}
}
else if (mReplay)
{
if (mNumSamples<mNumRecordedSamples)
{
mGamepadAccel = mGamepadAccelValues[mNumSamples];
mTankThrustLeft = mGamepadTankThrustLeftValues[mNumSamples];
mTankThrustRight = mGamepadTankThrustRightValues[mNumSamples];
mGamepadGearup = mGamepadGearupValues[mNumSamples];
mGamepadGeardown = mGamepadGeardownValues[mNumSamples];
}
}
if (mGamepadAccel<0.0f || mGamepadAccel>1.01f)
printf("Illegal accel value from gamepad!\n");
if (mTankThrustLeft<-1.01f || mTankThrustLeft>1.01f)
printf("Illegal brake value from gamepad!\n");
if (mTankThrustRight<-1.01f || mTankThrustRight>1.01f)
printf("Illegal steer value from gamepad\n");
if (mUseKeyInputs && ((mGamepadAccel + mTankThrustLeft + mTankThrustRight) != 0.0f || mGamepadGearup || mGamepadGeardown))
{
mUseKeyInputs = false;
}
if (!mUseKeyInputs)
{
rawInputData.setAnalogAccel(mGamepadAccel);
rawInputData.setAnalogLeftThrust(mTankThrustLeft);
rawInputData.setAnalogRightThrust(mTankThrustRight);
rawInputData.setAnalogLeftBrake(mTankBrakeLeft);
rawInputData.setAnalogRightBrake(mTankBrakeRight);
rawInputData.setGearUp(mGamepadGearup);
rawInputData.setGearDown(mGamepadGeardown);
}
}
if (useAutoGears && (rawInputData.getGearDown() || rawInputData.getGearUp()))
{
rawInputData.setGearDown(false);
rawInputData.setGearUp(false);
}
mNumSamples++;
}
#define THRESHOLD_FORWARD_SPEED (0.1f)
#define THRESHOLD_SIDEWAYS_SPEED (0.2f)
#define THRESHOLD_ROLLING_BACKWARDS_SPEED (0.1f)
void VehicleController::processAutoReverse
(const PxVehicleWheels& focusVehicle, const PxVehicleDriveDynData& driveDynData, const PxVehicleWheelQueryResult& vehicleWheelQueryResults,
const PxVehicleDrive4WRawInputData& carRawInputs,
bool& toggleAutoReverse, bool& newIsMovingForwardSlowly) const
{
newIsMovingForwardSlowly = false;
toggleAutoReverse = false;
if (driveDynData.getUseAutoGears())
{
//If the car is travelling very slowly in forward gear without player input and the player subsequently presses the brake then we want the car to go into reverse gear
//If the car is travelling very slowly in reverse gear without player input and the player subsequently presses the accel then we want the car to go into forward gear
//If the car is in forward gear and is travelling backwards then we want to automatically put the car into reverse gear.
//If the car is in reverse gear and is travelling forwards then we want to automatically put the car into forward gear.
//(If the player brings the car to rest with the brake the player needs to release the brake then reapply it
//to indicate they want to toggle between forward and reverse.)
const bool prevIsMovingForwardSlowly = mIsMovingForwardSlowly;
bool isMovingForwardSlowly = false;
bool isMovingBackwards = false;
const bool isInAir = PxVehicleIsInAir(vehicleWheelQueryResults);
if (!isInAir)
{
bool accelRaw, brakeRaw, handbrakeRaw;
if (mUseKeyInputs)
{
accelRaw = carRawInputs.getDigitalAccel();
brakeRaw = carRawInputs.getDigitalBrake();
handbrakeRaw = carRawInputs.getDigitalHandbrake();
}
else
{
accelRaw = carRawInputs.getAnalogAccel() > 0 ? true : false;
brakeRaw = carRawInputs.getAnalogBrake() > 0 ? true : false;
handbrakeRaw = carRawInputs.getAnalogHandbrake() > 0 ? true : false;
}
const PxF32 forwardSpeed = focusVehicle.computeForwardSpeed();
const PxF32 forwardSpeedAbs = PxAbs(forwardSpeed);
const PxF32 sidewaysSpeedAbs = PxAbs(focusVehicle.computeSidewaysSpeed());
const PxU32 currentGear = driveDynData.getCurrentGear();
const PxU32 targetGear = driveDynData.getTargetGear();
//Check if the car is rolling against the gear (backwards in forward gear or forwards in reverse gear).
if (PxVehicleGearsData::eFIRST == currentGear && forwardSpeed < -THRESHOLD_ROLLING_BACKWARDS_SPEED)
{
isMovingBackwards = true;
}
else if (PxVehicleGearsData::eREVERSE == currentGear && forwardSpeed > THRESHOLD_ROLLING_BACKWARDS_SPEED)
{
isMovingBackwards = true;
}
//Check if the car is moving slowly.
if (forwardSpeedAbs < THRESHOLD_FORWARD_SPEED && sidewaysSpeedAbs < THRESHOLD_SIDEWAYS_SPEED)
{
isMovingForwardSlowly = true;
}
//Now work if we need to toggle from forwards gear to reverse gear or vice versa.
if (isMovingBackwards)
{
if (!accelRaw && !brakeRaw && !handbrakeRaw && (currentGear == targetGear))
{
//The car is rolling against the gear and the player is doing nothing to stop this.
toggleAutoReverse = true;
}
}
else if (prevIsMovingForwardSlowly && isMovingForwardSlowly)
{
if ((currentGear > PxVehicleGearsData::eNEUTRAL) && brakeRaw && !accelRaw && (currentGear == targetGear))
{
//The car was moving slowly in forward gear without player input and is now moving slowly with player input that indicates the
//player wants to switch to reverse gear.
toggleAutoReverse = true;
}
else if (currentGear == PxVehicleGearsData::eREVERSE && accelRaw && !brakeRaw && (currentGear == targetGear))
{
//The car was moving slowly in reverse gear without player input and is now moving slowly with player input that indicates the
//player wants to switch to forward gear.
toggleAutoReverse = true;
}
}
//If the car was brought to rest through braking and the player is still braking then start the process that will lead to toggling
//between reverse and forward gears.
if (isMovingForwardSlowly)
{
if (currentGear >= PxVehicleGearsData::eFIRST && brakeRaw)
{
newIsMovingForwardSlowly = true;
}
else if (currentGear == PxVehicleGearsData::eREVERSE && accelRaw)
{
newIsMovingForwardSlowly = true;
}
}
}
}
}
void VehicleController::processAutoReverse
(const PxVehicleWheels& focusVehicle, const PxVehicleDriveDynData& driveDynData, const PxVehicleWheelQueryResult& vehicleWheelQueryResults,
const PxVehicleDriveTankRawInputData& tankRawInputs,
bool& toggleAutoReverse, bool& newIsMovingForwardSlowly) const
{
newIsMovingForwardSlowly = false;
toggleAutoReverse = false;
if (driveDynData.getUseAutoGears())
{
//If the car is travelling very slowly in forward gear without player input and the player subsequently presses the brake then we want the car to go into reverse gear
//If the car is travelling very slowly in reverse gear without player input and the player subsequently presses the accel then we want the car to go into forward gear
//If the car is in forward gear and is travelling backwards then we want to automatically put the car into reverse gear.
//If the car is in reverse gear and is travelling forwards then we want to automatically put the car into forward gear.
//(If the player brings the car to rest with the brake the player needs to release the brake then reapply it
//to indicate they want to toggle between forward and reverse.)
const bool prevIsMovingForwardSlowly = mIsMovingForwardSlowly;
bool isMovingForwardSlowly = false;
bool isMovingBackwards = false;
const bool isInAir = PxVehicleIsInAir(vehicleWheelQueryResults);
if (!isInAir)
{
bool accelLeft, accelRight, brakeLeft, brakeRight;
if (mUseKeyInputs)
{
accelLeft = tankRawInputs.getDigitalLeftThrust();
accelRight = tankRawInputs.getDigitalRightThrust();
brakeLeft = tankRawInputs.getDigitalLeftBrake();
brakeRight = tankRawInputs.getDigitalRightBrake();
}
else
{
accelLeft = tankRawInputs.getAnalogLeftThrust() > 0 ? true : false;
accelRight = tankRawInputs.getAnalogRightThrust() > 0 ? true : false;
brakeLeft = tankRawInputs.getAnalogLeftBrake() > 0 ? true : false;
brakeRight = tankRawInputs.getAnalogRightBrake() > 0 ? true : false;
/*
if(accelLeft && accelLeft==accelRight && !brakeLeft && !brakeRight)
{
shdfnd::printFormatted("aligned accel\n");
}
if(brakeLeft && brakeLeft==brakeRight && !accelLeft && !accelRight)
{
shdfnd::printFormatted("aligned brake\n");
}
*/
}
const PxF32 forwardSpeed = focusVehicle.computeForwardSpeed();
const PxF32 forwardSpeedAbs = PxAbs(forwardSpeed);
const PxF32 sidewaysSpeedAbs = PxAbs(focusVehicle.computeSidewaysSpeed());
const PxU32 currentGear = driveDynData.getCurrentGear();
const PxU32 targetGear = driveDynData.getTargetGear();
//Check if the car is rolling against the gear (backwards in forward gear or forwards in reverse gear).
if (PxVehicleGearsData::eFIRST == currentGear && forwardSpeed < -THRESHOLD_ROLLING_BACKWARDS_SPEED)
{
isMovingBackwards = true;
}
else if (PxVehicleGearsData::eREVERSE == currentGear && forwardSpeed > THRESHOLD_ROLLING_BACKWARDS_SPEED)
{
isMovingBackwards = true;
}
//Check if the car is moving slowly.
if (forwardSpeedAbs < THRESHOLD_FORWARD_SPEED && sidewaysSpeedAbs < THRESHOLD_SIDEWAYS_SPEED)
{
isMovingForwardSlowly = true;
}
//Now work if we need to toggle from forwards gear to reverse gear or vice versa.
if (isMovingBackwards)
{
if (!accelLeft && !accelRight && !brakeLeft && !brakeRight && (currentGear == targetGear))
{
//The car is rolling against the gear and the player is doing nothing to stop this.
toggleAutoReverse = true;
}
}
else if (prevIsMovingForwardSlowly && isMovingForwardSlowly)
{
if ((currentGear > PxVehicleGearsData::eNEUTRAL) && brakeLeft && brakeRight && !accelLeft && !accelRight && (currentGear == targetGear))
{
//The car was moving slowly in forward gear without player input and is now moving slowly with player input that indicates the
//player wants to switch to reverse gear.
toggleAutoReverse = true;
}
else if (currentGear == PxVehicleGearsData::eREVERSE && accelLeft && accelRight && !brakeLeft && !brakeRight && (currentGear == targetGear))
{
//The car was moving slowly in reverse gear without player input and is now moving slowly with player input that indicates the
//player wants to switch to forward gear.
toggleAutoReverse = true;
}
}
//If the car was brought to rest through braking then the player needs to release the brake then reapply
//to indicate that the gears should toggle between reverse and forward.
if (isMovingForwardSlowly && (!brakeLeft || !brakeRight) && (!accelLeft || !accelRight))
{
newIsMovingForwardSlowly = true;
}
}
}
}
void VehicleController::update(const PxF32 timestep, const PxVehicleWheelQueryResult& vehicleWheelQueryResults, PxVehicleWheels& focusVehicle)
{
PxVehicleDriveDynData* driveDynData = NULL;
bool isTank = false;
PxVehicleDriveTankControlModel::Enum tankDriveModel = PxVehicleDriveTankControlModel::eSTANDARD;
switch (focusVehicle.getVehicleType())
{
case PxVehicleTypes::eDRIVE4W:
{
PxVehicleDrive4W& vehDrive4W = (PxVehicleDrive4W&)focusVehicle;
driveDynData = &vehDrive4W.mDriveDynData;
isTank = false;
}
break;
case PxVehicleTypes::eDRIVENW:
{
PxVehicleDriveNW& vehDriveNW = (PxVehicleDriveNW&)focusVehicle;
driveDynData = &vehDriveNW.mDriveDynData;
isTank = false;
}
break;
case PxVehicleTypes::eDRIVETANK:
{
PxVehicleDriveTank& vehDriveTank = (PxVehicleDriveTank&)focusVehicle;
driveDynData = &vehDriveTank.mDriveDynData;
isTank = true;
tankDriveModel = vehDriveTank.getDriveModel();
}
break;
default:
PX_ASSERT(false);
break;
}
//Toggle autogear flag
if (mToggleAutoGears)
{
driveDynData->toggleAutoGears();
mToggleAutoGears = false;
}
//Store raw inputs in replay stream if in recording mode.
//Set raw inputs from replay stream if in replay mode.
//Store raw inputs from active stream in handy arrays so we don't need to worry
//about which stream (live input or replay) is active.
//Work out if we are using keys or gamepad controls depending on which is being used
//(gamepad selected if both are being used).
PxVehicleDrive4WRawInputData carRawInputs;
PxVehicleDriveTankRawInputData tankRawInputs(tankDriveModel);
processRawInputs(timestep, driveDynData->getUseAutoGears(), carRawInputs);
//Work out if the car is to flip from reverse to forward gear or from forward gear to reverse.
bool toggleAutoReverse = false;
bool newIsMovingForwardSlowly = false;
processAutoReverse(focusVehicle, *driveDynData, vehicleWheelQueryResults, carRawInputs, toggleAutoReverse, newIsMovingForwardSlowly);
mIsMovingForwardSlowly = newIsMovingForwardSlowly;
//If the car is to flip gear direction then switch gear as appropriate.
if (toggleAutoReverse)
{
mInReverseMode = !mInReverseMode;
if (mInReverseMode)
{
driveDynData->forceGearChange(PxVehicleGearsData::eREVERSE);
}
else
{
driveDynData->forceGearChange(PxVehicleGearsData::eFIRST);
}
}
//If in reverse mode then swap the accel and brake.
if (mInReverseMode)
{
if (mUseKeyInputs)
{
const bool accel = carRawInputs.getDigitalAccel();
const bool brake = carRawInputs.getDigitalBrake();
carRawInputs.setDigitalAccel(brake);
carRawInputs.setDigitalBrake(accel);
}
else
{
if (!isTank)
{
const PxF32 accel = carRawInputs.getAnalogAccel();
const PxF32 brake = carRawInputs.getAnalogBrake();
carRawInputs.setAnalogAccel(brake);
carRawInputs.setAnalogBrake(accel);
}
else if (PxVehicleDriveTankControlModel::eSPECIAL == tankDriveModel)
{
const PxF32 thrustLeft = tankRawInputs.getAnalogLeftThrust();
const PxF32 thrustRight = tankRawInputs.getAnalogRightThrust();
tankRawInputs.setAnalogLeftThrust(-thrustLeft);
tankRawInputs.setAnalogRightThrust(-thrustRight);
}
else
{
const PxF32 thrustLeft = tankRawInputs.getAnalogLeftThrust();
const PxF32 thrustRight = tankRawInputs.getAnalogRightThrust();
const PxF32 brakeLeft = tankRawInputs.getAnalogLeftBrake();
const PxF32 brakeRight = tankRawInputs.getAnalogRightBrake();
tankRawInputs.setAnalogLeftThrust(brakeLeft);
tankRawInputs.setAnalogLeftBrake(thrustLeft);
tankRawInputs.setAnalogRightThrust(brakeRight);
tankRawInputs.setAnalogRightBrake(thrustRight);
}
}
}
// Now filter the raw input values and apply them to focus vehicle
// as floats for brake,accel,handbrake,steer and bools for gearup,geardown.
if (mUseKeyInputs)
{
const bool isInAir = PxVehicleIsInAir(vehicleWheelQueryResults);
PxVehicleDrive4WSmoothDigitalRawInputsAndSetAnalogInputs
(gKeySmoothingData, gSteerVsForwardSpeedTable, carRawInputs, timestep, isInAir, (PxVehicleDrive4W&)focusVehicle);
}
else
{
const bool isInAir = PxVehicleIsInAir(vehicleWheelQueryResults);
PxVehicleDrive4WSmoothAnalogRawInputsAndSetAnalogInputs
(gCarPadSmoothingData, gSteerVsForwardSpeedTable, carRawInputs, timestep, isInAir, (PxVehicleDrive4W&)focusVehicle);
}
}
void VehicleController::restart()
{
const bool record = mRecord;
const bool replay = mReplay;
const PxU32 numSamples = mNumSamples;
const PxU32 numRecordedSamples = mNumRecordedSamples;
clear();
mRecord = record;
mReplay = replay;
mNumRecordedSamples = numRecordedSamples;
if (record)
{
PX_ASSERT(!replay);
mNumRecordedSamples = numSamples;
mRecord = false;
mReplay = true;
}
}

View File

@ -0,0 +1,226 @@
//
// 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-2018 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 VEHICLE_CONTROLLER_H
#define VEHICLE_CONTROLLER_H
#include "common/PxPhysXCommonConfig.h"
#include "foundation/PxVec3.h"
#include "vehicle/PxVehicleSDK.h"
#include "vehicle/PxVehicleUpdate.h"
#include "vehicle/PxVehicleUtilControl.h"
using namespace physx;
class VehicleController
{
public:
VehicleController();
~VehicleController();
void setCarKeyboardInputs
(const bool accel, const bool brake, const bool handbrake,
const bool steerleft, const bool steerright,
const bool gearup, const bool geardown)
{
mKeyPressedAccel = accel;
mKeyPressedBrake = brake;
mKeyPressedHandbrake = handbrake;
mKeyPressedSteerLeft = steerleft;
mKeyPressedSteerRight = steerright;
mKeyPressedGearUp = gearup;
mKeyPressedGearDown = geardown;
}
void setCarGamepadInputs
(const PxF32 accel, const PxF32 brake,
const PxF32 steer,
const bool gearup, const bool geardown,
const bool handbrake)
{
mGamepadAccel = accel;
mGamepadCarBrake = brake;
mGamepadCarSteer = steer;
mGamepadGearup = gearup;
mGamepadGeardown = geardown;
mGamepadCarHandbrake = handbrake;
}
void setTankKeyboardInputs
(const bool accel, const bool thrustLeft, const bool thrustRight, const bool brakeLeft, const bool brakeRight, const bool gearUp, const bool gearDown)
{
mKeyPressedAccel = accel;
mKeyPressedThrustLeft = thrustLeft;
mKeyPressedThrustRight = thrustRight;
mKeyPressedBrakeLeft = brakeLeft;
mKeyPressedBrakeRight = brakeRight;
mKeyPressedGearUp = gearUp;
mKeyPressedGearDown = gearDown;
}
void setTankGamepadInputs
(const PxF32 accel, const PxF32 thrustLeft, const PxF32 thrustRight, const PxF32 brakeLeft, const PxF32 brakeRight, const bool gearUp, const bool gearDown)
{
mGamepadAccel = accel;
mTankThrustLeft = thrustLeft;
mTankThrustRight = thrustRight;
mTankBrakeLeft = brakeLeft;
mTankBrakeRight = brakeRight;
mGamepadGearup = gearUp;
mGamepadGeardown = gearDown;
}
void toggleAutoGearFlag()
{
mToggleAutoGears = true;
}
void update(const PxF32 dtime, const PxVehicleWheelQueryResult& vehicleWheelQueryResults, PxVehicleWheels& focusVehicle);
void clear();
private:
//Raw driving inputs - keys (car + tank)
bool mKeyPressedAccel;
bool mKeyPressedGearUp;
bool mKeyPressedGearDown;
//Raw driving inputs - keys (car only)
bool mKeyPressedBrake;
bool mKeyPressedHandbrake;
bool mKeyPressedSteerLeft;
bool mKeyPressedSteerRight;
//Raw driving inputs - keys (tank only)
bool mKeyPressedThrustLeft;
bool mKeyPressedThrustRight;
bool mKeyPressedBrakeLeft;
bool mKeyPressedBrakeRight;
//Raw driving inputs - gamepad (car + tank)
PxF32 mGamepadAccel;
bool mGamepadGearup;
bool mGamepadGeardown;
//Raw driving inputs - gamepad (car only)
PxF32 mGamepadCarBrake;
PxF32 mGamepadCarSteer;
bool mGamepadCarHandbrake;
//Raw driving inputs - (tank only)
PxF32 mTankThrustLeft;
PxF32 mTankThrustRight;
PxF32 mTankBrakeLeft;
PxF32 mTankBrakeRight;
//Record and replay using raw driving inputs.
bool mRecord;
bool mReplay;
enum
{
MAX_NUM_RECORD_REPLAY_SAMPLES = 8192
};
// Keyboard
bool mKeyboardAccelValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mKeyboardBrakeValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mKeyboardHandbrakeValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mKeyboardSteerLeftValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mKeyboardSteerRightValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mKeyboardGearupValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mKeyboardGeardownValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
// Gamepad - (tank + car)
PxF32 mGamepadAccelValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mGamepadGearupValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mGamepadGeardownValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
// Gamepad - car only
PxF32 mGamepadCarBrakeValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
PxF32 mGamepadCarSteerValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mGamepadCarHandbrakeValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
//Gamepad - tank only.
PxF32 mGamepadTankThrustLeftValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
PxF32 mGamepadTankThrustRightValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
PxU32 mNumSamples;
PxU32 mNumRecordedSamples;
// Raw data taken from the correct stream (live input stream or replay stream)
bool mUseKeyInputs;
// Toggle autogears flag on focus vehicle
bool mToggleAutoGears;
//Auto-reverse mode.
bool mIsMovingForwardSlowly;
bool mInReverseMode;
//Update
void processRawInputs(const PxF32 timestep, const bool useAutoGears, PxVehicleDrive4WRawInputData& rawInputData);
void processRawInputs(const PxF32 timestep, const bool useAutoGears, PxVehicleDriveTankRawInputData& rawInputData);
void processAutoReverse(
const PxVehicleWheels& focusVehicle, const PxVehicleDriveDynData& driveDynData, const PxVehicleWheelQueryResult& vehicleWheelQueryResults,
const PxVehicleDrive4WRawInputData& rawInputData,
bool& toggleAutoReverse, bool& newIsMovingForwardSlowly) const;
void processAutoReverse(
const PxVehicleWheels& focusVehicle, const PxVehicleDriveDynData& driveDynData, const PxVehicleWheelQueryResult& vehicleWheelQueryResults,
const PxVehicleDriveTankRawInputData& rawInputData,
bool& toggleAutoReverse, bool& newIsMovingForwardSlowly) const;
////////////////////////////////
//Record and replay deprecated at the moment.
//Setting functions as private to avoid them being used.
///////////////////////////////
bool getIsInRecordReplayMode() const { return (mRecord || mReplay); }
bool getIsRecording() const { return mRecord; }
bool getIsReplaying() const { return mReplay; }
void enableRecordReplayMode()
{
PX_ASSERT(!getIsInRecordReplayMode());
mRecord = true;
mReplay = false;
mNumRecordedSamples = 0;
}
void disableRecordReplayMode()
{
PX_ASSERT(getIsInRecordReplayMode());
mRecord = false;
mReplay = false;
mNumRecordedSamples = 0;
}
void restart();
////////////////////////////
};
#endif //VehicleController

View File

@ -0,0 +1,499 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "SceneVehicleSceneQuery.h"
#include "VehicleManager.h"
#include "VehicleWheelQueryResults.h"
#include "vehicle/PxVehicleUtilSetup.h"
#include "PxRigidActorExt.h"
#include "PxSceneLock.h"
#include "PxD6Joint.h"
VehicleManager::VehicleManager() : mSqWheelRaycastBatchQuery(NULL)
{
}
VehicleManager::~VehicleManager()
{
PxCloseVehicleSDK();
}
void VehicleManager::init(PxPhysics& physics, const PxMaterial** drivableSurfaceMaterials, const PxVehicleDrivableSurfaceType* drivableSurfaceTypes)
{
//Initialise the sdk.
PxInitVehicleSDK(physics, NULL);
//Set the basis vectors.
PxVec3 up(0, 1, 0);
PxVec3 forward(0, 0, 1);
PxVehicleSetBasisVectors(up, forward);
//Set the vehicle update mode to be immediate velocity changes.
PxVehicleSetUpdateMode(PxVehicleUpdateMode::eVELOCITY_CHANGE);
//Initialise vehicle ptrs to null.
mVehicle = NULL;
//Allocate simulation data so we can switch from 3-wheeled to 4-wheeled cars by switching simulation data.
mWheelsSimData4W = PxVehicleWheelsSimData::allocate(4);
//Scene query data for to allow raycasts for all suspensions of all vehicles.
mSqData = VehicleSceneQueryData::allocate(4);
//Data to store reports for each wheel.
mWheelQueryResults = VehicleWheelQueryResults::allocate(4);
//Set up the friction values arising from combinations of tire type and surface type.
mSurfaceTirePairs = PxVehicleDrivableSurfaceToTireFrictionPairs::allocate(MAX_NUM_TIRE_TYPES, MAX_NUM_SURFACE_TYPES);
mSurfaceTirePairs->setup(MAX_NUM_TIRE_TYPES, MAX_NUM_SURFACE_TYPES, drivableSurfaceMaterials, drivableSurfaceTypes);
for (PxU32 i = 0; i<MAX_NUM_SURFACE_TYPES; i++)
{
for (PxU32 j = 0; j<MAX_NUM_TIRE_TYPES; j++)
{
mSurfaceTirePairs->setTypePairFriction(i, j, 1.3f*TireFrictionMultipliers::getValue(i, j));
}
}
}
void VehicleManager::computeWheelWidthsAndRadii(PxConvexMesh** wheelConvexMeshes, PxF32* wheelWidths, PxF32* wheelRadii)
{
for (PxU32 i = 0; i<4; i++)
{
const PxU32 numWheelVerts = wheelConvexMeshes[i]->getNbVertices();
const PxVec3* wheelVerts = wheelConvexMeshes[i]->getVertices();
PxVec3 wheelMin(PX_MAX_F32, PX_MAX_F32, PX_MAX_F32);
PxVec3 wheelMax(-PX_MAX_F32, -PX_MAX_F32, -PX_MAX_F32);
for (PxU32 j = 0; j<numWheelVerts; j++)
{
wheelMin.x = PxMin(wheelMin.x, wheelVerts[j].x);
wheelMin.y = PxMin(wheelMin.y, wheelVerts[j].y);
wheelMin.z = PxMin(wheelMin.z, wheelVerts[j].z);
wheelMax.x = PxMax(wheelMax.x, wheelVerts[j].x);
wheelMax.y = PxMax(wheelMax.y, wheelVerts[j].y);
wheelMax.z = PxMax(wheelMax.z, wheelVerts[j].z);
}
wheelWidths[i] = wheelMax.x - wheelMin.x;
wheelRadii[i] = PxMax(wheelMax.y, wheelMax.z)*0.975f;
}
}
PxVec3 VehicleManager::computeChassisAABBDimensions(const PxConvexMesh* chassisConvexMesh)
{
const PxU32 numChassisVerts = chassisConvexMesh->getNbVertices();
const PxVec3* chassisVerts = chassisConvexMesh->getVertices();
PxVec3 chassisMin(PX_MAX_F32, PX_MAX_F32, PX_MAX_F32);
PxVec3 chassisMax(-PX_MAX_F32, -PX_MAX_F32, -PX_MAX_F32);
for (PxU32 i = 0; i<numChassisVerts; i++)
{
chassisMin.x = PxMin(chassisMin.x, chassisVerts[i].x);
chassisMin.y = PxMin(chassisMin.y, chassisVerts[i].y);
chassisMin.z = PxMin(chassisMin.z, chassisVerts[i].z);
chassisMax.x = PxMax(chassisMax.x, chassisVerts[i].x);
chassisMax.y = PxMax(chassisMax.y, chassisVerts[i].y);
chassisMax.z = PxMax(chassisMax.z, chassisVerts[i].z);
}
const PxVec3 chassisDims = chassisMax - chassisMin;
return chassisDims;
}
void VehicleManager::createVehicle4WSimulationData(const PxF32 chassisMass, PxConvexMesh* chassisConvexMesh, const PxF32 wheelMass, PxConvexMesh** wheelConvexMeshes,
const PxVec3* wheelCentreOffsets, PxVehicleWheelsSimData& wheelsData, PxVehicleDriveSimData4W& driveData, PxVehicleChassisData& chassisData)
{
//Extract the chassis AABB dimensions from the chassis convex mesh.
const PxVec3 chassisDims = computeChassisAABBDimensions(chassisConvexMesh);
//The origin is at the center of the chassis mesh.
//Set the center of mass to be below this point and a little towards the front.
const PxVec3 chassisCMOffset = PxVec3(0.0f, -chassisDims.y*0.5f + 0.65f, 0.25f);
//Now compute the chassis mass and moment of inertia.
//Use the moment of inertia of a cuboid as an approximate value for the chassis moi.
PxVec3 chassisMOI
((chassisDims.y*chassisDims.y + chassisDims.z*chassisDims.z)*chassisMass / 12.0f,
(chassisDims.x*chassisDims.x + chassisDims.z*chassisDims.z)*chassisMass / 12.0f,
(chassisDims.x*chassisDims.x + chassisDims.y*chassisDims.y)*chassisMass / 12.0f);
//A bit of tweaking here. The car will have more responsive turning if we reduce the
//y-component of the chassis moment of inertia.
chassisMOI.y *= 0.8f;
//Let's set up the chassis data structure now.
chassisData.mMass = chassisMass;
chassisData.mMOI = chassisMOI;
chassisData.mCMOffset = chassisCMOffset;
//Compute the sprung masses of each suspension spring using a helper function.
PxF32 suspSprungMasses[4];
PxVehicleComputeSprungMasses(4, wheelCentreOffsets, chassisCMOffset, chassisMass, 1, suspSprungMasses);
//Extract the wheel radius and width from the wheel convex meshes.
PxF32 wheelWidths[4];
PxF32 wheelRadii[4];
computeWheelWidthsAndRadii(wheelConvexMeshes, wheelWidths, wheelRadii);
//Now compute the wheel masses and inertias components around the axle's axis.
//http://en.wikipedia.org/wiki/List_of_moments_of_inertia
PxF32 wheelMOIs[4];
for (PxU32 i = 0; i<4; i++)
{
wheelMOIs[i] = 0.5f*wheelMass*wheelRadii[i] * wheelRadii[i];
}
//Let's set up the wheel data structures now with radius, mass, and moi.
PxVehicleWheelData wheels[4];
for (PxU32 i = 0; i<4; i++)
{
wheels[i].mRadius = wheelRadii[i];
wheels[i].mMass = wheelMass;
wheels[i].mMOI = wheelMOIs[i];
wheels[i].mWidth = wheelWidths[i];
}
//Disable the handbrake from the front wheels and enable for the rear wheels
wheels[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mMaxHandBrakeTorque = 0.0f;
wheels[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mMaxHandBrakeTorque = 0.0f;
wheels[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mMaxHandBrakeTorque = 4000.0f;
wheels[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mMaxHandBrakeTorque = 4000.0f;
//Enable steering for the front wheels and disable for the front wheels.
wheels[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mMaxSteer = PxPi*0.3333f;
wheels[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mMaxSteer = PxPi*0.3333f;
wheels[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mMaxSteer = 0.0f;
wheels[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mMaxSteer = 0.0f;
//Let's set up the tire data structures now.
//Put slicks on the front tires and wets on the rear tires.
PxVehicleTireData tires[4];
tires[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mType = TIRE_TYPE_SLICKS;
tires[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mType = TIRE_TYPE_SLICKS;
tires[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mType = TIRE_TYPE_WETS;
tires[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mType = TIRE_TYPE_WETS;
//Let's set up the suspension data structures now.
PxVehicleSuspensionData susps[4];
for (PxU32 i = 0; i<4; i++)
{
susps[i].mMaxCompression = 0.3f;
susps[i].mMaxDroop = 0.1f;
susps[i].mSpringStrength = 35000.0f;
susps[i].mSpringDamperRate = 4500.0f;
}
susps[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mSprungMass = suspSprungMasses[PxVehicleDrive4WWheelOrder::eFRONT_LEFT];
susps[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mSprungMass = suspSprungMasses[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT];
susps[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mSprungMass = suspSprungMasses[PxVehicleDrive4WWheelOrder::eREAR_LEFT];
susps[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mSprungMass = suspSprungMasses[PxVehicleDrive4WWheelOrder::eREAR_RIGHT];
//Set up the camber.
//Remember that the left and right wheels need opposite camber so that the car preserves symmetry about the forward direction.
//Set the camber to 0.0f when the spring is neither compressed or elongated.
const PxF32 camberAngleAtRest = 0.0;
susps[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mCamberAtRest = camberAngleAtRest;
susps[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mCamberAtRest = -camberAngleAtRest;
susps[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mCamberAtRest = camberAngleAtRest;
susps[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mCamberAtRest = -camberAngleAtRest;
//Set the wheels to camber inwards at maximum droop (the left and right wheels almost form a V shape)
const PxF32 camberAngleAtMaxDroop = 0.001f;
susps[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mCamberAtMaxDroop = camberAngleAtMaxDroop;
susps[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mCamberAtMaxDroop = -camberAngleAtMaxDroop;
susps[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mCamberAtMaxDroop = camberAngleAtMaxDroop;
susps[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mCamberAtMaxDroop = -camberAngleAtMaxDroop;
//Set the wheels to camber outwards at maximum compression (the left and right wheels almost form a A shape).
const PxF32 camberAngleAtMaxCompression = -0.001f;
susps[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mCamberAtMaxCompression = camberAngleAtMaxCompression;
susps[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mCamberAtMaxCompression = -camberAngleAtMaxCompression;
susps[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mCamberAtMaxCompression = camberAngleAtMaxCompression;
susps[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mCamberAtMaxCompression = -camberAngleAtMaxCompression;
//We need to set up geometry data for the suspension, wheels, and tires.
//We already know the wheel centers described as offsets from the actor center and the center of mass offset from actor center.
//From here we can approximate application points for the tire and suspension forces.
//Lets assume that the suspension travel directions are absolutely vertical.
//Also assume that we apply the tire and suspension forces 30cm below the center of mass.
PxVec3 suspTravelDirections[4] = { PxVec3(0, -1, 0), PxVec3(0, -1, 0), PxVec3(0, -1, 0), PxVec3(0, -1, 0) };
PxVec3 wheelCentreCMOffsets[4];
PxVec3 suspForceAppCMOffsets[4];
PxVec3 tireForceAppCMOffsets[4];
for (PxU32 i = 0; i<4; i++)
{
wheelCentreCMOffsets[i] = wheelCentreOffsets[i] - chassisCMOffset;
suspForceAppCMOffsets[i] = PxVec3(wheelCentreCMOffsets[i].x, -0.3f, wheelCentreCMOffsets[i].z);
tireForceAppCMOffsets[i] = PxVec3(wheelCentreCMOffsets[i].x, -0.3f, wheelCentreCMOffsets[i].z);
}
//Now add the wheel, tire and suspension data.
for (PxU32 i = 0; i<4; i++)
{
wheelsData.setWheelData(i, wheels[i]);
wheelsData.setTireData(i, tires[i]);
wheelsData.setSuspensionData(i, susps[i]);
wheelsData.setSuspTravelDirection(i, suspTravelDirections[i]);
wheelsData.setWheelCentreOffset(i, wheelCentreCMOffsets[i]);
wheelsData.setSuspForceAppPointOffset(i, suspForceAppCMOffsets[i]);
wheelsData.setTireForceAppPointOffset(i, tireForceAppCMOffsets[i]);
}
//Set the car to perform 3 sub-steps when it moves with a forwards speed of less than 5.0
//and with a single step when it moves at speed greater than or equal to 5.0.
wheelsData.setSubStepCount(5.0f, 5, 5);
//Now set up the differential, engine, gears, clutch, and ackermann steering.
//Diff
PxVehicleDifferential4WData diff;
diff.mType = PxVehicleDifferential4WData::eDIFF_TYPE_LS_4WD;
driveData.setDiffData(diff);
//Engine
PxVehicleEngineData engine;
engine.mPeakTorque = 1500.0f;
engine.mMaxOmega = 1000.0f;//approx 6000 rpm
engine.mMOI = 2.f;
driveData.setEngineData(engine);
//Gears
PxVehicleGearsData gears;
gears.mSwitchTime = 0.5f;
driveData.setGearsData(gears);
//Clutch
PxVehicleClutchData clutch;
clutch.mStrength = 10.0f;
driveData.setClutchData(clutch);
//Ackermann steer accuracy
PxVehicleAckermannGeometryData ackermann;
ackermann.mAccuracy = 1.0f;
ackermann.mAxleSeparation = wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].z - wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_LEFT].z;
ackermann.mFrontWidth = wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].x - wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].x;
ackermann.mRearWidth = wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].x - wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_LEFT].x;
driveData.setAckermannGeometryData(ackermann);
}
void setupActor
(PxRigidDynamic* vehActor,
const PxFilterData& vehQryFilterData,
const PxGeometry** wheelGeometries, const PxTransform* wheelLocalPoses, const PxU32 numWheelGeometries, const PxMaterial* wheelMaterial, const PxFilterData& wheelCollFilterData,
const PxGeometry** chassisGeometries, const PxTransform* chassisLocalPoses, const PxU32 numChassisGeometries, const PxMaterial* chassisMaterial, const PxFilterData& chassisCollFilterData,
const PxVehicleChassisData& chassisData,
PxPhysics* physics)
{
//Add all the wheel shapes to the actor.
for (PxU32 i = 0; i<numWheelGeometries; i++)
{
PxShape* wheelShape = PxRigidActorExt::createExclusiveShape(*vehActor, *wheelGeometries[i], *wheelMaterial);
wheelShape->setQueryFilterData(vehQryFilterData);
wheelShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);
//wheelShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
wheelShape->setSimulationFilterData(wheelCollFilterData);
wheelShape->setLocalPose(wheelLocalPoses[i]);
}
//Add the chassis shapes to the actor.
for (PxU32 i = 0; i<numChassisGeometries; i++)
{
PxShape* chassisShape = PxRigidActorExt::createExclusiveShape(*vehActor, *chassisGeometries[i], *chassisMaterial);
chassisShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);
chassisShape->setQueryFilterData(vehQryFilterData);
chassisShape->setSimulationFilterData(chassisCollFilterData);
chassisShape->setLocalPose(chassisLocalPoses[i]);
}
vehActor->setMass(chassisData.mMass);
vehActor->setMassSpaceInertiaTensor(chassisData.mMOI);
vehActor->setCMassLocalPose(PxTransform(chassisData.mCMOffset, PxQuat(PxIdentity)));
}
PxRigidDynamic* createVehicleActor4W
(const PxVehicleChassisData& chassisData,
PxConvexMesh** wheelConvexMeshes, PxConvexMesh* chassisConvexMesh,
PxScene& scene, PxPhysics& physics, const PxMaterial& material)
{
//We need a rigid body actor for the vehicle.
//Don't forget to add the actor the scene after setting up the associated vehicle.
PxRigidDynamic* vehActor = physics.createRigidDynamic(PxTransform(PxIdentity));
//We need to add wheel collision shapes, their local poses, a material for the wheels, and a simulation filter for the wheels.
PxConvexMeshGeometry frontLeftWheelGeom(wheelConvexMeshes[0]);
PxConvexMeshGeometry frontRightWheelGeom(wheelConvexMeshes[1]);
PxConvexMeshGeometry rearLeftWheelGeom(wheelConvexMeshes[2]);
PxConvexMeshGeometry rearRightWheelGeom(wheelConvexMeshes[3]);
const PxGeometry* wheelGeometries[4] = { &frontLeftWheelGeom, &frontRightWheelGeom, &rearLeftWheelGeom, &rearRightWheelGeom };
const PxTransform wheelLocalPoses[4] = { PxTransform(PxIdentity), PxTransform(PxIdentity), PxTransform(PxIdentity), PxTransform(PxIdentity) };
const PxMaterial& wheelMaterial = material;
PxFilterData wheelCollFilterData;
wheelCollFilterData.word0 = COLLISION_FLAG_WHEEL;
wheelCollFilterData.word1 = COLLISION_FLAG_WHEEL_AGAINST;
wheelCollFilterData.word2 = PxPairFlag::eMODIFY_CONTACTS;
//We need to add chassis collision shapes, their local poses, a material for the chassis, and a simulation filter for the chassis.
PxConvexMeshGeometry chassisConvexGeom(chassisConvexMesh);
const PxGeometry* chassisGeoms[1] = { &chassisConvexGeom };
const PxTransform chassisLocalPoses[1] = { PxTransform(PxIdentity) };
const PxMaterial& chassisMaterial = material;
PxFilterData chassisCollFilterData;
chassisCollFilterData.word0 = COLLISION_FLAG_CHASSIS;
chassisCollFilterData.word1 = COLLISION_FLAG_CHASSIS_AGAINST;
//Create a query filter data for the car to ensure that cars
//do not attempt to drive on themselves.
PxFilterData vehQryFilterData;
VehicleSetupVehicleShapeQueryFilterData(&vehQryFilterData);
//Set up the physx rigid body actor with shapes, local poses, and filters.
setupActor
(vehActor,
vehQryFilterData,
wheelGeometries, wheelLocalPoses, 4, &wheelMaterial, wheelCollFilterData,
chassisGeoms, chassisLocalPoses, 1, &chassisMaterial, chassisCollFilterData,
chassisData,
&physics);
return vehActor;
}
void VehicleManager::resetNWCar(const PxTransform& startTransform, PxVehicleWheels* vehWheels)
{
PxVehicleDrive4W* vehDrive4W = (PxVehicleDrive4W*)vehWheels;
//Set the car back to its rest state.
vehDrive4W->setToRestState();
//Set the car to first gear.
vehDrive4W->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
//Set the car's transform to be the start transform.
PxRigidDynamic* actor = vehWheels->getRigidDynamicActor();
PxSceneWriteLock scopedLock(*actor->getScene());
actor->setGlobalPose(startTransform);
}
void VehicleManager::suspensionRaycasts(PxScene* scene)
{
//Create a scene query if we haven't already done so.
if (NULL == mSqWheelRaycastBatchQuery)
{
mSqWheelRaycastBatchQuery = mSqData->setUpBatchedSceneQuery(scene);
}
//Raycasts.
PxSceneReadLock scopedLock(*scene);
PxVehicleWheels* vehicles[1] = { mVehicle };
PxVehicleSuspensionRaycasts(mSqWheelRaycastBatchQuery, 1, vehicles, mSqData->getRaycastQueryResultBufferSize(), mSqData->getRaycastQueryResultBuffer());
}
void VehicleManager::suspensionSweeps(PxScene* scene)
{
//Create a scene query if we haven't already done so.
if (NULL == mSqWheelRaycastBatchQuery)
{
mSqWheelRaycastBatchQuery = mSqData->setUpBatchedSceneQuerySweep(scene);
}
//Raycasts.
PxSceneReadLock scopedLock(*scene);
PxVehicleWheels* vehicles[1] = { mVehicle };
PxVehicleSuspensionSweeps(mSqWheelRaycastBatchQuery, 1, vehicles, mSqData->getSweepQueryResultBufferSize(), mSqData->getSweepQueryResultBuffer(), 1);
}
void VehicleManager::update(const PxF32 timestep, const PxVec3& gravity)
{
PxVehicleWheels* vehicles[1] = { mVehicle };
PxVehicleUpdates(timestep, gravity, *mSurfaceTirePairs, 1, vehicles, &mVehicleWheelQueryResults);
}
void VehicleManager::create4WVehicle(PxScene& scene, PxPhysics& physics, PxCooking& cooking, const PxMaterial& material,
const PxF32 chassisMass, const PxVec3* wheelCentreOffsets4, PxConvexMesh* chassisConvexMesh, PxConvexMesh** wheelConvexMeshes4,
const PxTransform& startTransform, const bool useAutoGearFlag)
{
PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate(4);
PxVehicleDriveSimData4W driveSimData;
PxVehicleChassisData chassisData;
createVehicle4WSimulationData
(chassisMass, chassisConvexMesh,
20.0f, wheelConvexMeshes4, wheelCentreOffsets4,
*wheelsSimData, driveSimData, chassisData);
//Instantiate and finalize the vehicle using physx.
PxRigidDynamic* vehActor = createVehicleActor4W(chassisData, wheelConvexMeshes4, chassisConvexMesh, scene, physics, material);
//Create a car.
PxVehicleDrive4W* car = PxVehicleDrive4W::allocate(4);
car->setup(&physics, vehActor, *wheelsSimData, driveSimData, 0);
//Free the sim data because we don't need that any more.
wheelsSimData->free();
//Don't forget to add the actor to the scene.
{
PxSceneWriteLock scopedLock(scene);
scene.addActor(*vehActor);
}
//Set up the mapping between wheel and actor shape.
car->mWheelsSimData.setWheelShapeMapping(0, 0);
car->mWheelsSimData.setWheelShapeMapping(1, 1);
car->mWheelsSimData.setWheelShapeMapping(2, 2);
car->mWheelsSimData.setWheelShapeMapping(3, 3);
//Set up the scene query filter data for each suspension line.
PxFilterData vehQryFilterData;
VehicleSetupVehicleShapeQueryFilterData(&vehQryFilterData);
car->mWheelsSimData.setSceneQueryFilterData(0, vehQryFilterData);
car->mWheelsSimData.setSceneQueryFilterData(1, vehQryFilterData);
car->mWheelsSimData.setSceneQueryFilterData(2, vehQryFilterData);
car->mWheelsSimData.setSceneQueryFilterData(3, vehQryFilterData);
//Set the autogear mode of the instantiate car.
car->mDriveDynData.setUseAutoGears(useAutoGearFlag);
car->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
//Increment the number of vehicles
mVehicle = car;
mVehicleWheelQueryResults.nbWheelQueryResults = 4;
mVehicleWheelQueryResults.wheelQueryResults = mWheelQueryResults->addVehicle(4);
PxQuat rotation(3.1415 / 2.f, PxVec3(0.f, 0.f, 1.f));
PxD6Joint* joint = PxD6JointCreate(physics, vehActor, PxTransform(rotation), NULL, PxTransform(rotation));
joint->setMotion(PxD6Axis::eX, PxD6Motion::eFREE);
joint->setMotion(PxD6Axis::eY, PxD6Motion::eFREE);
joint->setMotion(PxD6Axis::eZ, PxD6Motion::eFREE);
joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eLIMITED);
joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eLIMITED);
PxJointLimitCone limitCone(3.1415/4.f, 3.1415 / 4.f);
joint->setSwingLimit(limitCone);
}

View File

@ -0,0 +1,161 @@
//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#ifndef VEHICLE_H
#define VEHICLE_H
#include "vehicle/PxVehicleWheels.h"
#include "vehicle/PxVehicleDrive4W.h"
#include "vehicle/PxVehicleTireFriction.h"
#include "vehicle/PxVehicleUpdate.h"
#include "RawLoader.h"
#include "PxPhysics.h"
#include "PxCooking.h"
using namespace physx;
namespace physx
{
class PxBatchQuery;
namespace fracture
{
namespace base
{
class Compound;
}
}
}
class VehicleWheelQueryResults;
class VehicleSceneQueryData;
//Tire types.
enum
{
TIRE_TYPE_WETS = 0,
TIRE_TYPE_SLICKS,
TIRE_TYPE_ICE,
TIRE_TYPE_MUD,
MAX_NUM_TIRE_TYPES
};
//Drivable surface types.
enum
{
SURFACE_TYPE_MUD = 0,
SURFACE_TYPE_TARMAC,
SURFACE_TYPE_SNOW,
SURFACE_TYPE_GRASS,
MAX_NUM_SURFACE_TYPES
};
//Collision types and flags describing collision interactions of each collision type.
enum
{
COLLISION_FLAG_GROUND = 1 << 0,
COLLISION_FLAG_WHEEL = 1 << 1,
COLLISION_FLAG_CHASSIS = 1 << 2,
COLLISION_FLAG_OBSTACLE = 1 << 3,
COLLISION_FLAG_DRIVABLE_OBSTACLE = 1 << 4,
COLLISION_FLAG_GROUND_AGAINST = COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,
COLLISION_FLAG_WHEEL_AGAINST = COLLISION_FLAG_WHEEL | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE,
COLLISION_FLAG_CHASSIS_AGAINST = COLLISION_FLAG_GROUND | COLLISION_FLAG_WHEEL | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,
COLLISION_FLAG_OBSTACLE_AGAINST = COLLISION_FLAG_GROUND | COLLISION_FLAG_WHEEL | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,
COLLISION_FLAG_DRIVABLE_OBSTACLE_AGAINST = COLLISION_FLAG_GROUND | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,
};
// ---------------------------------------------------------------------
struct TireFrictionMultipliers
{
static float getValue(PxU32 surfaceType, PxU32 tireType)
{
//Tire model friction for each combination of drivable surface type and tire type.
static PxF32 tireFrictionMultipliers[MAX_NUM_SURFACE_TYPES][MAX_NUM_TIRE_TYPES] =
{
//WETS SLICKS ICE MUD
{ 0.95f, 0.95f, 0.95f, 0.95f }, //MUD
{ 1.10f, 1.15f, 1.10f, 1.10f }, //TARMAC
{ 0.70f, 0.70f, 0.70f, 0.70f }, //ICE
{ 0.80f, 0.80f, 0.80f, 0.80f } //GRASS
};
return tireFrictionMultipliers[surfaceType][tireType];
}
};
class VehicleManager
{
public:
VehicleManager();
virtual ~VehicleManager();
void init(PxPhysics& physics, const PxMaterial** drivableSurfaceMaterials, const PxVehicleDrivableSurfaceType* drivableSurfaceTypes);
void create4WVehicle(PxScene& scene, PxPhysics& physics, PxCooking& cooking, const PxMaterial& material,
const PxF32 chassisMass, const PxVec3* wheelCentreOffsets4, PxConvexMesh* chassisConvexMesh, PxConvexMesh** wheelConvexMeshes4,
const PxTransform& startTransform, const bool useAutoGearFlag);
void createVehicle4WSimulationData(const PxF32 chassisMass, PxConvexMesh* chassisConvexMesh, const PxF32 wheelMass, PxConvexMesh** wheelConvexMeshes,
const PxVec3* wheelCentreOffsets, PxVehicleWheelsSimData& wheelsData, PxVehicleDriveSimData4W& driveData, PxVehicleChassisData& chassisData);
PxVec3 computeChassisAABBDimensions(const PxConvexMesh* chassisConvexMesh);
void computeWheelWidthsAndRadii(PxConvexMesh** wheelConvexMeshes, PxF32* wheelWidths, PxF32* wheelRadii);
void resetNWCar(const PxTransform& startTransform, PxVehicleWheels* vehWheels);
void suspensionRaycasts(PxScene* scene);
void suspensionSweeps(PxScene* scene);
void update(const PxF32 timestep, const PxVec3& gravity);
PxVehicleWheels* getVehicle() { return mVehicle; }
PxVehicleWheelQueryResult& getWheelQueryResult() { return mVehicleWheelQueryResults; };
void clearBatchQuery() { mSqWheelRaycastBatchQuery = NULL; }
private:
PxVehicleWheels* mVehicle;
PxVehicleWheelQueryResult mVehicleWheelQueryResults;
//sdk raycasts (for the suspension lines).
VehicleSceneQueryData* mSqData;
PxBatchQuery* mSqWheelRaycastBatchQuery;
//Reports for each wheel.
VehicleWheelQueryResults* mWheelQueryResults;
//Cached simulation data of focus vehicle in 4W mode.
PxVehicleWheelsSimData* mWheelsSimData4W;
PxVehicleDriveSimData4W mDriveSimData4W;
//Friction from combinations of tire and surface types.
PxVehicleDrivableSurfaceToTireFrictionPairs* mSurfaceTirePairs;
public:
fracture::base::Compound* mCompoundShape;
};
#endif // SCENE_BOXES_H

View File

@ -0,0 +1,72 @@
//
// 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-2018 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 "VehicleWheelQueryResults.h"
#include "vehicle/PxVehicleSDK.h"
#include "PsFoundation.h"
#include "PsUtilities.h"
//#define CHECK_MSG(exp, msg) (!!(exp) || (physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, msg), 0) )
VehicleWheelQueryResults* VehicleWheelQueryResults::allocate(const PxU32 maxNumWheels)
{
const PxU32 size = sizeof(VehicleWheelQueryResults) + sizeof(PxWheelQueryResult)*maxNumWheels;
VehicleWheelQueryResults* resData = (VehicleWheelQueryResults*)PX_ALLOC(size, "VehicleWheelQueryResults");
resData->init();
PxU8* ptr = (PxU8*)resData;
ptr += sizeof(VehicleWheelQueryResults);
resData->mWheelQueryResults = (PxWheelQueryResult*)ptr;
ptr += sizeof(PxWheelQueryResult)*maxNumWheels;
resData->mMaxNumWheels = maxNumWheels;
for (PxU32 i = 0; i<maxNumWheels; i++)
{
new(&resData->mWheelQueryResults[i]) PxWheelQueryResult();
}
return resData;
}
void VehicleWheelQueryResults::free()
{
PX_FREE(this);
}
PxWheelQueryResult* VehicleWheelQueryResults::addVehicle(const PxU32 numWheels)
{
PX_ASSERT((mNumWheels + numWheels) <= mMaxNumWheels);
PxWheelQueryResult* r = &mWheelQueryResults[mNumWheels];
mNumWheels += numWheels;
return r;
}

View File

@ -0,0 +1,82 @@
//
// 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-2018 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 VEHICLE_WHEELQUERYRESULTS_H
#define VEHICLE_WHEELQUERYRESULTS_H
#include "vehicle/PxVehicleSDK.h"
#include "vehicle/PxVehicleUpdate.h"
using namespace physx;
//Data structure to store reports for each wheel.
class VehicleWheelQueryResults
{
public:
//Allocate a buffer of wheel query results for up to maxNumWheels.
static VehicleWheelQueryResults* allocate(const PxU32 maxNumWheels);
//Free allocated buffer.
void free();
PxWheelQueryResult* addVehicle(const PxU32 numWheels);
private:
//One result for each wheel.
PxWheelQueryResult* mWheelQueryResults;
//Maximum number of wheels.
PxU32 mMaxNumWheels;
//Number of wheels
PxU32 mNumWheels;
VehicleWheelQueryResults()
: mWheelQueryResults(NULL), mMaxNumWheels(0), mNumWheels(0)
{
init();
}
~VehicleWheelQueryResults()
{
}
void init()
{
mWheelQueryResults = NULL;
mMaxNumWheels = 0;
mNumWheels = 0;
}
};
#endif //VEHICLE_WHEELQUERYRESULTS_H