Init
This commit is contained in:
491
kaplademo/source/kaplaDemo/AABox.cpp
Normal file
491
kaplademo/source/kaplaDemo/AABox.cpp
Normal 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);
|
||||
}
|
||||
98
kaplademo/source/kaplaDemo/AABox.h
Normal file
98
kaplademo/source/kaplaDemo/AABox.h
Normal 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);
|
||||
};
|
||||
822
kaplademo/source/kaplaDemo/Crab.cpp
Normal file
822
kaplademo/source/kaplaDemo/Crab.cpp
Normal 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]);
|
||||
}
|
||||
191
kaplademo/source/kaplaDemo/Crab.h
Normal file
191
kaplademo/source/kaplaDemo/Crab.h
Normal 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
|
||||
159
kaplademo/source/kaplaDemo/CrabManager.cpp
Normal file
159
kaplademo/source/kaplaDemo/CrabManager.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
126
kaplademo/source/kaplaDemo/CrabManager.h
Normal file
126
kaplademo/source/kaplaDemo/CrabManager.h
Normal file
@ -0,0 +1,126 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-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
|
||||
48
kaplademo/source/kaplaDemo/Fracture/Actor.cpp
Normal file
48
kaplademo/source/kaplaDemo/Fracture/Actor.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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()
|
||||
{
|
||||
|
||||
}
|
||||
52
kaplademo/source/kaplaDemo/Fracture/Actor.h
Normal file
52
kaplademo/source/kaplaDemo/Fracture/Actor.h
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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
|
||||
97
kaplademo/source/kaplaDemo/Fracture/Compound.cpp
Normal file
97
kaplademo/source/kaplaDemo/Fracture/Compound.cpp
Normal 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);
|
||||
}
|
||||
86
kaplademo/source/kaplaDemo/Fracture/Compound.h
Normal file
86
kaplademo/source/kaplaDemo/Fracture/Compound.h
Normal 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
|
||||
65
kaplademo/source/kaplaDemo/Fracture/CompoundCreator.cpp
Normal file
65
kaplademo/source/kaplaDemo/Fracture/CompoundCreator.cpp
Normal 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
|
||||
}
|
||||
48
kaplademo/source/kaplaDemo/Fracture/CompoundCreator.h
Normal file
48
kaplademo/source/kaplaDemo/Fracture/CompoundCreator.h
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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
|
||||
102
kaplademo/source/kaplaDemo/Fracture/CompoundGeometry.cpp
Normal file
102
kaplademo/source/kaplaDemo/Fracture/CompoundGeometry.cpp
Normal 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
|
||||
}
|
||||
45
kaplademo/source/kaplaDemo/Fracture/CompoundGeometry.h
Normal file
45
kaplademo/source/kaplaDemo/Fracture/CompoundGeometry.h
Normal 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
|
||||
276
kaplademo/source/kaplaDemo/Fracture/Convex.cpp
Normal file
276
kaplademo/source/kaplaDemo/Fracture/Convex.cpp
Normal 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);
|
||||
}
|
||||
65
kaplademo/source/kaplaDemo/Fracture/Convex.h
Normal file
65
kaplademo/source/kaplaDemo/Fracture/Convex.h
Normal 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
|
||||
403
kaplademo/source/kaplaDemo/Fracture/ConvexRenderer.cpp
Normal file
403
kaplademo/source/kaplaDemo/Fracture/ConvexRenderer.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
104
kaplademo/source/kaplaDemo/Fracture/ConvexRenderer.h
Normal file
104
kaplademo/source/kaplaDemo/Fracture/ConvexRenderer.h
Normal 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
|
||||
166
kaplademo/source/kaplaDemo/Fracture/Core/ActorBase.cpp
Normal file
166
kaplademo/source/kaplaDemo/Fracture/Core/ActorBase.cpp
Normal 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
|
||||
81
kaplademo/source/kaplaDemo/Fracture/Core/ActorBase.h
Normal file
81
kaplademo/source/kaplaDemo/Fracture/Core/ActorBase.h
Normal 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
|
||||
563
kaplademo/source/kaplaDemo/Fracture/Core/CompoundBase.cpp
Normal file
563
kaplademo/source/kaplaDemo/Fracture/Core/CompoundBase.cpp
Normal 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
|
||||
162
kaplademo/source/kaplaDemo/Fracture/Core/CompoundBase.h
Normal file
162
kaplademo/source/kaplaDemo/Fracture/Core/CompoundBase.h
Normal file
@ -0,0 +1,162 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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
|
||||
871
kaplademo/source/kaplaDemo/Fracture/Core/CompoundCreatorBase.cpp
Normal file
871
kaplademo/source/kaplaDemo/Fracture/Core/CompoundCreatorBase.cpp
Normal 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
|
||||
130
kaplademo/source/kaplaDemo/Fracture/Core/CompoundCreatorBase.h
Normal file
130
kaplademo/source/kaplaDemo/Fracture/Core/CompoundCreatorBase.h
Normal 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
|
||||
@ -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
|
||||
@ -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
|
||||
1343
kaplademo/source/kaplaDemo/Fracture/Core/ConvexBase.cpp
Normal file
1343
kaplademo/source/kaplaDemo/Fracture/Core/ConvexBase.cpp
Normal file
File diff suppressed because it is too large
Load Diff
239
kaplademo/source/kaplaDemo/Fracture/Core/ConvexBase.h
Normal file
239
kaplademo/source/kaplaDemo/Fracture/Core/ConvexBase.h
Normal 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
|
||||
239
kaplademo/source/kaplaDemo/Fracture/Core/MeshBase.cpp
Normal file
239
kaplademo/source/kaplaDemo/Fracture/Core/MeshBase.cpp
Normal 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 ¢er, 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
|
||||
94
kaplademo/source/kaplaDemo/Fracture/Core/MeshBase.h
Normal file
94
kaplademo/source/kaplaDemo/Fracture/Core/MeshBase.h
Normal 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 ¢er, 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
|
||||
@ -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
|
||||
@ -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
|
||||
364
kaplademo/source/kaplaDemo/Fracture/Core/SimSceneBase.cpp
Normal file
364
kaplademo/source/kaplaDemo/Fracture/Core/SimSceneBase.cpp
Normal 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
|
||||
275
kaplademo/source/kaplaDemo/Fracture/Core/SimSceneBase.h
Normal file
275
kaplademo/source/kaplaDemo/Fracture/Core/SimSceneBase.h
Normal 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
|
||||
192
kaplademo/source/kaplaDemo/Fracture/Mesh.cpp
Normal file
192
kaplademo/source/kaplaDemo/Fracture/Mesh.cpp
Normal 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;
|
||||
}
|
||||
59
kaplademo/source/kaplaDemo/Fracture/Mesh.h
Normal file
59
kaplademo/source/kaplaDemo/Fracture/Mesh.h
Normal 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
|
||||
31
kaplademo/source/kaplaDemo/Fracture/PolygonTriangulator.cpp
Normal file
31
kaplademo/source/kaplaDemo/Fracture/PolygonTriangulator.cpp
Normal 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
|
||||
49
kaplademo/source/kaplaDemo/Fracture/PolygonTriangulator.h
Normal file
49
kaplademo/source/kaplaDemo/Fracture/PolygonTriangulator.h
Normal file
@ -0,0 +1,49 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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
|
||||
35
kaplademo/source/kaplaDemo/Fracture/RTdef.h
Normal file
35
kaplademo/source/kaplaDemo/Fracture/RTdef.h
Normal 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
|
||||
736
kaplademo/source/kaplaDemo/Fracture/SimScene.cpp
Normal file
736
kaplademo/source/kaplaDemo/Fracture/SimScene.cpp
Normal 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
|
||||
}
|
||||
107
kaplademo/source/kaplaDemo/Fracture/SimScene.h
Normal file
107
kaplademo/source/kaplaDemo/Fracture/SimScene.h
Normal file
@ -0,0 +1,107 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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
|
||||
392
kaplademo/source/kaplaDemo/MathUtils.cpp
Normal file
392
kaplademo/source/kaplaDemo/MathUtils.cpp
Normal 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;
|
||||
}
|
||||
129
kaplademo/source/kaplaDemo/MathUtils.h
Normal file
129
kaplademo/source/kaplaDemo/MathUtils.h
Normal 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
|
||||
310
kaplademo/source/kaplaDemo/MediaPath.cpp
Normal file
310
kaplademo/source/kaplaDemo/MediaPath.cpp
Normal 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
|
||||
43
kaplademo/source/kaplaDemo/MediaPath.h
Normal file
43
kaplademo/source/kaplaDemo/MediaPath.h
Normal file
@ -0,0 +1,43 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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
|
||||
40
kaplademo/source/kaplaDemo/PhysXMacros.h
Normal file
40
kaplademo/source/kaplaDemo/PhysXMacros.h
Normal 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
|
||||
2258
kaplademo/source/kaplaDemo/SampleViewer.cpp
Normal file
2258
kaplademo/source/kaplaDemo/SampleViewer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
48
kaplademo/source/kaplaDemo/SampleViewer.h
Normal file
48
kaplademo/source/kaplaDemo/SampleViewer.h
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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
|
||||
238
kaplademo/source/kaplaDemo/SampleViewerGamepad.cpp
Normal file
238
kaplademo/source/kaplaDemo/SampleViewerGamepad.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
96
kaplademo/source/kaplaDemo/SampleViewerGamepad.h
Normal file
96
kaplademo/source/kaplaDemo/SampleViewerGamepad.h
Normal 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
|
||||
133
kaplademo/source/kaplaDemo/SampleViewerScene.cpp
Normal file
133
kaplademo/source/kaplaDemo/SampleViewerScene.cpp
Normal 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();
|
||||
}
|
||||
152
kaplademo/source/kaplaDemo/SampleViewerScene.h
Normal file
152
kaplademo/source/kaplaDemo/SampleViewerScene.h
Normal file
@ -0,0 +1,152 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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
|
||||
189
kaplademo/source/kaplaDemo/SceneCrab.cpp
Normal file
189
kaplademo/source/kaplaDemo/SceneCrab.cpp
Normal 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);
|
||||
}
|
||||
80
kaplademo/source/kaplaDemo/SceneCrab.h
Normal file
80
kaplademo/source/kaplaDemo/SceneCrab.h
Normal 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
|
||||
46
kaplademo/source/kaplaDemo/SceneCrabInputEventIds.h
Normal file
46
kaplademo/source/kaplaDemo/SceneCrabInputEventIds.h
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-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
|
||||
956
kaplademo/source/kaplaDemo/SceneKapla.cpp
Normal file
956
kaplademo/source/kaplaDemo/SceneKapla.cpp
Normal 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());*/
|
||||
}
|
||||
}
|
||||
149
kaplademo/source/kaplaDemo/SceneKapla.h
Normal file
149
kaplademo/source/kaplaDemo/SceneKapla.h
Normal 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
|
||||
78
kaplademo/source/kaplaDemo/SceneKaplaArena.cpp
Normal file
78
kaplademo/source/kaplaDemo/SceneKaplaArena.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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);
|
||||
}
|
||||
51
kaplademo/source/kaplaDemo/SceneKaplaArena.h
Normal file
51
kaplademo/source/kaplaDemo/SceneKaplaArena.h
Normal file
@ -0,0 +1,51 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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
|
||||
718
kaplademo/source/kaplaDemo/SceneKaplaTower.cpp
Normal file
718
kaplademo/source/kaplaDemo/SceneKaplaTower.cpp
Normal 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);
|
||||
}
|
||||
68
kaplademo/source/kaplaDemo/SceneKaplaTower.h
Normal file
68
kaplademo/source/kaplaDemo/SceneKaplaTower.h
Normal file
@ -0,0 +1,68 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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
|
||||
133
kaplademo/source/kaplaDemo/SceneRagdollWashingMachine.cpp
Normal file
133
kaplademo/source/kaplaDemo/SceneRagdollWashingMachine.cpp
Normal 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);
|
||||
}
|
||||
52
kaplademo/source/kaplaDemo/SceneRagdollWashingMachine.h
Normal file
52
kaplademo/source/kaplaDemo/SceneRagdollWashingMachine.h
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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
|
||||
1217
kaplademo/source/kaplaDemo/SceneVehicle.cpp
Normal file
1217
kaplademo/source/kaplaDemo/SceneVehicle.cpp
Normal file
File diff suppressed because it is too large
Load Diff
125
kaplademo/source/kaplaDemo/SceneVehicle.h
Normal file
125
kaplademo/source/kaplaDemo/SceneVehicle.h
Normal 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
|
||||
214
kaplademo/source/kaplaDemo/SceneVehicleCooking.cpp
Normal file
214
kaplademo/source/kaplaDemo/SceneVehicleCooking.cpp
Normal 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;
|
||||
}
|
||||
50
kaplademo/source/kaplaDemo/SceneVehicleCooking.h
Normal file
50
kaplademo/source/kaplaDemo/SceneVehicleCooking.h
Normal file
@ -0,0 +1,50 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-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
|
||||
100
kaplademo/source/kaplaDemo/SceneVehicleSceneQuery.cpp
Normal file
100
kaplademo/source/kaplaDemo/SceneVehicleSceneQuery.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-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);
|
||||
}
|
||||
|
||||
|
||||
147
kaplademo/source/kaplaDemo/SceneVehicleSceneQuery.h
Normal file
147
kaplademo/source/kaplaDemo/SceneVehicleSceneQuery.h
Normal 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
|
||||
396
kaplademo/source/kaplaDemo/TerrainMesh.cpp
Normal file
396
kaplademo/source/kaplaDemo/TerrainMesh.cpp
Normal 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;
|
||||
}
|
||||
66
kaplademo/source/kaplaDemo/TerrainMesh.h
Normal file
66
kaplademo/source/kaplaDemo/TerrainMesh.h
Normal file
@ -0,0 +1,66 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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);
|
||||
};
|
||||
|
||||
92
kaplademo/source/kaplaDemo/TerrainRandomSamplePrecompute.cpp
Normal file
92
kaplademo/source/kaplaDemo/TerrainRandomSamplePrecompute.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-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;
|
||||
}
|
||||
64
kaplademo/source/kaplaDemo/TerrainRandomSamplePrecompute.h
Normal file
64
kaplademo/source/kaplaDemo/TerrainRandomSamplePrecompute.h
Normal file
@ -0,0 +1,64 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-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
|
||||
63
kaplademo/source/kaplaDemo/Timing.cpp
Normal file
63
kaplademo/source/kaplaDemo/Timing.cpp
Normal 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(¤tTime);
|
||||
unsigned long long elapsedTime = currentTime.QuadPart - previousTime.QuadPart;
|
||||
previousTime = currentTime;
|
||||
return (float)(elapsedTime)/(freq.QuadPart);
|
||||
}
|
||||
|
||||
35
kaplademo/source/kaplaDemo/Timing.h
Normal file
35
kaplademo/source/kaplaDemo/Timing.h
Normal 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
|
||||
209
kaplademo/source/kaplaDemo/Vec/Bounds3.h
Normal file
209
kaplademo/source/kaplaDemo/Vec/Bounds3.h
Normal 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
|
||||
100
kaplademo/source/kaplaDemo/Vec/Plane.h
Normal file
100
kaplademo/source/kaplaDemo/Vec/Plane.h
Normal file
@ -0,0 +1,100 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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
|
||||
|
||||
328
kaplademo/source/kaplaDemo/Vec/Quat.h
Normal file
328
kaplademo/source/kaplaDemo/Vec/Quat.h
Normal 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
|
||||
121
kaplademo/source/kaplaDemo/Vec/Transform.h
Normal file
121
kaplademo/source/kaplaDemo/Vec/Transform.h
Normal file
@ -0,0 +1,121 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 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
|
||||
517
kaplademo/source/kaplaDemo/Vec/Vec3.h
Normal file
517
kaplademo/source/kaplaDemo/Vec/Vec3.h
Normal 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
|
||||
165
kaplademo/source/kaplaDemo/VehicleCameraController.cpp
Normal file
165
kaplademo/source/kaplaDemo/VehicleCameraController.cpp
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
93
kaplademo/source/kaplaDemo/VehicleCameraController.h
Normal file
93
kaplademo/source/kaplaDemo/VehicleCameraController.h
Normal file
@ -0,0 +1,93 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-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
|
||||
65
kaplademo/source/kaplaDemo/VehicleControlInputs.cpp
Normal file
65
kaplademo/source/kaplaDemo/VehicleControlInputs.cpp
Normal 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()
|
||||
{
|
||||
}
|
||||
|
||||
145
kaplademo/source/kaplaDemo/VehicleControlInputs.h
Normal file
145
kaplademo/source/kaplaDemo/VehicleControlInputs.h
Normal 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
|
||||
808
kaplademo/source/kaplaDemo/VehicleController.cpp
Normal file
808
kaplademo/source/kaplaDemo/VehicleController.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
226
kaplademo/source/kaplaDemo/VehicleController.h
Normal file
226
kaplademo/source/kaplaDemo/VehicleController.h
Normal 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
|
||||
499
kaplademo/source/kaplaDemo/VehicleManager.cpp
Normal file
499
kaplademo/source/kaplaDemo/VehicleManager.cpp
Normal 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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
161
kaplademo/source/kaplaDemo/VehicleManager.h
Normal file
161
kaplademo/source/kaplaDemo/VehicleManager.h
Normal 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
|
||||
72
kaplademo/source/kaplaDemo/VehicleWheelQueryResults.cpp
Normal file
72
kaplademo/source/kaplaDemo/VehicleWheelQueryResults.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
82
kaplademo/source/kaplaDemo/VehicleWheelQueryResults.h
Normal file
82
kaplademo/source/kaplaDemo/VehicleWheelQueryResults.h
Normal 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
|
||||
Reference in New Issue
Block a user