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

View File

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

View File

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

View File

@ -0,0 +1,97 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "Mesh.h"
#include "CompoundGeometry.h"
#include "CompoundCreator.h"
#include "PxConvexMeshGeometry.h"
#include "PxRigidBodyExt.h"
#include "foundation/PxMat44.h"
#include "PxScene.h"
#include "PxShape.h"
#include "SimScene.h"
#include "Compound.h"
#include "Convex.h"
#include "foundation/PxMathUtils.h"
#include <vector>
#include <stdio.h>
#include "MathUtils.h"
using namespace std;
#define CREATE_DEBRIS 1
float Compound::getSleepingThresholdRB()
{
return 0.1f;
}
// --------------------------------------------------------------------------------------------
void Compound::draw(bool useShader, bool debug)
{
if (useShader && mShader)
mShader->activate(mShaderMat);
else {
glColor3f(mShaderMat.color[0], mShaderMat.color[1], mShaderMat.color[2]);
}
for (int i = 0; i < (int)mConvexes.size(); i++)
mConvexes[i]->draw(debug);
if (useShader && mShader)
mShader->deactivate();
}
// --------------------------------------------------------------------------------------------
void Compound::clear()
{
base::Compound::clear();
mShader = NULL;
mShaderMat.init();
}
void Compound::copyShaders(base::Compound* m)
{
((Compound*)m)->mShader = mShader;
((Compound*)m)->mShaderMat = mShaderMat;
}
void Compound::convexAdded(base::Convex* c, Shader* shader)
{
((SimScene*)mScene)->getConvexRenderer().add(c, shader);
}
void Compound::convexRemoved(base::Convex* c)
{
((SimScene*)mScene)->getConvexRenderer().remove(c);
}

View File

@ -0,0 +1,86 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#ifndef COMPOUND
#define COMPOUND
#include <foundation/PxVec3.h>
#include <foundation/PxPlane.h>
#include <foundation/PxBounds3.h>
#include <foundation/PxTransform.h>
#include <PsArray.h>
#include <PxRigidDynamic.h>
#include "Shader.h"
#include "CompoundBase.h"
using namespace physx;
class Convex;
class Particles;
class Mesh;
class SimScene;
class CompoundGeometry;
class XMLParser;
class ShaderShadow;
using namespace physx::fracture;
class Compound : public base::Compound
{
friend class SimScene;
protected:
Compound(SimScene* scene, PxReal contactOffset = 0.005f, PxReal restOffset = -0.001f):
physx::fracture::base::Compound((base::SimScene*)scene,contactOffset,restOffset) {}
public:
virtual void convexAdded(base::Convex* c, Shader* shader);
virtual void convexRemoved(base::Convex* c);
bool createFromXml(XMLParser *p, float scale, const PxTransform &trans, bool ignoreVisualMesh = false);
void setShader(Shader* shader, const ShaderMaterial &mat) { mShader = shader; mShaderMat = mat; }
Shader* getShader() const { return mShader; }
const ShaderMaterial& getShaderMat() { return mShaderMat; }
virtual void draw(bool useShader, bool debug = false);
virtual void clear();
virtual void copyShaders(base::Compound*);
protected:
virtual float getSleepingThresholdRB();
Shader *mShader;
ShaderMaterial mShaderMat;
};
#endif

View File

@ -0,0 +1,65 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "CompoundCreator.h"
#include <algorithm>
#include <assert.h>
#include "CompoundGeometry.h"
#define DEBUG_DRAW 1
#if DEBUG_DRAW
#include <windows.h>
#include <GL/gl.h>
#endif
// -----------------------------------------------------------------------------
void CompoundCreator::debugDraw()
{
#if DEBUG_DRAW
const bool drawEdges = false;
if (drawEdges) {
glBegin(GL_LINES);
for (int i = 0; i < (int)mTetEdges.size(); i++) {
TetEdge &e = mTetEdges[i];
if (e.onSurface)
glColor3f(1.0f, 0.0f, 0.0f);
else
glColor3f(1.0f, 1.0f, 0.0f);
PxVec3 &p0 = mTetVertices[e.i0];
PxVec3 &p1 = mTetVertices[e.i1];
glVertex3f(p0.x, p0.y, p0.z);
glVertex3f(p1.x, p1.y, p1.z);
}
glEnd();
}
#endif
}

View File

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

View File

@ -0,0 +1,102 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "CompoundGeometry.h"
#define DEBUG_DRAW 1
#if DEBUG_DRAW
#include <windows.h>
#include <GL/gl.h>
#endif
// -------------------------------------------------------------------------------
void CompoundGeometry::debugDraw(int maxConvexes) const
{
#if DEBUG_DRAW
const bool drawConvexes = true;
const bool drawWireframe = true;
const bool drawClipped = false;
const float clipMaxX = 0.0f;
if (drawConvexes) {
float s = drawClipped ? 1.0f : 0.95f;
if (drawWireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
PxVec3 n;
int num = convexes.size();
if (maxConvexes > 0 && maxConvexes < num)
num = maxConvexes;
for (int i = 0; i < num; i++) {
switch (i%7) {
case 0 : glColor3f(1.0f, 0.0f, 0.0f); break;
case 1 : glColor3f(0.0f, 1.0f, 0.0f); break;
case 2 : glColor3f(1.0f, 0.0f, 1.0f); break;
case 3 : glColor3f(0.0f, 1.0f, 1.0f); break;
case 4 : glColor3f(1.0f, 0.0f, 1.0f); break;
case 5 : glColor3f(1.0f, 1.0f, 0.0f); break;
case 6 : glColor3f(1.0f, 1.0f, 1.0f); break;
};
const Convex &c = convexes[i];
const PxVec3 *verts = &vertices[c.firstVert];
PxVec3 center;
center = PxVec3(0.0f, 0.0f, 0.0f);
for (int j = 0; j < c.numVerts; j++)
center += verts[j];
center /= (float)c.numVerts;
if (drawClipped && center.x > clipMaxX)
continue;
const int *ids = &indices[c.firstIndex];
for (int j = 0; j < c.numFaces; j++) {
int numVerts = *ids++;
int flags = *ids++;
n = (verts[ids[1]] - verts[ids[0]]).cross(verts[ids[2]] - verts[ids[0]]);
n.normalize();
glNormal3f(n.x, n.y, n.z);
glBegin(GL_POLYGON);
for (int k = 0; k < numVerts; k++) {
PxVec3 p = verts[ids[k]];
p = center + (p - center) * s;
glVertex3f(p.x, p.y, p.z);
}
glEnd();
ids += numVerts;
}
}
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
#endif
}

View File

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

View File

@ -0,0 +1,276 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "PxPhysics.h"
#include "PxCooking.h"
#include "PxDefaultStreams.h"
#include "PxShape.h"
#include "foundation/PxMath.h"
#include "PxRigidDynamic.h"
#include "PxConvexMesh.h"
#include "foundation/PxMat44.h"
#include "foundation/PxMathUtils.h"
#include "CompoundGeometry.h"
#include "Shader.h"
#include "PolygonTriangulator.h"
#include "Convex.h"
#include "PhysXMacros.h"
class physx::PxPhysics;
class physx::PxCooking;
class physx::PxActor;
class physx::PxScene;
class physx::PxConvexMesh;
#define COOK_TRIANGLES 0
#include <algorithm>
// --------------------------------------------------------------------------------------------
void Convex::draw(bool debug)
{
//if (!mIsGhostConvex)
// return; // foo
bool drawConvex = true;
bool drawVisMesh = true;
bool wireframe = false;
bool drawWorldBounds = false;
bool drawInsideTest = false;
bool drawVisPolys = true;
bool drawTangents = false;
bool drawNewFlag = false;
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0f, 1.0f);
if (!debug) {
drawConvex = false;
drawVisMesh = true;
wireframe = false;
drawWorldBounds = false;
drawInsideTest = false;
drawVisPolys = false;
drawTangents = false;
}
if (drawConvex) {
if (mHasExplicitVisMesh)
glColor3f(0.0f, 0.0f, 1.0f);
else if (mIsGhostConvex)
glColor3f(0.0f, 1.0f, 0.0f);
else
glColor3f(1.0f, 1.0f, 1.0f);
glDisable(GL_LIGHTING);
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
PxMat44 mat(getGlobalPose());
glMultMatrixf((GLfloat*)mat.front());
}
glBegin(GL_LINES);
for (int i = 0; i < (int)mFaces.size(); i++) {
Face &f = mFaces[i];
for (int j = 0; j < f.numIndices; j++) {
PxVec3 &p0 = mVertices[mIndices[f.firstIndex + j]];
PxVec3 &p1 = mVertices[mIndices[f.firstIndex + (j+1)%f.numIndices]];
glVertex3f(p0.x, p0.y, p0.z);
glVertex3f(p1.x, p1.y, p1.z);
}
if (drawNewFlag && (f.flags & CompoundGeometry::FF_NEW) && f.numIndices > 0) {
float r = 0.01f;
PxVec3 c(0.0f, 0.0f, 0.0f);
for (int j = 0; j < f.numIndices; j++)
c += mVertices[mIndices[f.firstIndex + j]];
c /= (float)f.numIndices;
glVertex3f(c.x - r, c.y, c.z); glVertex3f(c.x + r, c.y, c.z);
glVertex3f(c.x, c.y - r, c.z); glVertex3f(c.x, c.y + r, c.z);
glVertex3f(c.x, c.y, c.z - r); glVertex3f(c.x, c.y, c.z + r);
}
}
glEnd();
glEnable(GL_LIGHTING);
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
}
if (mVisVertices.empty())
return;
if (drawVisPolys) {
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
PxMat44 mat(getGlobalPose());
glMultMatrixf((GLfloat*)mat.front());
}
glColor3f(1.0f, 0.0f, 0.0f);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
for (int i = 0; i < (int)mVisPolyStarts.size()-1; i++) {
int first = mVisPolyStarts[i];
int num = mVisPolyStarts[i+1] - first;
for (int j = 0; j < num; j++) {
PxVec3 &p0 = mVisVertices[mVisPolyIndices[first + j]];
PxVec3 &p1 = mVisVertices[mVisPolyIndices[first + (j+1)%num]];
glVertex3f(p0.x, p0.y, p0.z);
glVertex3f(p1.x, p1.y, p1.z);
}
}
glEnd();
glEnable(GL_LIGHTING);
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
}
if (drawTangents) {
const float r = 0.1f;
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
PxMat44 mat(getGlobalPose());
glMultMatrixf((GLfloat*)mat.front());
}
glColor3f(1.0f, 1.0f, 0.0f);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
for (int i = 0; i < (int)mVisVertices.size()-1; i++) {
PxVec3 p0 = mVisVertices[i];
PxVec3 p1 = p0 + r * mVisTangents[i];
glVertex3f(p0.x, p0.y, p0.z);
glVertex3f(p1.x, p1.y, p1.z);
}
glEnd();
glEnable(GL_LIGHTING);
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
}
if (drawVisMesh && mVisTriIndices.size() > 0) {
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
PxMat44 mat(getGlobalPose());
glMultMatrixf((GLfloat*)mat.front());
}
if (wireframe) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDisable(GL_LIGHTING);
}
if (debug)
glColor3f(1.0f, 1.0f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &mVisVertices[0]);
glNormalPointer(GL_FLOAT, sizeof(PxVec3), &mVisNormals[0]);
glDrawElements(GL_TRIANGLES, mVisTriIndices.size(), GL_UNSIGNED_INT, &mVisTriIndices[0]);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
if (mPxActor != NULL) {
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
if (wireframe) {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_LIGHTING);
}
}
if (drawWorldBounds) {
static const int corners[12 * 2][3] = {
{0,0,0}, {1,0,0}, {0,1,0}, {1,1,0}, {0,1,1}, {1,1,1}, {0,0,1}, {1,0,1},
{0,0,0}, {0,1,0}, {1,0,0}, {1,1,0}, {1,0,1}, {1,1,1}, {0,0,1}, {0,1,1},
{0,0,0}, {0,0,1}, {1,0,0}, {1,0,1}, {1,1,0}, {1,1,1}, {0,1,0}, {0,1,1}};
PxBounds3 b;
getWorldBounds(b);
glBegin(GL_LINES);
for (int i = 0; i < 24; i++) {
glVertex3f(
corners[i][0] ? b.minimum.x : b.maximum.x,
corners[i][1] ? b.minimum.y : b.maximum.y,
corners[i][2] ? b.minimum.z : b.maximum.z);
}
glEnd();
}
if (drawInsideTest) {
PxBounds3 bounds;
bounds.setEmpty();
for (int i = 0; i < (int)mVertices.size(); i++)
bounds.include(mVertices[i]);
int num = 20;
float r = 0.05f * bounds.getDimensions().magnitude() / (float)num;
PxVec3 p;
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_LINES);
for (int xi = 0; xi < num; xi++) {
for (int yi = 0; yi < num; yi++) {
for (int zi = 0; zi < num; zi++) {
p.x = bounds.minimum.x + xi * (bounds.maximum.x - bounds.minimum.x)/num;
p.y = bounds.minimum.y + yi * (bounds.maximum.y - bounds.minimum.y)/num;
p.z = bounds.minimum.z + zi * (bounds.maximum.z - bounds.minimum.z)/num;
if (insideVisualMesh(p)) {
glVertex3f(p.x - r, p.y, p.z); glVertex3f(p.x + r, p.y, p.z);
glVertex3f(p.x, p.y - r, p.z); glVertex3f(p.x, p.y + r, p.z);
glVertex3f(p.x, p.y, p.z - r); glVertex3f(p.x, p.y, p.z + r);
}
}
}
}
glEnd();
}
glDisable(GL_POLYGON_OFFSET_FILL);
}

View File

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

View File

@ -0,0 +1,403 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "Shader.h"
#include "ConvexRenderer.h"
#include "Compound.h"
#include <foundation/PxMat44.h>
//--------------------------------------------------------
ConvexRenderer::ConvexRenderer()
{
init();
}
//--------------------------------------------------------
ConvexRenderer::~ConvexRenderer()
{
}
//--------------------------------------------------------
void ConvexRenderer::init()
{
mShader = NULL;
mShaderMat.init();
mBumpTextureUVScale = 0.1f;
mExtraNoiseScale = 2.0f;
mRoughnessScale = 0.2f;
mDiffuseTexArray = 0;
mBumpTexArray = 0;
mSpecularTexArray = 0;
mEmissiveReflectSpecPowerTexArray = 0;
mActive = true;
}
//--------------------------------------------------------
void ConvexRenderer::add(const base::Convex* convex, Shader* shader)
{
if (!mActive)
return;
ConvexGroup *g;
// int gnr = 0; // to search all groups
int gnr = 0;// !mGroups.empty() ? mGroups.size() - 1 : 0; // to search only last
int numNewVerts = convex->getVisVertices().size();
while (gnr < (int)mGroups.size() && (mGroups[gnr]->numVertices + numNewVerts >= maxVertsPerGroup || mGroups[gnr]->mShader != shader))
gnr++;
if (gnr == (int)mGroups.size()) { // create new group
g = new ConvexGroup();
g->init();
g->mShader = shader;
gnr = mGroups.size();
mGroups.push_back(g);
}
g = mGroups[gnr];
convex->setConvexRendererInfo(gnr, g->convexes.size());
g->convexes.push_back((Convex*)convex);
g->numIndices += convex->getVisTriIndices().size();
g->numVertices += convex->getVisVertices().size();
g->dirty = true;
}
//--------------------------------------------------------
void ConvexRenderer::remove(const base::Convex* convex)
{
if (!mActive)
return;
int gnr = convex->getConvexRendererGroupNr();
int pos = convex->getConvexRendererGroupPos();
if (gnr < 0 || gnr >= (int)mGroups.size())
return;
ConvexGroup *g = mGroups[gnr];
if (pos < 0 || pos > (int)g->convexes.size())
return;
if (g->convexes[pos] != convex)
return;
g->numIndices -= convex->getVisTriIndices().size();
g->numVertices -= convex->getVisVertices().size();
g->convexes[pos] = g->convexes[g->convexes.size()-1];
g->convexes[pos]->setConvexRendererInfo(gnr, pos);
g->convexes.pop_back();
g->dirty = true;
}
//--------------------------------------------------------
void ConvexRenderer::updateRenderBuffers()
{
/*
static int maxNumV = 0;
static int maxNumI = 0;
static int maxNumC = 0;
static int maxNumG = 0;
if (mGroups.size() > maxNumG) maxNumG = mGroups.size();
*/
for (int i = 0; i < (int)mGroups.size(); i++) {
ConvexGroup *g = mGroups[i];
if (!g->dirty)
continue;
if (g->numIndices == 0 || g->numVertices == 0)
continue;
if (!g->VBO) {
glGenBuffersARB(1, &g->VBO);
}
if (!g->IBO) {
glGenBuffersARB(1, &g->IBO);
}
if (!g->matTex) {
glGenTextures(1, &g->matTex);
glBindTexture(GL_TEXTURE_2D, g->matTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glBindTexture(GL_TEXTURE_2D, 0);
}
if (g->numVertices == 0 || g->numIndices == 0)
return;
// recalculate in case they have changed
g->numVertices = 0;
g->numIndices = 0;
for (int i = 0; i < (int)g->convexes.size(); i++) {
g->numVertices += g->convexes[i]->getVisVertices().size();
g->numIndices += g->convexes[i]->getVisTriIndices().size();
}
g->vertices.resize(g->numVertices*12);
g->indices.resize(g->numIndices);
float* vp = &g->vertices[0];
unsigned int* ip = &g->indices[0];
int sumV = 0;
// Make cpu copy of VBO and IBO
int convexNr = 0;
for (int j = 0; j < (int)g->convexes.size(); j++, convexNr++) {
const Convex* c = g->convexes[j];
// PxVec3 matOff = c->getMaterialOffset();
int nv = c->getVisVertices().size();
int ni = c->getVisTriIndices().size();
if (nv > 0) {
float* cvp = (float*)&c->getVisVertices()[0]; // float3
float* cnp = (float*)&c->getVisNormals()[0]; // float3
// float* c3dtp = (float*)&c->getVisVertices()[0]; // float3
float* c2dtp = (float*)&c->getVisTexCoords()[0]; // float2
float* ctanp = (float*)&c->getVisTangents()[0]; // float3
int* cip = (int*)&c->getVisTriIndices()[0];
for (int k = 0; k < nv; k++) {
*(vp++) = *(cvp++);
*(vp++) = *(cvp++);
*(vp++) = *(cvp++);
*(vp++) = *(cnp++);
*(vp++) = *(cnp++);
*(vp++) = *(cnp++);
*(vp++) = *(ctanp++);
*(vp++) = *(ctanp++);
*(vp++) = *(ctanp++);
*(vp++) = (float)convexNr;
*(vp++) = *(c2dtp++);
*(vp++) = *(c2dtp++);
}
for (int k = 0; k < ni; k++) {
*(ip++) = *(cip++) + sumV;
}
}
//memcpy(ip, cip, sizeof(int)*ni);
//ip += 3*ni;
//std::vector<PxVec3> mTriVertices;
//std::vector<PxVec3> mTriNormals;
//std::vector<int> mTriIndices;
//std::vector<float> mTriTexCoords; // 3d + obj nr
sumV += nv;
}
/*
if (g->vertices.size() > maxNumV) maxNumV = g->vertices.size();
if (g->indices.size() > maxNumI) maxNumI = g->indices.size();
if (g->convexes.size() > maxNumC) maxNumC = g->convexes.size();
*/
glBindBufferARB(GL_ARRAY_BUFFER_ARB, g->VBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, g->vertices.size()*sizeof(float), &g->vertices[0], GL_DYNAMIC_DRAW);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, g->IBO);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, g->indices.size()*sizeof(unsigned int), &g->indices[0], GL_DYNAMIC_DRAW);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
int oldTexSize = g->texSize;
if (g->texSize == 0) {
// First time
oldTexSize = 1;
g->texSize = 32;
}
while (1) {
int convexesPerRow = g->texSize / 4;
if (convexesPerRow * g->texSize >= (int)g->convexes.size()) {
break;
} else {
g->texSize *= 2;
}
}
if (g->texSize != oldTexSize) {
g->texCoords.resize(g->texSize*g->texSize*4);
// Let's allocate texture
glBindTexture(GL_TEXTURE_2D, g->matTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, g->texSize, g->texSize, 0, GL_RGBA, GL_FLOAT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
g->dirty = false;
}
// printf("maxV = %d, maxI = %d, maxC = %d, maxG = %d\n", maxNumV, maxNumI, maxNumC, maxNumG);
}
//--------------------------------------------------------
void ConvexRenderer::updateTransformations()
{
for (int i = 0; i < (int)mGroups.size(); i++) {
ConvexGroup *g = mGroups[i];
if (g->texCoords.empty())
continue;
float* tt = &g->texCoords[0];
for (int j = 0; j < (int)g->convexes.size(); j++) {
const Convex* c = g->convexes[j];
PxMat44 pose(c->getGlobalPose());
float* mp = (float*)pose.front();
float* ta = tt;
for (int k = 0; k < 16; k++) {
*(tt++) = *(mp++);
}
PxVec3 matOff = c->getMaterialOffset();
ta[3] = matOff.x;
ta[7] = matOff.y;
ta[11] = matOff.z;
int idFor2DTex = c->getSurfaceMaterialId();
int idFor3DTex = c->getMaterialId();
const int MAX_3D_TEX = 8;
ta[15] = (float)(idFor2DTex*MAX_3D_TEX + idFor3DTex);
}
glBindTexture(GL_TEXTURE_2D, g->matTex);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, g->texSize, g->texSize,
GL_RGBA, GL_FLOAT, &g->texCoords[0]);
glBindTexture(GL_TEXTURE_2D, 0);
}
}
//--------------------------------------------------------
void ConvexRenderer::render()
{
if (!mActive)
return;
updateRenderBuffers();
updateTransformations();
for (int i = 0; i < (int)mGroups.size(); i++) {
ConvexGroup *g = mGroups[i];
Shader* shader = mShader;
if (g->mShader != NULL)
shader = g->mShader;
shader->activate(mShaderMat);
// Assume convex all use the same shader
glActiveTexture(GL_TEXTURE7);
glBindTexture(GL_TEXTURE_3D, volTex);
glActiveTexture(GL_TEXTURE8);
glBindTexture(GL_TEXTURE_2D, g->matTex);
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mDiffuseTexArray);
glActiveTexture(GL_TEXTURE11);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mBumpTexArray);
glActiveTexture(GL_TEXTURE12);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mSpecularTexArray);
glActiveTexture(GL_TEXTURE13);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mEmissiveReflectSpecPowerTexArray);
glActiveTexture(GL_TEXTURE0);
float itt = 1.0f/g->texSize;
shader->setUniform("diffuseTexArray", 10);
shader->setUniform("bumpTexArray", 11);
shader->setUniform("specularTexArray", 12);
shader->setUniform("emissiveReflectSpecPowerTexArray", 13);
shader->setUniform("ttt3D", 7);
shader->setUniform("transTex", 8);
shader->setUniform("transTexSize", g->texSize);
shader->setUniform("iTransTexSize", itt);
shader->setUniform("bumpTextureUVScale", mBumpTextureUVScale);
shader->setUniform("extraNoiseScale", mExtraNoiseScale);
shader->setUniform("roughnessScale", mRoughnessScale);
if (mShaderMat.color[3] < 1.0f) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
glColor4f(mShaderMat.color[0], mShaderMat.color[1], mShaderMat.color[2], mShaderMat.color[3]);
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, g->VBO);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, g->IBO);
int stride = 12*sizeof(float);
glVertexPointer(3, GL_FLOAT, stride, 0);
glNormalPointer(GL_FLOAT, stride, (void*)(3*sizeof(float)));
glTexCoordPointer(4, GL_FLOAT, stride, (void*)(6*sizeof(float)));
glClientActiveTexture(GL_TEXTURE1);
glTexCoordPointer(2, GL_FLOAT, stride, (void*)(10*sizeof(float)));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawElements(GL_TRIANGLES, g->numIndices, GL_UNSIGNED_INT, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
if (mShaderMat.color[3] < 1.0f) {
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
shader->deactivate();
}
}

View File

@ -0,0 +1,104 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#ifndef CONVEX_RENDERER
#define CONVEX_RENDERER
#include "Convex.h"
#include <vector>
using namespace physx;
class Shader;
// ----------------------------------------------------------------------------
class ConvexRenderer
{
public:
ConvexRenderer();
~ConvexRenderer();
void init();
const static int maxVertsPerGroup = 100000;
void setActive(bool active) { mActive = active; };
void add(const base::Convex* convex, Shader* shader);
void remove(const base::Convex* convex);
void render();
void setShaderMaterial(Shader* shader, const ShaderMaterial& mat) {this->mShader = shader; this->mShaderMat = mat;}
void setTexArrays(unsigned int diffuse, unsigned int bump, unsigned int specular, unsigned int specPower) {
mDiffuseTexArray = diffuse; mBumpTexArray = bump;
mSpecularTexArray = specular; mEmissiveReflectSpecPowerTexArray = specPower; }
void setVolTex(unsigned int volTexi) { volTex = volTexi;}
private:
void updateRenderBuffers();
void updateTransformations();
Shader* mShader;
ShaderMaterial mShaderMat;
struct ConvexGroup {
void init() {
numVertices = 0; numIndices = 0;
VBO = 0; IBO = 0; matTex = 0;
texSize = 0;
}
bool dirty;
std::vector<const Convex*> convexes;
std::vector<float> vertices;
std::vector<unsigned int> indices;
std::vector<float> texCoords;
int numVertices, numIndices;
unsigned int VBO;
unsigned int IBO;
unsigned int matTex;
int texSize;
Shader* mShader;
};
std::vector<ConvexGroup*> mGroups;
bool mActive;
float mBumpTextureUVScale;
float mExtraNoiseScale;
float mRoughnessScale;
unsigned int mDiffuseTexArray;
unsigned int mBumpTexArray;
unsigned int mSpecularTexArray;
unsigned int mEmissiveReflectSpecPowerTexArray;
unsigned int volTex;
};
#endif

View File

@ -0,0 +1,166 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#include "ActorBase.h"
#include <foundation/PxMat44.h>
#include "PxRigidBodyExt.h"
#include "PxScene.h"
#include "SimSceneBase.h"
#include "CompoundBase.h"
namespace physx
{
namespace fracture
{
namespace base
{
Actor::Actor(SimScene* scene):
mScene(scene),
mMinConvexSize(scene->mMinConvexSize),
mDepthLimit(100),
mDestroyIfAtDepthLimit(false)
{
}
Actor::~Actor()
{
mScene->getScene()->lockWrite();
clear();
mScene->getScene()->unlockWrite();
mScene->removeActor(this);
}
void Actor::clear()
{
for (int i = 0; i < (int)mCompounds.size(); i++) {
PX_DELETE(mCompounds[i]);
}
mCompounds.clear();
}
void Actor::addCompound(Compound *c)
{
mCompounds.pushBack(c);
PxRigidDynamic *a = c->getPxActor();
#if 1
if (a) {
// a->setContactReportFlags(Px_NOTIFY_ON_TOUCH_FORCE_THRESHOLD | Px_NOTIFY_ON_START_TOUCH_FORCE_THRESHOLD);
a->setContactReportThreshold(mScene->mFractureForceThreshold);
}
#endif
c->mActor = this;
++(mScene->mSceneVersion);
}
void Actor::removeCompound(Compound *c)
{
int num = 0;
for (int i = 0; i < (int)mCompounds.size(); i++) {
if (mCompounds[i] != c) {
mCompounds[num] = mCompounds[i];
num++;
}
}
if (mScene->mPickActor == c->getPxActor())
mScene->mPickActor = NULL;
c->clear();
//delCompoundList.push_back(c);
//delete c;
mScene->delCompoundList.pushBack(c);
mCompounds.resize(num);
++mScene->mSceneVersion;
}
void Actor::preSim(float dt)
{
int num = 0;
for (int i = 0; i < (int)mCompounds.size(); i++) {
mCompounds[i]->step(dt);
if (mCompounds[i]->getLifeFrames() == 0) {
mCompounds[i]->clear();
//delCompoundList.push_back(mCompounds[i]);
//delete mCompounds[i];
mScene->delCompoundList.pushBack(mCompounds[i]);
}
else {
mCompounds[num] = mCompounds[i];
num++;
}
}
mCompounds.resize(num);
}
void Actor::postSim(float /*dt*/)
{
}
bool Actor::rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &compoundNr, int &convexNr, PxVec3 &normal) const
{
dist = PX_MAX_F32;
compoundNr = -1;
convexNr = -1;
for (int i = 0; i < (int)mCompounds.size(); i++) {
float d;
int cNr;
PxVec3 n;
if (mCompounds[i]->rayCast(orig, dir, d, cNr, n)) {
if (d < dist) {
dist = d;
compoundNr = i;
convexNr = cNr;
normal = n;
}
}
}
return compoundNr >= 0;
}
bool Actor::findCompound(const Compound* c, int& compoundNr)
{
for(int i = 0; i < (int)mCompounds.size(); i++)
{
if(mCompounds[i] == c)
{
compoundNr = i;
return true;
}
}
return false;
}
}
}
}
#endif

View File

@ -0,0 +1,81 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef ACTOR_BASE_H
#define ACTOR_BASE_H
#include <PsArray.h>
#include <PsUserAllocated.h>
namespace physx
{
namespace fracture
{
namespace base
{
class Compound;
class Actor : public ::physx::shdfnd::UserAllocated
{
friend class SimScene;
friend class Compound;
protected:
Actor(SimScene* scene);
public:
virtual ~Actor();
void clear();
void addCompound(Compound *m);
void removeCompound(Compound *m);
bool findCompound(const Compound* c, int& compoundNr);
void preSim(float dt);
void postSim(float dt);
bool rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &compoundNr, int &convexNr, PxVec3 &normal) const;
shdfnd::Array<Compound*> getCompounds() { return mCompounds; }
protected:
SimScene* mScene;
shdfnd::Array<Compound*> mCompounds;
PxF32 mMinConvexSize;
PxU32 mDepthLimit;
bool mDestroyIfAtDepthLimit;
};
}
}
}
#endif
#endif

View File

@ -0,0 +1,563 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#include "MeshBase.h"
#include "CompoundGeometryBase.h"
#include "CompoundCreatorBase.h"
#include "PxConvexMeshGeometry.h"
#include "PxRigidBodyExt.h"
#include "foundation/PxMat44.h"
#include "PxScene.h"
#include "PxShape.h"
#include "SimSceneBase.h"
#include "CompoundBase.h"
#include "ActorBase.h"
#include "ConvexBase.h"
#include "foundation/PxMathUtils.h"
#include <stdio.h>
#include "MathUtils.h"
namespace physx
{
namespace fracture
{
namespace base
{
//vector<PxVec3> tmpPoints;
void Compound::appendUniformSamplesOfConvexPolygon(PxVec3* vertices, int numV, float area, shdfnd::Array<PxVec3>& samples, shdfnd::Array<PxVec3>* normals) {
PxVec3& p0 = vertices[0];
PxVec3 normal;
if (numV < 3) {
normal = PxVec3(0.0f,1.0f,0.0f);
} else {
normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
normal.normalize();
}
for (int i = 1; i < numV-1; i++) {
PxVec3& p1 = vertices[i];
PxVec3& p2 = vertices[i+1];
float tarea = 0.5f*((p1-p0).cross(p2-p0)).magnitude();
float aa = tarea / area;
int np = (int)floor(aa);
if (randRange(0.0f,1.0f) <= aa-np) np++;
for (int j = 0; j < np; j++) {
float r1 = randRange(0.0f,1.0f);
float sr1 = physx::PxSqrt(r1);
float r2 = randRange(0.0f, 1.0f);
PxVec3 p = (1 - sr1) * p0 + (sr1 * (1 - r2)) * p1 + (sr1 * r2) * p2;
samples.pushBack(p);
if (normals) normals->pushBack(normal);
}
}
}
// --------------------------------------------------------------------------------------------
Compound::Compound(SimScene *scene, PxReal contactOffset, PxReal restOffset)
{
mScene = scene;
mActor = NULL;
mPxActor = NULL;
mContactOffset = contactOffset;
mRestOffset = restOffset;
mLifeFrames = -1; // live forever
mDepth = 0;
clear();
}
// --------------------------------------------------------------------------------------------
Compound::~Compound()
{
clear();
}
// --------------------------------------------------------------------------------------------
#define SHAPE_BUFFER_SIZE 100
void Compound::clear()
{
if (mPxActor != NULL) {
// Unmap all shapes for this actor
const physx::PxU32 shapeCount = mPxActor->getNbShapes();
physx::PxShape* shapeBuffer[SHAPE_BUFFER_SIZE];
for (physx::PxU32 shapeStartIndex = 0; shapeStartIndex < shapeCount; shapeStartIndex += SHAPE_BUFFER_SIZE)
{
physx::PxU32 shapesRead = mPxActor->getShapes(shapeBuffer, SHAPE_BUFFER_SIZE, shapeStartIndex);
for (physx::PxU32 shapeBufferIndex = 0; shapeBufferIndex < shapesRead; ++shapeBufferIndex)
{
mScene->unmapShape(*shapeBuffer[shapeBufferIndex]);
}
}
// release the actor
mPxActor->release();
mPxActor = NULL;
}
for (int i = 0; i < (int)mConvexes.size(); i++) {
if (mConvexes[i]->decreaseRefCounter() <= 0) {
convexRemoved(mConvexes[i]); //mScene->getConvexRenderer().remove(mConvexes[i]);
PX_DELETE(mConvexes[i]);
}
}
mConvexes.clear();
mEdges.clear();
//mShader = NULL;
//mShaderMat.init();
mKinematicVel = PxVec3(0.0f, 0.0f, 0.0f);
mAttachmentBounds.clear();
mAdditionalImpactNormalImpulse = 0.0f;
mAdditionalImpactRadialImpulse = 0.0f;
}
// --------------------------------------------------------------------------------------------
void Compound::setKinematic(const PxVec3 &vel)
{
if (mPxActor == NULL)
return;
mPxActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
mKinematicVel = vel;
}
// --------------------------------------------------------------------------------------------
void Compound::step(float dt)
{
//if (mPxActor == NULL)
// return;
if (!mKinematicVel.isZero()) {
PxTransform pose = mPxActor->getGlobalPose();
pose.p += mKinematicVel * dt;
mPxActor->setKinematicTarget(pose);
}
if (mLifeFrames > 0)
mLifeFrames--;
}
// --------------------------------------------------------------------------------------------
bool Compound::createFromConvex(Convex* convex, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, bool copyConvexes, int matID, int surfMatID)
{
return createFromConvexes(&convex, 1, pose, vel, omega, copyConvexes, matID, surfMatID);
}
// --------------------------------------------------------------------------------------------
bool Compound::createFromConvexes(Convex** convexes, int numConvexes, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, bool copyConvexes, int matID, int surfMatID)
{
if (numConvexes == 0)
return false;
clear();
PxVec3 center(0.0f, 0.0f, 0.0f);
for (int i = 0; i < numConvexes; i++)
center += convexes[i]->getCenter();
center /= (float)numConvexes;
shdfnd::Array<PxShape*> shapes;
for (int i = 0; i < numConvexes; i++) {
Convex *c;
if (copyConvexes) {
c = mScene->createConvex();
c->createFromConvex(convexes[i], 0, matID, surfMatID);
}
else
c = convexes[i];
c->increaseRefCounter();
mConvexes.pushBack(c);
PxVec3 off = c->centerAtZero();
c->setMaterialOffset(c->getMaterialOffset() + off);
c->setLocalPose(PxTransform(off - center));
if (convexes[i]->isGhostConvex())
continue;
bool reused = c->getPxConvexMesh() != NULL;
mScene->profileBegin("cook convex meshes"); //Profiler::getInstance()->begin("cook convex meshes");
PxConvexMesh* mesh = c->createPxConvexMesh(this, mScene->getPxPhysics(), mScene->getPxCooking());
mScene->profileEnd("cook convex meshes"); //Profiler::getInstance()->end("cook convex meshes");
if (mesh == NULL) {
if (c->decreaseRefCounter() <= 0)
PX_DELETE(c);
mConvexes.popBack();
continue;
}
if (!c->hasExplicitVisMesh())
c->createVisMeshFromConvex();
if (!reused)
convexAdded(c); //mScene->getConvexRenderer().add(c);
PxShape *shape = mScene->getPxPhysics()->createShape(
PxConvexMeshGeometry(mesh),
*mScene->getPxDefaultMaterial(),
true
);
shape->setLocalPose(c->getLocalPose());
//shape->setContactOffset(mContactOffset);
//shape->setRestOffset(mRestOffset);
if (mContactOffset < mRestOffset || mContactOffset < 0.0f)
{
printf("WRONG\n");
}
mScene->mapShapeToConvex(*shape, *c);
shapes.pushBack(shape);
}
if (shapes.empty())
{
return false;
}
createPxActor(shapes, pose, vel, omega);
return true;
}
// --------------------------------------------------------------------------------------------
bool Compound::createFromGeometry(const CompoundGeometry &geom, PxRigidDynamic* body, Shader* myShader, int matID, int surfMatID)
{
clear();
shdfnd::Array<PxShape*> shapes(body->getNbShapes());
body->getShapes(shapes.begin(), body->getNbShapes());
PX_ASSERT(geom.convexes.size() == body->getNbShapes());
for (int i = 0; i < (int)geom.convexes.size(); i++) {
Convex *c = mScene->createConvex();
c->createFromGeometry(geom, i, 0, matID, surfMatID);
c->increaseRefCounter();
mConvexes.pushBack(c);
PxVec3 off = c->centerAtZero();
c->setMaterialOffset(c->getMaterialOffset() + off);
c->createVisMeshFromConvex();
c->setLocalPose(PxTransform(off));
bool reused = c->getPxConvexMesh() != NULL;
if (!reused)
convexAdded(c, myShader); //mScene->getConvexRenderer().add(c);
mScene->mapShapeToConvex(*shapes[i], *c);
}
if (shapes.empty())
return false;
mPxActor = body;
for (int i = 0; i < (int)mConvexes.size(); i++)
mConvexes[i]->setPxActor(mPxActor);
//createPxActor(shapes, pose, vel, omega);
return true;
}
bool Compound::createFromGeometry(const CompoundGeometry &geom, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, Shader* myShader, int matID, int surfMatID)
{
clear();
shdfnd::Array<PxShape*> shapes;
for (int i = 0; i < (int)geom.convexes.size(); i++) {
Convex *c = mScene->createConvex();
c->createFromGeometry(geom, i, 0, matID, surfMatID);
c->increaseRefCounter();
mConvexes.pushBack(c);
PxVec3 off = c->centerAtZero();
c->setMaterialOffset(c->getMaterialOffset() + off);
c->createVisMeshFromConvex();
c->setLocalPose(PxTransform(off));
bool reused = c->getPxConvexMesh() != NULL;
PxConvexMesh* mesh = c->createPxConvexMesh(this, mScene->getPxPhysics(), mScene->getPxCooking());
if (mesh == NULL) {
if (c->decreaseRefCounter() <= 0)
PX_DELETE(c);
mConvexes.popBack();
continue;
}
if (!reused)
convexAdded(c, myShader); //mScene->getConvexRenderer().add(c);
PxShape *shape;
if (geom.convexes[i].isSphere)
{
shape = mScene->getPxPhysics()->createShape(
PxSphereGeometry(geom.convexes[i].radius),
*mScene->getPxDefaultMaterial(),
true
);
}
else
{
shape = mScene->getPxPhysics()->createShape(
PxConvexMeshGeometry(mesh),
*mScene->getPxDefaultMaterial(),
true
);
}
shape->setLocalPose(c->getLocalPose());
//shape->setContactOffset(mContactOffset);
//shape->setRestOffset(mRestOffset);
mScene->mapShapeToConvex(*shape, *c);
shapes.pushBack(shape);
}
if (shapes.empty())
return false;
createPxActor(shapes, pose, vel, omega);
return true;
}
// --------------------------------------------------------------------------------------------
void Compound::createFromMesh(const Mesh *mesh, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, int submeshNr, const PxVec3& scale, int matID, int surfMatID)
{
const shdfnd::Array<PxVec3> &verts = mesh->getVertices();
const shdfnd::Array<PxVec3> &normals = mesh->getNormals();
const shdfnd::Array<PxVec2> &texcoords = mesh->getTexCoords();
const shdfnd::Array<PxU32> &indices = mesh->getIndices();
if (verts.empty() || indices.empty())
return;
if (submeshNr >= 0 && submeshNr >= (int)mesh->getSubMeshes().size())
return;
PxBounds3 bounds;
mesh->getBounds(bounds, submeshNr);
PxMat33 scaleMat(PxMat33::createDiagonal(scale));
bounds = PxBounds3::transformSafe(scaleMat, bounds);
PxVec3 dims = bounds.getDimensions() * 1.01f;
PxVec3 center = bounds.getCenter();
mScene->getCompoundCreator()->createBox(dims);
createFromGeometry(mScene->getCompoundCreator()->getGeometry(), pose, vel, omega, NULL, matID, surfMatID);
PxTransform trans(-center);
if (submeshNr < 0)
mConvexes[0]->setExplicitVisMeshFromTriangles(verts.size(), &verts[0], &normals[0], &texcoords[0], indices.size(), &indices[0], &trans, &scale);
else {
const Mesh::SubMesh &sm = mesh->getSubMeshes()[submeshNr];
mConvexes[0]->setExplicitVisMeshFromTriangles(verts.size(), &verts[0], &normals[0], &texcoords[0], sm.numIndices, &indices[sm.firstIndex], &trans, &scale);
}
}
// --------------------------------------------------------------------------------------------
bool Compound::createPxActor(shdfnd::Array<PxShape*> &shapes, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega)
{
if (shapes.empty())
return false;
for(int i = 0; i < (int)shapes.size(); i++)
{
applyShapeTemplate(shapes[i]);
}
PxRigidDynamic* body = mScene->getPxPhysics()->createRigidDynamic(pose);
if (body == NULL)
return false;
//body->setSleepThreshold(getSleepingThresholdRB());
#if 0
body->setWakeCounter(100000000000.f);
#endif
mScene->getScene()->addActor(*body);
for (int i = 0; i < (int)shapes.size(); i++)
body->attachShape(*shapes[i]);
//KS - we clamp the mass in the range [minMass, maxMass]. This helps to improve stability
PxRigidBodyExt::updateMassAndInertia(*body, 1.0f);
/*const PxReal maxMass = 50.f;
const PxReal minMass = 1.f;
PxReal mass = PxMax(PxMin(maxMass, body->getMass()), minMass);
PxRigidBodyExt::setMassAndUpdateInertia(*body, mass);*/
body->setLinearVelocity(vel);
body->setAngularVelocity(omega);
/*if (vel.isZero() && omega.isZero())
{
body->putToSleep();
}*/
mPxActor = body;
for (int i = 0; i < (int)mConvexes.size(); i++)
mConvexes[i]->setPxActor(mPxActor);
return true;
}
// --------------------------------------------------------------------------------------------
bool Compound::rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &convexNr, PxVec3 &normal)
{
dist = PX_MAX_F32;
convexNr = -1;
for (int i = 0; i < (int)mConvexes.size(); i++) {
float d;
PxVec3 n;
if (mConvexes[i]->rayCast(orig, dir, d, n)) {
if (d < dist) {
dist = d;
convexNr = i;
normal = n;
}
}
}
return convexNr >= 0;
}
// --------------------------------------------------------------------------------------------
void Compound::getRestBounds(PxBounds3 &bounds) const
{
bounds.setEmpty();
PxBounds3 bi;
for (int i = 0; i < (int)mConvexes.size(); i++) {
Convex *c = mConvexes[i];
PxBounds3 bi = c->getBounds();
bi = PxBounds3::transformSafe(c->getLocalPose(), bi);
bounds.include(bi);
}
}
// --------------------------------------------------------------------------------------------
void Compound::getWorldBounds(PxBounds3 &bounds) const
{
bounds.setEmpty();
PxBounds3 bi;
for (int i = 0; i < (int)mConvexes.size(); i++) {
mConvexes[i]->getWorldBounds(bi);
bounds.include(bi);
}
}
// --------------------------------------------------------------------------------------------
void Compound::getLocalBounds(PxBounds3 &bounds) const
{
bounds.setEmpty();
PxBounds3 bi;
for (int i = 0; i < (int)mConvexes.size(); i++) {
mConvexes[i]->getLocalBounds(bi);
bounds.include(bi);
}
}
// --------------------------------------------------------------------------------------------
bool Compound::isAttached()
{
if (mAttachmentBounds.empty())
return false;
PxBounds3 b;
for (int i = 0; i < (int)mConvexes.size(); i++) {
Convex *c = mConvexes[i];
b = c->getBounds();
b.minimum += c->getMaterialOffset();
b.maximum += c->getMaterialOffset();
for (int j = 0; j < (int)mAttachmentBounds.size(); j++) {
if (b.intersects(mAttachmentBounds[j]))
return true;
}
}
return false;
}
// --------------------------------------------------------------------------------------------
void Compound::attach(const shdfnd::Array<PxBounds3> &bounds)
{
mAttachmentBounds.resize(bounds.size());
PxTransform t = getPxActor()->getGlobalPose().getInverse();
for (int i = 0; i < (int)bounds.size(); i++) {
PxVec3 a = t.transform(bounds[i].minimum);
PxVec3 b = t.transform(bounds[i].maximum);
mAttachmentBounds[i].minimum = PxVec3(PxMin(a.x,b.x),PxMin(a.y,b.y),PxMin(a.z,b.z));
mAttachmentBounds[i].maximum = PxVec3(PxMax(a.x,b.x),PxMax(a.y,b.y),PxMax(a.z,b.z));
}
if (isAttached())
mPxActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
}
// --------------------------------------------------------------------------------------------
void Compound::attachLocal(const shdfnd::Array<PxBounds3> &bounds)
{
mAttachmentBounds.resize(bounds.size());
for (int i = 0; i < (int)bounds.size(); i++) {
mAttachmentBounds[i] = bounds[i];
}
if (isAttached())
mPxActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
}
}
}
}
#endif

View File

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

View File

@ -0,0 +1,871 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#include "CompoundCreatorBase.h"
#include <algorithm>
#include <foundation/PxAssert.h>
#include "PhysXMacros.h"
#include "PxConvexMeshGeometry.h"
#include "PxConvexMesh.h"
namespace physx
{
namespace fracture
{
namespace base
{
int CompoundCreator::tetFaceIds[4][3] = {{0,1,3},{1,2,3},{2,0,3},{0,2,1}};
int CompoundCreator::tetEdgeVerts[6][2] = {{0,1},{1,2},{2,0},{0,3},{1,3},{2,3}};
int CompoundCreator::tetFaceEdges[4][3] = {{0,4,3},{1,5,4},{2,3,5},{0,2,1}};
#define CONVEX_THRESHOLD (PxPi + 0.05f)
// -----------------------------------------------------------------------------
void CompoundCreator::createTorus(float r0, float r1, int numSegs0, int numSegs1, const PxTransform *trans)
{
mGeom.clear();
CompoundGeometry::Convex c;
PxVec3 nr0,nr1,nz;
nz = PxVec3(0.0f, 0.0f, 1.0f);
PxVec3 p,n;
PxTransform t = PX_TRANSFORM_ID;
if (trans)
t = *trans;
shdfnd::Array<PxVec3> normals;
float dphi0 = PxTwoPi / (float)numSegs0;
float dphi1 = PxTwoPi / (float)numSegs1;
for (int i = 0; i < numSegs0; i++) {
nr0 = PxVec3(PxCos(i*dphi0), PxSin(i*dphi0), 0.0f);
nr1 = PxVec3(PxCos((i+1)*dphi0), PxSin((i+1)*dphi0), 0.0f);
mGeom.initConvex(c);
c.numVerts = 2*numSegs1;
normals.clear();
for (int j = 0; j < numSegs1; j++) {
p = nr0 * (r0 + r1 * PxCos(j*dphi1)) + nz * r1 * PxSin(j*dphi1);
mGeom.vertices.pushBack(t.transform(p));
n = nr0 * (PxCos(j*dphi1)) + nz * PxSin(j*dphi1);
normals.pushBack(t.rotate(n));
p = nr1 * (r0 + r1 * PxCos(j*dphi1)) + nz * r1 * PxSin(j*dphi1);
mGeom.vertices.pushBack(t.transform(p));
n = nr1 * (PxCos(j*dphi1)) + nz * PxSin(j*dphi1);
normals.pushBack(t.rotate(n));
}
c.numFaces = 2 + numSegs1;
mGeom.indices.pushBack(numSegs1); // face size
mGeom.indices.pushBack(CompoundGeometry::FF_INVISIBLE); // face flags
for (int j = 0; j < numSegs1; j++)
mGeom.indices.pushBack(2*j);
mGeom.indices.pushBack(numSegs1); // face size
mGeom.indices.pushBack(CompoundGeometry::FF_INVISIBLE); // face flags
for (int j = 0; j < numSegs1; j++) {
mGeom.indices.pushBack(2*(numSegs1-1-j) + 1);
}
for (int j = 0; j < numSegs1; j++) {
int k = (j+1)%numSegs1;
mGeom.indices.pushBack(4); // face size
mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE | CompoundGeometry::FF_HAS_NORMALS);
int i0 = 2*j;
int i1 = 2*j+1;
int i2 = 2*k+1;
int i3 = 2*k;
mGeom.indices.pushBack(i0);
mGeom.indices.pushBack(i1);
mGeom.indices.pushBack(i2);
mGeom.indices.pushBack(i3);
mGeom.normals.pushBack(normals[i0]);
mGeom.normals.pushBack(normals[i1]);
mGeom.normals.pushBack(normals[i2]);
mGeom.normals.pushBack(normals[i3]);
}
c.numNeighbors = 2;
mGeom.neighbors.pushBack((i + (numSegs0-1)) % numSegs0);
mGeom.neighbors.pushBack((i + 1) % numSegs0);
mGeom.convexes.pushBack(c);
}
}
// -----------------------------------------------------------------------------
void CompoundCreator::createCylinder(float r, float h, int numSegs, const PxTransform *trans)
{
PxTransform t = PX_TRANSFORM_ID;
if (trans)
t = *trans;
mGeom.clear();
CompoundGeometry::Convex c;
mGeom.initConvex(c);
float dphi = PxTwoPi / (float)numSegs;
c.numVerts = 2*numSegs;
mGeom.vertices.resize(c.numVerts);
for (int i = 0; i < numSegs; i++) {
PxVec3 p0(r * PxCos(i*dphi), r * PxSin(i*dphi), -0.5f * h);
PxVec3 p1(r * PxCos(i*dphi), r * PxSin(i*dphi), 0.5f * h);
mGeom.vertices[2*i] = t.transform(p0);
mGeom.vertices[2*i+1] = t.transform(p1);
}
c.numFaces = 2 + numSegs;
mGeom.indices.pushBack(numSegs);
mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE);
for (int i = 0; i < numSegs; i++)
mGeom.indices.pushBack(2*(numSegs-1-i));
mGeom.indices.pushBack(numSegs);
mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE);
for (int i = 0; i < numSegs; i++)
mGeom.indices.pushBack(2*i+1);
for (int i = 0; i < numSegs; i++) {
int j = (i+1) % numSegs;
PxVec3 n0(PxCos(i*dphi),PxSin(i*dphi),0.0f);
PxVec3 n1(PxCos(j*dphi),PxSin(j*dphi),0.0f);
n0 = t.rotate(n0);
n1 = t.rotate(n1);
//n0*=-1;
//n1*=-1;
mGeom.indices.pushBack(4);
mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE | CompoundGeometry::FF_HAS_NORMALS);
mGeom.indices.pushBack(2*i);
mGeom.indices.pushBack(2*j);
mGeom.indices.pushBack(2*j+1);
mGeom.indices.pushBack(2*i+1);
mGeom.normals.pushBack(n0);
mGeom.normals.pushBack(n1);
mGeom.normals.pushBack(n1);
mGeom.normals.pushBack(n0);
}
mGeom.convexes.pushBack(c);
}
// -----------------------------------------------------------------------------
void CompoundCreator::createBox(const PxVec3 &dims, const PxTransform *trans, bool clear)
{
PxTransform t = PX_TRANSFORM_ID;
if (trans)
t = *trans;
if (clear)
mGeom.clear();
CompoundGeometry::Convex c;
mGeom.initConvex(c);
c.numVerts = 8;
mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, -0.5f * dims.y, -0.5f * dims.z)));
mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, -0.5f * dims.y, -0.5f * dims.z)));
mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, 0.5f * dims.y, -0.5f * dims.z)));
mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, 0.5f * dims.y, -0.5f * dims.z)));
mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, -0.5f * dims.y, 0.5f * dims.z)));
mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, -0.5f * dims.y, 0.5f * dims.z)));
mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, 0.5f * dims.y, 0.5f * dims.z)));
mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, 0.5f * dims.y, 0.5f * dims.z)));
static int faceIds[6][4] = {{0,1,5,4},{1,2,6,5},{2,3,7,6},{3,0,4,7},{0,3,2,1},{4,5,6,7}};
c.numFaces = 6;
for (int i = 0; i < 6; i++) {
mGeom.indices.pushBack(4);
mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE);
for (int j = 0; j < 4; j++)
mGeom.indices.pushBack(faceIds[i][j]);
}
mGeom.convexes.pushBack(c);
}
void CompoundCreator::createFromConvexMesh(const PxConvexMeshGeometry& convexGeom, PxTransform offset, bool clear)
{
if (clear)
{
mGeom.clear();
}
CompoundGeometry::Convex c;
mGeom.initConvex(c);
PxConvexMesh* convexMesh = convexGeom.convexMesh;
c.numVerts = convexMesh->getNbVertices();
c.numFaces = convexMesh->getNbPolygons();
const PxVec3* verts = convexMesh->getVertices();
const PxU8* indexBuff = convexMesh->getIndexBuffer();
for (PxU32 a = 0; a < c.numVerts; ++a)
{
mGeom.vertices.pushBack(offset.transform(verts[a]));
}
for (PxU32 a = 0; a < c.numFaces; ++a)
{
PxHullPolygon data;
convexMesh->getPolygonData(a, data);
mGeom.indices.pushBack(data.mNbVerts);
mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE);
const PxU32 indexBase = data.mIndexBase;
for (PxU32 b = 0; b < data.mNbVerts; ++b)
{
PxU32 ind = indexBuff[indexBase + b];
mGeom.indices.pushBack(ind);
}
}
mGeom.convexes.pushBack(c);
}
// -----------------------------------------------------------------------------
void CompoundCreator::createSphere(const PxVec3 &dims, int resolution, const PxTransform *trans)
{
PxTransform t = PX_TRANSFORM_ID;
if (trans)
t = *trans;
if (resolution < 2) resolution = 2;
int numSegs0 = 2*resolution;
int numSegs1 = resolution;
float rx = 0.5f * dims.x;
float ry = 0.5f * dims.y;
float rz = 0.5f * dims.z;
mGeom.clear();
CompoundGeometry::Convex c;
mGeom.initConvex(c);
if (rx == ry && rx == rz)
{
c.isSphere = true;
c.radius = rx;
}
float dphi = PxTwoPi / (float)numSegs0;
float dteta = PxPi / (float)numSegs1;
PxVec3 p, n;
for (int i = 1; i < numSegs1; i++) {
for (int j = 0; j < numSegs0; j++) {
float phi = j * dphi;
float teta = -PxHalfPi + i * dteta;
p = PxVec3(PxCos(phi)*PxCos(teta), PxSin(phi)*PxCos(teta), PxSin(teta));
mGeom.vertices.pushBack(PxVec3(p.x * rx, p.y * ry, p.z * rz));
}
}
int bottomNr = mGeom.vertices.size();
mGeom.vertices.pushBack(PxVec3(0.0f, 0.0f, -rz));
int topNr = mGeom.vertices.size();
mGeom.vertices.pushBack(PxVec3(0.0f, 0.0f, +rz));
c.numVerts = mGeom.vertices.size();
for (int i = 0; i < numSegs1-2; i++) {
for (int j = 0; j < numSegs0; j++) {
mGeom.indices.pushBack(4); // face size
mGeom.indices.pushBack(CompoundGeometry::FF_HAS_NORMALS | CompoundGeometry::FF_OBJECT_SURFACE);
int i0 = i*numSegs0 + j;
int i1 = i*numSegs0 + (j+1)%numSegs0;
int i2 = (i+1)*numSegs0 + (j+1)%numSegs0;
int i3 = (i+1)*numSegs0 + j;
mGeom.indices.pushBack(i0);
mGeom.indices.pushBack(i1);
mGeom.indices.pushBack(i2);
mGeom.indices.pushBack(i3);
n = mGeom.vertices[i0]; n.normalize(); mGeom.normals.pushBack(n);
n = mGeom.vertices[i1]; n.normalize(); mGeom.normals.pushBack(n);
n = mGeom.vertices[i2]; n.normalize(); mGeom.normals.pushBack(n);
n = mGeom.vertices[i3]; n.normalize(); mGeom.normals.pushBack(n);
c.numFaces++;
}
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < numSegs0; j++) {
mGeom.indices.pushBack(3); // face size
mGeom.indices.pushBack(CompoundGeometry::FF_HAS_NORMALS | CompoundGeometry::FF_OBJECT_SURFACE);
int i0,i1,i2;
if (i == 0) {
i0 = j;
i1 = bottomNr;
i2 = (j+1)%numSegs0;
}
else {
i0 = (numSegs1-2)*numSegs0 + j;
i1 = (numSegs1-2)*numSegs0 + (j+1)%numSegs0;
i2 = topNr;
}
mGeom.indices.pushBack(i0);
mGeom.indices.pushBack(i1);
mGeom.indices.pushBack(i2);
n = mGeom.vertices[i0]; n.normalize(); mGeom.normals.pushBack(n);
n = mGeom.vertices[i1]; n.normalize(); mGeom.normals.pushBack(n);
n = mGeom.vertices[i2]; n.normalize(); mGeom.normals.pushBack(n);
c.numFaces++;
}
}
mGeom.convexes.pushBack(c);
}
// -----------------------------------------------------------------------------
void CompoundCreator::fromTetraMesh(const shdfnd::Array<PxVec3> &tetVerts, const shdfnd::Array<int> &tetIndices)
{
mTetVertices = tetVerts;
mTetIndices = tetIndices;
deleteColors();
computeTetNeighbors();
computeTetEdges();
colorTets();
colorsToConvexes();
}
// -----------------------------------------------------------------------------
void CompoundCreator::computeTetNeighbors()
{
int numTets = mTetIndices.size() / 4;
struct TetFace {
void init(int i0, int i1, int i2, int faceNr, int tetNr) {
if (i0 > i1) { int i = i0; i0 = i1; i1 = i; }
if (i1 > i2) { int i = i1; i1 = i2; i2 = i; }
if (i0 > i1) { int i = i0; i0 = i1; i1 = i; }
this->i0 = i0; this->i1 = i1; this->i2 = i2;
this->faceNr = faceNr; this->tetNr = tetNr;
}
bool operator < (const TetFace &f) const {
if (i0 < f.i0) return true;
if (i0 > f.i0) return false;
if (i1 < f.i1) return true;
if (i1 > f.i1) return false;
return i2 < f.i2;
}
bool operator == (const TetFace &f) const {
return i0 == f.i0 && i1 == f.i1 && i2 == f.i2;
}
int i0,i1,i2;
int faceNr, tetNr;
};
shdfnd::Array<TetFace> faces(numTets * 4);
for (int i = 0; i < numTets; i++) {
int ids[4];
ids[0] = mTetIndices[4*i];
ids[1] = mTetIndices[4*i+1];
ids[2] = mTetIndices[4*i+2];
ids[3] = mTetIndices[4*i+3];
for (int j = 0; j < 4; j++) {
int i0 = ids[tetFaceIds[j][0]];
int i1 = ids[tetFaceIds[j][1]];
int i2 = ids[tetFaceIds[j][2]];
faces[4*i+j].init(i0,i1,i2, j, i);
}
}
std::sort(faces.begin(), faces.end());
mTetNeighbors.clear();
mTetNeighbors.resize(numTets * 4, -1);
int i = 0;
while (i < (int)faces.size()) {
TetFace &f0 = faces[i];
i++;
if (i < (int)faces.size() && faces[i] == f0) {
TetFace &f1 = faces[i];
mTetNeighbors[4*f0.tetNr + f0.faceNr] = f1.tetNr;
mTetNeighbors[4*f1.tetNr + f1.faceNr] = f0.tetNr;
while (i < (int)faces.size() && faces[i] == f0)
i++;
}
}
}
// -----------------------------------------------------------------------------
void CompoundCreator::computeTetEdges()
{
int numTets = mTetIndices.size() / 4;
struct SortEdge {
void init(int i0, int i1, int edgeNr, int tetNr) {
if (i0 < i1) { this->i0 = i0; this->i1 = i1; }
else { this->i0 = i1; this->i1 = i0; }
this->edgeNr = edgeNr; this->tetNr = tetNr;
}
bool operator < (const SortEdge &e) const {
if (i0 < e.i0) return true;
if (i0 > e.i0) return false;
return i1 < e.i1;
}
bool operator == (const SortEdge &e) const {
return i0 == e.i0 && i1 == e.i1;
}
int i0,i1;
int edgeNr, tetNr;
};
shdfnd::Array<SortEdge> edges(numTets * 6);
for (int i = 0; i < numTets; i++) {
int ids[4];
ids[0] = mTetIndices[4*i];
ids[1] = mTetIndices[4*i+1];
ids[2] = mTetIndices[4*i+2];
ids[3] = mTetIndices[4*i+3];
for (int j = 0; j < 6; j++) {
int i0 = ids[tetEdgeVerts[j][0]];
int i1 = ids[tetEdgeVerts[j][1]];
edges[6*i + j].init(i0,i1, j, i);
}
}
std::sort(edges.begin(), edges.end());
mTetEdgeNrs.clear();
mTetEdgeNrs.resize(numTets * 6, -1);
mTetEdges.clear();
mEdgeTetNrs.clear();
mEdgeTetAngles.clear();
TetEdge te;
struct ChainVert {
int adjVert0;
int adjVert1;
int tet0;
int tet1;
float dihed0;
float dihed1;
int mark;
};
ChainVert cv;
cv.mark = 0;
shdfnd::Array<ChainVert> chainVerts(mTetVertices.size(), cv);
shdfnd::Array<int> chainVertNrs;
int mark = 1;
int i = 0;
while (i < (int)edges.size()) {
SortEdge &e0 = edges[i];
int edgeNr = mTetEdges.size();
te.init(e0.i0, e0.i1);
te.firstTet = mEdgeTetNrs.size();
te.numTets = 0;
mark++;
chainVertNrs.clear();
do {
SortEdge &e = edges[i];
mTetEdgeNrs[6 * e.tetNr + e.edgeNr] = edgeNr;
int i2 = -1;
int i3 = -1;
for (int j = 0; j < 4; j++) {
int id = mTetIndices[4 * e.tetNr + j];
if (id != e0.i0 && id != e0.i1) {
if (i2 < 0) i2 = id;
else i3 = id;
}
}
PX_ASSERT(i2 >= 0 && i3 >= 0);
// dihedral angle at edge
PxVec3 &p0 = mTetVertices[e0.i0];
PxVec3 &p1 = mTetVertices[e0.i1];
PxVec3 &p2 = mTetVertices[i2];
PxVec3 &p3 = mTetVertices[i3];
PxVec3 n2 = (p1-p0).cross(p2-p0); n2.normalize();
if ((p3-p0).dot(n2) > 0.0f) n2 = -n2;
PxVec3 n3 = (p1-p0).cross(p3-p0); n3.normalize();
if ((p2-p0).dot(n3) > 0.0f) n3 = -n3;
float dot = n2.dot(n3);
float dihed = PxPi - PxAcos(dot);
// chain for ordering tets of edge correctly
ChainVert &cv2 = chainVerts[i2];
ChainVert &cv3 = chainVerts[i3];
if (cv2.mark != mark) { cv2.adjVert0 = -1; cv2.adjVert1 = -1; cv2.mark = mark; }
if (cv3.mark != mark) { cv3.adjVert0 = -1; cv3.adjVert1 = -1; cv3.mark = mark; }
if (cv2.adjVert0 < 0) { cv2.adjVert0 = i3; cv2.tet0 = e.tetNr; cv2.dihed0 = dihed; }
else { cv2.adjVert1 = i3; cv2.tet1 = e.tetNr; cv2.dihed1 = dihed; }
if (cv3.adjVert0 < 0) { cv3.adjVert0 = i2; cv3.tet0 = e.tetNr; cv3.dihed0 = dihed; }
else { cv3.adjVert1 = i2; cv3.tet1 = e.tetNr; cv3.dihed1 = dihed; }
chainVertNrs.pushBack(i2);
chainVertNrs.pushBack(i3);
i++;
}
while (i < (int)edges.size() && edges[i] == e0);
te.numTets = chainVertNrs.size() / 2;
// find chain start;
int startVertNr = -1;
for (int j = 0; j < (int)chainVertNrs.size(); j++) {
ChainVert &cv = chainVerts[chainVertNrs[j]];
if (cv.adjVert0 < 0 || cv.adjVert1 < 0) {
startVertNr = chainVertNrs[j];
break;
}
}
te.onSurface = startVertNr >= 0;
mTetEdges.pushBack(te);
int curr = startVertNr;
if (curr < 0) curr = chainVertNrs[0];
int prev = -1;
// collect adjacent tetrahedra
for (int j = 0; j < te.numTets; j++) {
ChainVert &cv = chainVerts[curr];
int next;
if (cv.adjVert0 == prev) {
next = cv.adjVert1;
mEdgeTetNrs.pushBack(cv.tet1);
mEdgeTetAngles.pushBack(cv.dihed1);
}
else {
next = cv.adjVert0;
mEdgeTetNrs.pushBack(cv.tet0);
mEdgeTetAngles.pushBack(cv.dihed0);
}
prev = curr;
curr = next;
}
}
}
// -----------------------------------------------------------------------------
bool CompoundCreator::tetHasColor(int tetNr, int color)
{
int nr = mTetFirstColor[tetNr];
while (nr >= 0) {
if (mTetColors[nr].color == color)
return true;
nr = mTetColors[nr].next;
}
return false;
}
// -----------------------------------------------------------------------------
bool CompoundCreator::tetAddColor(int tetNr, int color)
{
if (tetHasColor(tetNr, color))
return false;
Color c;
c.color = color;
c.next = mTetFirstColor[tetNr];
if (mTetColorsFirstEmpty <= 0) { // new entry
mTetFirstColor[tetNr] = mTetColors.size();
mTetColors.pushBack(c);
}
else { // take from empty list
int newNr = mTetColorsFirstEmpty;
mTetFirstColor[tetNr] = newNr;
mTetColorsFirstEmpty = mTetColors[newNr].next;
mTetColors[newNr] = c;
}
return true;
}
// -----------------------------------------------------------------------------
bool CompoundCreator::tetRemoveColor(int tetNr, int color)
{
int nr = mTetFirstColor[tetNr];
int prev = -1;
while (nr >= 0) {
if (mTetColors[nr].color == color) {
if (prev < 0)
mTetFirstColor[tetNr] = mTetColors[nr].next;
else
mTetColors[prev].next = mTetColors[nr].next;
// add to empty list
mTetColors[nr].next = mTetColorsFirstEmpty;
mTetColorsFirstEmpty = nr;
return true;
}
prev = nr;
nr = mTetColors[nr].next;
}
return false;
}
// -----------------------------------------------------------------------------
int CompoundCreator::tetNumColors(int tetNr)
{
int num = 0;
int nr = mTetFirstColor[tetNr];
while (nr >= 0) {
num++;
nr = mTetColors[nr].next;
}
return num;
}
// -----------------------------------------------------------------------------
void CompoundCreator::deleteColors()
{
mTetFirstColor.resize(mTetIndices.size()/4, -1);
mTetColors.clear();
mTetColorsFirstEmpty = -1;
}
// -----------------------------------------------------------------------------
bool CompoundCreator::tryTet(int tetNr, int color)
{
if (tetNr < 0)
return false;
//if (mTetColors[tetNr] >= 0)
// return false;
if (tetHasColor(tetNr, color))
return false;
mTestEdges.clear();
mAddedTets.clear();
tetAddColor(tetNr, color);
mAddedTets.pushBack(tetNr);
for (int i = 0; i < 6; i++)
mTestEdges.pushBack(mTetEdgeNrs[6*tetNr+i]);
bool failed = false;
while (mTestEdges.size() > 0) {
int edgeNr = mTestEdges[mTestEdges.size()-1];
mTestEdges.popBack();
TetEdge &e = mTetEdges[edgeNr];
bool anyOtherCol = false;
float sumAng = 0.0f;
for (int i = 0; i < e.numTets; i++) {
int edgeTetNr = mEdgeTetNrs[e.firstTet + i];
if (tetHasColor(edgeTetNr, color))
sumAng += mEdgeTetAngles[e.firstTet + i];
else if (tetNumColors(edgeTetNr) > 0)
anyOtherCol = true;
}
if (sumAng < CONVEX_THRESHOLD)
continue;
// if (e.onSurface || anyOtherCol) {
if (e.onSurface) {
failed = true;
break;
}
for (int i = 0; i < e.numTets; i++) {
int edgeTetNr = mEdgeTetNrs[e.firstTet + i];
if (!tetHasColor(edgeTetNr, color)) {
tetAddColor(edgeTetNr, color);
mAddedTets.pushBack(edgeTetNr);
for (int j = 0; j < 6; j++)
mTestEdges.pushBack(mTetEdgeNrs[6*edgeTetNr+j]);
}
}
}
if (failed) {
for (int i = 0; i < (int)mAddedTets.size(); i++)
tetRemoveColor(mAddedTets[i], color);
mAddedTets.clear();
return false;
}
return true;
}
// -----------------------------------------------------------------------------
void CompoundCreator::colorTets()
{
int numTets = mTetIndices.size() / 4;
deleteColors();
int color = 0;
shdfnd::Array<int> edges;
shdfnd::Array<int> faces;
for (int i = 0; i < numTets; i++) {
if (tetNumColors(i) > 0)
continue;
tetAddColor(i, color);
faces.clear();
faces.pushBack(4*i);
faces.pushBack(4*i+1);
faces.pushBack(4*i+2);
faces.pushBack(4*i+3);
while (faces.size() > 0) {
int faceNr = faces[faces.size()-1];
faces.popBack();
int adjTetNr = mTetNeighbors[faceNr];
if (adjTetNr < 0)
continue;
//if (tetNumColors(adjTetNr) > 0)
// continue;
if (!tryTet(adjTetNr, color))
continue;
for (int j = 0; j < (int)mAddedTets.size(); j++) {
int addedTet = mAddedTets[j];
for (int k = 0; k < 4; k++) {
int adj = mTetNeighbors[4*addedTet+k];
if (adj >= 0 && !tetHasColor(adj, color))
faces.pushBack(4*addedTet+k);
}
}
}
color++;
}
}
// -----------------------------------------------------------------------------
void CompoundCreator::colorsToConvexes()
{
mGeom.clear();
int numTets = mTetIndices.size() / 4;
int numColors = 0;
for (int i = 0; i < (int)mTetColors.size(); i++) {
int color = mTetColors[i].color;
if (color >= numColors)
numColors = color+1;
}
shdfnd::Array<bool> colorVisited(numColors, false);
shdfnd::Array<int> queue;
shdfnd::Array<int> globalToLocal(mTetVertices.size(), -1);
shdfnd::Array<int> tetMarks(numTets, 0);
shdfnd::Array<int> vertMarks(mTetVertices.size(), 0);
int mark = 1;
shdfnd::Array<int> colorToConvexNr;
CompoundGeometry::Convex c;
for (int i = 0; i < numTets; i++) {
int nr = mTetFirstColor[i];
while (nr >= 0) {
int color = mTetColors[nr].color;
nr = mTetColors[nr].next;
if (colorVisited[color])
continue;
colorVisited[color] = true;
if ((int)colorToConvexNr.size() <= color)
colorToConvexNr.resize(color+1, -1);
colorToConvexNr[color] = mGeom.convexes.size();
queue.clear();
queue.pushBack(i);
mGeom.initConvex(c);
mark++;
c.numVerts = 0;
// flood fill
while (!queue.empty()) {
int tetNr = queue[queue.size()-1];
queue.popBack();
if (tetMarks[tetNr] == mark)
continue;
tetMarks[tetNr] = mark;
for (int j = 0; j < 4; j++) {
int adjNr = mTetNeighbors[4*tetNr + j];
if (adjNr < 0 || !tetHasColor(adjNr, color)) {
// create new face
mGeom.indices.pushBack(3); // face size
int flags = 0;
if (adjNr < 0) flags |= CompoundGeometry::FF_OBJECT_SURFACE;
mGeom.indices.pushBack(flags);
for (int k = 0; k < 3; k++) {
int id = mTetIndices[4*tetNr + tetFaceIds[j][k]];
if (vertMarks[id] != mark) {
vertMarks[id] = mark;
globalToLocal[id] = c.numVerts;
c.numVerts++;
mGeom.vertices.pushBack(mTetVertices[id]);
}
mGeom.indices.pushBack(globalToLocal[id]);
}
c.numFaces++;
}
if (adjNr >= 0) {
// add neighbors
int colNr = mTetFirstColor[adjNr];
while (colNr >= 0) {
int adjColor = mTetColors[colNr].color;
colNr = mTetColors[colNr].next;
if (adjColor != color) {
bool isNew = true;
for (int k = 0; k < c.numNeighbors; k++) {
if (mGeom.neighbors[c.firstNeighbor+k] == adjColor) {
isNew = false;
break;
}
}
if (isNew) {
mGeom.neighbors.pushBack(adjColor);
c.numNeighbors++;
}
}
}
}
if (adjNr < 0 || !tetHasColor(adjNr, color) || tetMarks[adjNr] == mark)
continue;
queue.pushBack(adjNr);
}
}
mGeom.convexes.pushBack(c);
}
}
for (int i = 0; i < (int)mGeom.neighbors.size(); i++) {
if (mGeom.neighbors[i] >= 0)
mGeom.neighbors[i] = colorToConvexNr[mGeom.neighbors[i]];
}
}
}
}
}
#endif

View File

@ -0,0 +1,130 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef COMPOUND_CREATOR_BASE_H
#define COMPOUND_CREATOR_BASE_H
// Matthias Mueller-Fischer
#include <foundation/PxVec3.h>
#include <foundation/PxTransform.h>
#include <PsArray.h>
#include <PsUserAllocated.h>
#include "CompoundGeometryBase.h"
namespace physx
{
class PxConvexMeshGeometry;
namespace fracture
{
namespace base
{
class SimScene;
// ---------------------------------------------------------------------------------------
class CompoundCreator : public ::physx::shdfnd::UserAllocated {
friend class SimScene;
public:
// direct
void createTorus(float r0, float r1, int numSegs0, int numSegs1, const PxTransform *trans = NULL);
void createCylinder(float r, float h, int numSegs, const PxTransform *trans = NULL);
void createBox(const PxVec3 &dims, const PxTransform *trans = NULL, bool clearShape = true);
void createSphere(const PxVec3 &dims, int resolution = 5, const PxTransform *trans = NULL);
void fromTetraMesh(const shdfnd::Array<PxVec3> &tetVerts, const shdfnd::Array<int> &tetIndices);
void createFromConvexMesh(const PxConvexMeshGeometry& convexGeom, PxTransform offset = PxTransform(PxIdentity), bool clear = true);
const CompoundGeometry &getGeometry() { return mGeom; }
virtual void debugDraw() {}
protected:
CompoundCreator(SimScene* scene): mScene(scene) {}
virtual ~CompoundCreator() {}
SimScene* mScene;
static int tetFaceIds[4][3];
static int tetEdgeVerts[6][2];
static int tetFaceEdges[4][3];
void computeTetNeighbors();
void computeTetEdges();
void colorTets();
void colorsToConvexes();
bool tetHasColor(int tetNr, int color);
bool tetAddColor(int tetNr, int color);
bool tetRemoveColor(int tetNr, int color);
int tetNumColors(int tetNr);
void deleteColors();
bool tryTet(int tetNr, int color);
// from tet mesh
shdfnd::Array<PxVec3> mTetVertices;
shdfnd::Array<int> mTetIndices;
shdfnd::Array<int> mTetNeighbors;
shdfnd::Array<int> mTetFirstColor;
struct Color {
int color;
int next;
};
int mTetColorsFirstEmpty;
shdfnd::Array<Color> mTetColors;
struct TetEdge {
void init(int i0, int i1) { this->i0 = i0; this->i1 = i1; firstTet = 0; numTets = 0; onSurface = false; }
int i0, i1;
int firstTet, numTets;
bool onSurface;
};
shdfnd::Array<TetEdge> mTetEdges;
shdfnd::Array<int> mTetEdgeNrs;
shdfnd::Array<int> mEdgeTetNrs;
shdfnd::Array<float> mEdgeTetAngles;
shdfnd::Array<int> mAddedTets;
shdfnd::Array<int> mTestEdges;
// input
shdfnd::Array<PxVec3> mVertices;
shdfnd::Array<int> mIndices;
// output
CompoundGeometry mGeom;
};
}}}
#endif
#endif

View File

@ -0,0 +1,113 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#include "CompoundGeometryBase.h"
namespace physx
{
namespace fracture
{
namespace base
{
// -------------------------------------------------------------------------------
void CompoundGeometry::clear()
{
convexes.clear();
vertices.clear();;
normals.clear();
indices.clear();
neighbors.clear();
planes.clear();
}
// -------------------------------------------------------------------------------
bool CompoundGeometry::loadFromFile(const char * /*filename*/)
{
return true;
}
// -------------------------------------------------------------------------------
bool CompoundGeometry::saveFromFile(const char * /*filename*/)
{
return true;
}
// -------------------------------------------------------------------------------
void CompoundGeometry::initConvex(Convex &c)
{
c.firstVert = vertices.size();
c.numVerts = 0;
c.firstNormal = normals.size();
c.firstIndex = indices.size();
c.numFaces = 0;
c.firstPlane = 0;
c.firstNeighbor = neighbors.size();
c.numNeighbors = 0;
c.radius = 0.f;
c.isSphere = false;
}
// -------------------------------------------------------------------------------
void CompoundGeometry::derivePlanes()
{
planes.clear();
PxPlane p;
for (int i = 0; i < (int)convexes.size(); i++) {
Convex &c = convexes[i];
c.firstPlane = planes.size();
int *ids = &indices[c.firstIndex];
PxVec3 *verts = &vertices[c.firstVert];
for (int j = 0; j < c.numFaces; j++) {
int num = *ids++;
*ids++; //int flags = *ids++;
if (num < 3)
p = PxPlane(1.0f, 0.0f, 0.0f, 0.0f);
else {
p.n = PxVec3(0.0f, 0.0f, 0.0f);
for (int k = 1; k < num-1; k++) {
const PxVec3 &p0 = verts[ids[0]];
const PxVec3 &p1 = verts[ids[k]];
const PxVec3 &p2 = verts[ids[k+1]];
p.n += (p1-p0).cross(p2-p1);
}
p.n.normalize();
p.d = p.n.dot(verts[ids[0]]);
}
planes.pushBack(p);
ids += num;
}
}
}
}
}
}
#endif

View File

@ -0,0 +1,95 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef COMPOUND_GEOMETRY_BASE
#define COMPOUND_GEOMETRY_BASE
#include <foundation/PxVec3.h>
#include <foundation/PxPlane.h>
#include <PsArray.h>
#include <PsUserAllocated.h>
namespace physx
{
namespace fracture
{
namespace base
{
// -----------------------------------------------------------------------------------
class CompoundGeometry : public ::physx::shdfnd::UserAllocated
{
public:
CompoundGeometry() {}
virtual ~CompoundGeometry() {}
bool loadFromFile(const char *filename);
bool saveFromFile(const char *filename);
void clear();
void derivePlanes();
virtual void debugDraw(int /*maxConvexes*/ = 0) const {}
struct Convex { // init using CompoundGeometry::initConvex()
int firstVert;
int numVerts;
int firstNormal; // one per face index! If not provided (see face flags) face normal is used
int firstIndex;
int numFaces;
int firstPlane;
int firstNeighbor;
int numNeighbors;
float radius;
bool isSphere;
};
void initConvex(Convex &c);
shdfnd::Array<Convex> convexes;
shdfnd::Array<PxVec3> vertices;
shdfnd::Array<PxVec3> normals; // one per face and vertex!
// face size, face flags, id, id, .., face size, face flags, id ..
shdfnd::Array<int> indices;
shdfnd::Array<int> neighbors;
shdfnd::Array<PxPlane> planes; // derived for faster cuts
enum FaceFlags {
FF_OBJECT_SURFACE = 1,
FF_HAS_NORMALS = 2,
FF_INVISIBLE = 4,
FF_NEW = 8,
};
};
}
}
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,239 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef CONVEX_BASE
#define CONVEX_BASE
#include <PxPhysics.h>
#include <PxCooking.h>
#include <foundation/PxVec3.h>
#include <foundation/PxPlane.h>
#include <foundation/PxBounds3.h>
#include <foundation/PxTransform.h>
#include <PsArray.h>
#include <PsUserAllocated.h>
namespace physx
{
namespace fracture
{
namespace base
{
class physx::PxShape;
class physx::PxActor;
class physx::PxScene;
class physx::PxConvexMesh;
class Compound;
class CompoundGeometry;
class SimScene;
// ----------------------------------------------------------------------------
class Convex : public ::physx::shdfnd::UserAllocated
{
friend class SimScene;
protected:
Convex(SimScene* scene);
public:
virtual ~Convex();
void createFromConvex(const Convex *convex, const PxTransform *trans = NULL, int matID = 0, int surfMatID = 0);
void createFromGeometry(const CompoundGeometry &geom, int convexNr, const PxMat44 *trans = NULL, int matID = 0, int surfMatID = 0);
void transform(const PxMat44 &trans);
PxVec3 centerAtZero();
PxVec3 getCenter() const;
void setTexScale(float texScale) { mTexScale = texScale; }
void increaseRefCounter() { mRefCounter++; }
int decreaseRefCounter() { mRefCounter--; return mRefCounter; }
bool rayCast(const PxVec3 &ray, const PxVec3 &dir, float &dist, PxVec3 &normal) const;
bool collide(const PxVec3 &pos, float r, float &penetration, PxVec3 &surfaceNormal, PxVec3 &surfaceVel) const;
void intersectWithConvex(const PxPlane *planes, int numPlanes, const PxMat44 &trans, bool &empty);
virtual void draw(bool /*debug*/ = false) {}
PxConvexMesh* createPxConvexMesh(Compound *parent, PxPhysics *pxPhysics, PxCooking *pxCooking);
void setPxActor(PxRigidActor *actor);
void setLocalPose(const PxTransform &pose);
// accessors
Compound *getParent() { return mParent; }
const Compound *getParent() const { return mParent; }
const PxConvexMesh *getPxConvexMesh() const { return mPxConvexMesh; }
PxConvexMesh *getPxConvexMesh() { return mPxConvexMesh; }
const shdfnd::Array<PxPlane> &getPlanes() const { return mPlanes; };
const PxBounds3 &getBounds() const { return mBounds; }
void getWorldBounds(PxBounds3 &bounds) const;
void getLocalBounds(PxBounds3 &bounds) const;
float getVolume() const;
void removeInvisibleFacesFlags();
void updateFaceVisibility(const float *faceCoverage);
void clearFraceFlags(unsigned int flag);
struct Face {
void init() {
firstIndex = 0; numIndices = 0; flags = 0; firstNormal = 0;
}
int firstIndex;
int numIndices;
int flags;
int firstNormal;
};
const shdfnd::Array<Face> &getFaces() const { return mFaces; }
const shdfnd::Array<int> &getIndices() const { return mIndices; }
const shdfnd::Array<PxVec3> &getVertices() const { return mVertices; }
const shdfnd::Array<PxVec3> &getVisVertices() const { return mVisVertices; }
const shdfnd::Array<PxVec3> &getVisNormals() const { return mVisNormals; }
const shdfnd::Array<PxVec3> &getVisTangents() const { return mVisTangents; }
const shdfnd::Array<float> &getVisTexCoords() const { return mVisTexCoords; }
const shdfnd::Array<int> &getVisTriIndices() const { return mVisTriIndices; }
const shdfnd::Array<int> &getVisPolyStarts() const { return mVisPolyStarts; }
const shdfnd::Array<int> &getVisPolyIndices() const { return mVisPolyIndices; }
const shdfnd::Array<int> &getVisPolyNeighbors() const { return mVisPolyNeighbors; }
PxVec3 getMaterialOffset() const { return mMaterialOffset; }
void setMaterialOffset(const PxVec3 &offset);
PxTransform getGlobalPose() const;
PxTransform getLocalPose() const;
bool isGhostConvex() const { return mIsGhostConvex; }
// explicit visual mesh
bool hasExplicitVisMesh() const { return mHasExplicitVisMesh; }
bool setExplicitVisMeshFromTriangles(int numVertices, const PxVec3 *vertices, const PxVec3 *normals, const PxVec2 *texcoords,
int numIndices, const PxU32 *indices, PxTransform *trans = NULL, const PxVec3* scale = NULL);
bool setExplicitVisMeshFromPolygons(int numVertices, const PxVec3 *vertices, const PxVec3 *normals,
const PxVec3 *tangents, const float *texCoords,
int numPolygons, const int *polyStarts, // numPolygons+1 entries
int numIndices, const int *indices, PxTransform *trans = NULL, const PxVec3* scale = NULL);
void createVisTrisFromPolys();
void createVisMeshFromConvex();
void transformVisualMesh(const PxTransform &trans);
bool insideVisualMesh(const PxVec3 &pos) const;
void fitToVisualMesh(bool &cutEmpty, int numFitDirections = 3);
bool isOnConvexSurface(const PxVec3 pts) const;
bool check();
PxActor* getActor();
bool insideFattened(const PxVec3 &pos, float r) const;
bool use2dTexture() const { return mUse2dTexture; }
bool isIndestructible() const { return mIndestructible; }
int getMaterialId() const { return mMaterialId; }
int getSurfaceMaterialId() const { return mSurfaceMaterialId; }
void setSurfaceMaterialId(int id) { mSurfaceMaterialId = id; }
void setModelIslandNr(int nr) { mModelIslandNr = nr; }
int getModelIslandNr() const { return mModelIslandNr; }
void setConvexRendererInfo(int groupNr, int groupPos) const { mConvexRendererGroupNr = groupNr; mConvexRendererGroupPos = groupPos; }
int getConvexRendererGroupNr() const { return mConvexRendererGroupNr; }
int getConvexRendererGroupPos() const { return mConvexRendererGroupPos; }
void setIsFarConvex(bool v) { mIsFarConvex = v; }
bool getIsFarConvex() { return mIsFarConvex; }
protected:
void clear();
void finalize();
void updateBounds();
void updatePlanes();
bool computeVisMeshNeighbors();
void computeVisTangentsFromPoly();
bool cutVisMesh(const PxVec3 &localPlaneN, float localPlaneD, bool &cutEmpty);
bool cut(const PxVec3 &localPlaneN, float localPlaneD, bool &cutEmpty, bool setNewFaceFlag = true);
bool rayCastConvex(const PxVec3 &orig, const PxVec3 &dir, float &dist, PxVec3 &normal) const;
bool rayCastVisMesh(const PxVec3 &orig, const PxVec3 &dir, float &dist, PxVec3 &normal) const;
SimScene* mScene;
shdfnd::Array<Face> mFaces;
shdfnd::Array<int> mIndices;
shdfnd::Array<PxVec3> mVertices;
shdfnd::Array<PxVec3> mNormals;
shdfnd::Array<PxPlane> mPlanes;
shdfnd::Array<PxVec3> mVisVertices;
shdfnd::Array<PxVec3> mVisNormals;
shdfnd::Array<PxVec3> mVisTangents;
shdfnd::Array<float> mVisTexCoords;
shdfnd::Array<int> mVisTriIndices;
int mRefCounter;
bool mHasExplicitVisMesh;
bool mIsGhostConvex;
shdfnd::Array<int> mVisPolyStarts; // for explicit mesh only
shdfnd::Array<int> mVisPolyIndices;
shdfnd::Array<int> mVisPolyNeighbors;
Convex *mNewConvex; // temporary buffer for cut operations
Compound *mParent;
PxRigidActor *mPxActor;
PxTransform mLocalPose;
PxConvexMesh *mPxConvexMesh;
PxBounds3 mBounds;
mutable float mVolume;
mutable bool mVolumeDirty;
PxVec3 mMaterialOffset;
float mTexScale;
int mModelIslandNr;
// material
bool mUse2dTexture;
bool mIndestructible;
int mMaterialId;
int mSurfaceMaterialId;
bool mIsFarConvex;
mutable int mConvexRendererGroupNr;
mutable int mConvexRendererGroupPos;
};
}
}
}
#endif
#endif

View File

@ -0,0 +1,239 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#include <foundation/PxBounds3.h>
#include "MeshBase.h"
#include <algorithm>
namespace physx
{
namespace fracture
{
namespace base
{
// ----------------------------------------------------------------------
void Mesh::updateNormals()
{
if (mVertices.empty())
return;
PxVec3 zero(0.0f, 0.0f, 0.0f);
mNormals.resize(mVertices.size());
for (int i = 0; i < (int)mNormals.size(); i++)
mNormals[i] = zero;
PxVec3 n;
PxU32 *idx = &mIndices[0];
int numTriangles = mIndices.size() / 3;
for (int i = 0; i < numTriangles; i++) {
PxU32 i0 = *idx++;
PxU32 i1 = *idx++;
PxU32 i2 = *idx++;
n = (mVertices[i1] - mVertices[i0]).cross(mVertices[i2] - mVertices[i0]);
mNormals[i0] += n;
mNormals[i1] += n;
mNormals[i2] += n;
}
for (int i = 0; i < (int)mNormals.size(); i++) {
if (!mNormals[i].isZero())
mNormals[i].normalize();
}
}
// ------------------------------------------------------------------------------
void Mesh::getBounds(PxBounds3 &bounds, int subMeshNr) const
{
bounds.setEmpty();
if (subMeshNr < 0 || subMeshNr >= (int)mSubMeshes.size()) {
for (int i = 0; i < (int)mVertices.size(); i++)
bounds.include(mVertices[i]);
}
else {
const SubMesh &sm = mSubMeshes[subMeshNr];
for (int i = 0; i < sm.numIndices; i++) {
bounds.include(mVertices[mIndices[sm.firstIndex + i]]);
}
}
}
// ------------------------------------------------------------------------------
void Mesh::normalize(const PxVec3 &center, float diagonal)
{
if (mVertices.size() < 3)
return;
PxBounds3 bounds;
getBounds(bounds);
float s = diagonal / bounds.getDimensions().magnitude();
PxVec3 c = 0.5f * (bounds.minimum + bounds.maximum);
for (int i = 0; i < (int)mVertices.size(); i++)
mVertices[i] = center + (mVertices[i] - c) * s;
}
// ------------------------------------------------------------------------------
void Mesh::scale(float diagonal)
{
if (mVertices.size() < 3)
return;
PxBounds3 bounds;
getBounds(bounds);
float s = diagonal / bounds.getDimensions().magnitude();
for (int i = 0; i < (int)mVertices.size(); i++)
mVertices[i] *= s;
}
// --------------------------------------------------------------------------------------------
struct IdEdge {
void set(PxU32 &i0, PxU32 &i1, int faceNr, int edgeNr) {
if (i0 < i1) { this->i0 = i0; this->i1 = i1; }
else { this->i0 = i1; this->i1 = i0; }
this->faceNr = faceNr; this->edgeNr = edgeNr;
}
bool operator < (const IdEdge &e) const {
if (i0 < e.i0) return true;
if (i0 == e.i0 && i1 < e.i1) return true;
return false;
}
bool operator == (const IdEdge &e) const { return i0 == e.i0 && i1 == e.i1; }
PxU32 i0,i1;
int faceNr, edgeNr;
};
// ------------------------------------------------------------------------------
bool Mesh::computeNeighbors()
{
int numTris = mIndices.size() / 3;
shdfnd::Array<IdEdge> edges(3*numTris);
for (int i = 0; i < numTris; i++) {
for (int j = 0; j < 3; j++)
edges[3*i+j].set(mIndices[3*i+j], mIndices[3*i + (j+1)%3], i, j);
}
std::sort(edges.begin(), edges.end());
mNeighbors.clear();
mNeighbors.resize(mIndices.size(), -1);
bool manifold = true;
int i = 0;
while (i < (int)edges.size()) {
IdEdge &e0 = edges[i];
i++;
if (i < (int)edges.size() && edges[i] == e0) {
IdEdge &e1 = edges[i];
mNeighbors[3* e0.faceNr + e0.edgeNr] = e1.faceNr;
mNeighbors[3* e1.faceNr + e1.edgeNr] = e0.faceNr;
i++;
}
while (i < (int)edges.size() && edges[i] == e0) {
manifold = false;
i++;
}
}
return manifold;
}
// --------------------------------------------------------------------------------------------
struct PosEdge {
// not using indices for edge match but positions
// so duplicated vertices are handled as one vertex
static bool smaller(const PxVec3 &v0, const PxVec3 &v1) {
if (v0.x < v1.x) return true;
if (v0.x > v1.x) return false;
if (v0.y < v1.y) return true;
if (v0.y > v1.y) return false;
return (v0.z < v1.z);
}
void set(const PxVec3 &v0, const PxVec3 &v1, int faceNr, int edgeNr) {
if (smaller(v0,v1)) { this->v0 = v0; this->v1 = v1; }
else { this->v0 = v1; this->v1 = v0; }
this->faceNr = faceNr; this->edgeNr = edgeNr;
}
bool operator < (const PosEdge &e) const {
if (smaller(v0, e.v0)) return true;
if (v0 == e.v0 && smaller(v1, e.v1)) return true;
return false;
}
bool operator == (const PosEdge &e) const { return v0 == e.v0 && v1 == e.v1; }
PxVec3 v0,v1;
int faceNr, edgeNr;
};
// ------------------------------------------------------------------------------
bool Mesh::computeWeldedNeighbors()
{
int numTris = mIndices.size() / 3;
shdfnd::Array<PosEdge> edges(3*numTris);
for (int i = 0; i < numTris; i++) {
for (int j = 0; j < 3; j++)
edges[3*i+j].set(mVertices[mIndices[3*i+j]], mVertices[mIndices[3*i + (j+1)%3]], i, j);
}
std::sort(edges.begin(), edges.end());
mNeighbors.clear();
mNeighbors.resize(mIndices.size(), -1);
bool manifold = true;
int i = 0;
while (i < (int)edges.size()) {
PosEdge &e0 = edges[i];
i++;
if (i < (int)edges.size() && edges[i] == e0) {
PosEdge &e1 = edges[i];
mNeighbors[3* e0.faceNr + e0.edgeNr] = e1.faceNr;
mNeighbors[3* e1.faceNr + e1.edgeNr] = e0.faceNr;
i++;
}
while (i < (int)edges.size() && edges[i] == e0) {
manifold = false;
i++;
}
}
return manifold;
}
void Mesh::flipV()
{
for(PxU32 i = 0; i < mTexCoords.size(); i++)
{
mTexCoords[i].y = 1.0f - mTexCoords[i].y;
}
}
}
}
}
#endif

View File

@ -0,0 +1,94 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef MESH_BASE
#define MESH_BASE
#include <foundation/PxVec3.h>
#include <foundation/PxVec2.h>
#include <PsArray.h>
#include <PsUserAllocated.h>
namespace physx
{
namespace fracture
{
namespace base
{
// -----------------------------------------------------------------------------------
class Mesh : public ::physx::shdfnd::UserAllocated
{
public:
Mesh() {};
virtual ~Mesh() {};
const shdfnd::Array<PxVec3> &getVertices() const { return mVertices; }
const shdfnd::Array<PxVec3> &getNormals() const { return mNormals; }
const shdfnd::Array<PxVec2> &getTexCoords() const { return mTexCoords; }
const shdfnd::Array<PxU32> &getIndices() const { return mIndices; }
const shdfnd::Array<int> &getNeighbors() const { return mNeighbors; }
struct SubMesh {
void init() { /*name = "";*/ firstIndex = -1; numIndices = 0; }
//std::string name;
int firstIndex;
int numIndices;
};
const shdfnd::Array<SubMesh> &getSubMeshes() const { return mSubMeshes; }
void normalize(const PxVec3 &center, float diagonal);
void scale(float diagonal);
void getBounds(PxBounds3 &bounds, int subMeshNr = -1) const;
void flipV(); // flips v values to hand coordinate system change (Assumes normalized coordinates)
bool computeNeighbors();
bool computeWeldedNeighbors();
protected:
void clear();
void updateNormals();
shdfnd::Array<PxVec3> mVertices;
shdfnd::Array<PxVec3> mNormals;
shdfnd::Array<PxVec2> mTexCoords;
shdfnd::Array<SubMesh> mSubMeshes;
shdfnd::Array<PxU32> mIndices;
shdfnd::Array<int> mNeighbors;
};
}
}
}
#endif
#endif

View File

@ -0,0 +1,299 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#include "PolygonTriangulatorBase.h"
#include <foundation/PxAssert.h>
namespace physx
{
namespace fracture
{
namespace base
{
// ------ singleton pattern -----------------------------------------------------------
//static PolygonTriangulator *gPolygonTriangulator = NULL;
//
//PolygonTriangulator* PolygonTriangulator::getInstance()
//{
// if (gPolygonTriangulator == NULL) {
// gPolygonTriangulator = PX_NEW(PolygonTriangulator)();
// }
// return gPolygonTriangulator;
//}
//
//void PolygonTriangulator::destroyInstance()
//{
// if (gPolygonTriangulator != NULL) {
// PX_DELETE(gPolygonTriangulator);
// }
// gPolygonTriangulator = NULL;
//}
// -------------------------------------------------------------------------------------
PolygonTriangulator::PolygonTriangulator(SimScene* scene):
mScene(scene)
{
}
// -------------------------------------------------------------------------------------
PolygonTriangulator::~PolygonTriangulator()
{
}
// -------------------------------------------------------------------------------------
float PolygonTriangulator::cross(const PxVec3 &p0, const PxVec3 &p1)
{
return p0.x * p1.y - p0.y * p1.x;
}
// -------------------------------------------------------------------------------------
bool PolygonTriangulator::inTriangle(const PxVec3 &p, const PxVec3 &p0, const PxVec3 &p1, const PxVec3 &p2)
{
float d0 = cross(p1 - p0, p - p0);
float d1 = cross(p2 - p1, p - p1);
float d2 = cross(p0 - p2, p - p2);
return (d0 >= 0.0f && d1 >= 0.0f && d2 >= 0.0f) ||
(d0 <= 0.0f && d1 <= 0.0f && d2 <= 0.0f);
}
// -------------------------------------------------------------------------------------
void PolygonTriangulator::triangulate(const PxVec3 *points, int numPoints, const int *indices, PxVec3 *planeNormal)
{
mIndices.clear();
if (numPoints < 3)
return;
if (numPoints == 3) {
if (indices == NULL) {
mIndices.pushBack(0);
mIndices.pushBack(1);
mIndices.pushBack(2);
}
else {
mIndices.pushBack(indices[0]);
mIndices.pushBack(indices[1]);
mIndices.pushBack(indices[2]);
}
return;
}
bool isConvex;
importPoints(points, numPoints, indices, planeNormal, isConvex);
if (isConvex) { // fast path
mIndices.resize(3*(numPoints-2));
for (int i = 0; i < numPoints-2; i++) {
mIndices[3*i] = 0;
mIndices[3*i+1] = i+1;
mIndices[3*i+2] = i+2;
}
}
else
clipEars();
if (indices != NULL) {
for (int i = 0; i < (int)mIndices.size(); i++) {
mIndices[i] = indices[mIndices[i]];
}
}
}
// -------------------------------------------------------------------------------------
void PolygonTriangulator::importPoints(const PxVec3 *points, int numPoints, const int *indices, PxVec3 *planeNormal, bool &isConvex)
{
// find projection 3d -> 2d;
PxVec3 n;
isConvex = true;
if (planeNormal)
n = *planeNormal;
else {
PX_ASSERT(numPoints >= 3);
n = PxVec3(0.0f, 0.0f, 0.0f);
for (int i = 1; i < numPoints-1; i++) {
int i0 = 0;
int i1 = i;
int i2 = i+1;
if (indices) {
i0 = indices[i0];
i1 = indices[i1];
i2 = indices[i2];
}
const PxVec3 &p0 = points[i0];
const PxVec3 &p1 = points[i1];
const PxVec3 &p2 = points[i2];
PxVec3 ni = (p1-p0).cross(p2-p0);
if (i > 1 && ni.dot(n) < 0.0f)
isConvex = false;
n += ni;
}
}
n.normalize();
PxVec3 t0,t1;
if (fabs(n.x) < fabs(n.y) && fabs(n.x) < fabs(n.z))
t0 = PxVec3(1.0f, 0.0f, 0.0f);
else if (fabs(n.y) < fabs(n.z))
t0 = PxVec3(0.0f, 1.0f, 0.0f);
else
t0 = PxVec3(0.0f, 0.0f, 1.0f);
t1 = n.cross(t0);
t1.normalize();
t0 = t1.cross(n);
mPoints.resize(numPoints);
if (indices == NULL) {
for (int i = 0; i < numPoints; i++)
mPoints[i] = PxVec3(points[i].dot(t0), points[i].dot(t1), 0.0f);
}
else {
for (int i = 0; i < numPoints; i++) {
const PxVec3 &p = points[indices[i]];
mPoints[i] = PxVec3(p.dot(t0), p.dot(t1), 0.0f);
}
}
}
// -------------------------------------------------------------------------------------
void PolygonTriangulator::clipEars()
{
// init
int num = mPoints.size();
mCorners.resize(num);
for (int i = 0; i < num; i++) {
Corner &c = mCorners[i];
c.prev = (i > 0) ? i-1 : num-1;
c.next = (i < num-1) ? i + 1 : 0;
c.isEar = false;
c.angle = 0.0f;
PxVec3 &p0 = mPoints[c.prev];
PxVec3 &p1 = mPoints[i];
PxVec3 &p2 = mPoints[c.next];
PxVec3 n1 = p1-p0;
PxVec3 n2 = p2-p1;
if (cross(n1, n2) > 0.0f) {
n1.normalize();
n2.normalize();
c.angle = n1.dot(n2);
c.isEar = true;
int nr = (i+2) % num;
for (int j = 0; j < num-3; j++) {
if (inTriangle(mPoints[nr], p0,p1,p2)) {
c.isEar = false;
break;
}
nr = (nr+1) % num;
}
}
}
int firstCorner = 0;
int numCorners = num;
while (numCorners > 3) {
// find best ear
float minAng = FLT_MAX;
int minNr = -1;
int nr = firstCorner;
for (int i = 0; i < numCorners; i++) {
Corner &c = mCorners[nr];
if (c.isEar && c.angle < minAng) {
minAng = c.angle;
minNr = nr;
}
nr = c.next;
}
// cut ear
// assert(minNr >= 0);
if (minNr < 0)
break;
Corner &cmin = mCorners[minNr];
mIndices.pushBack(cmin.prev);
mIndices.pushBack(minNr);
mIndices.pushBack(cmin.next);
mCorners[cmin.prev].next = cmin.next;
mCorners[cmin.next].prev = cmin.prev;
if (firstCorner == minNr)
firstCorner = cmin.next;
numCorners--;
if (numCorners == 3)
break;
// new ears?
for (int i = 0; i < 2; i++) {
int i1 = (i == 0) ? cmin.prev : cmin.next;
int i0 = mCorners[i1].prev;
int i2 = mCorners[i1].next;
PxVec3 &p0 = mPoints[i0];
PxVec3 &p1 = mPoints[i1];
PxVec3 &p2 = mPoints[i2];
PxVec3 n1 = p1-p0;
PxVec3 n2 = p2-p1;
if (cross(n1, n2) > 0.0f) {
n1.normalize();
n2.normalize();
mCorners[i1].angle = n1.dot(n2);
mCorners[i1].isEar = true;
int nr = mCorners[i2].next;
for (int j = 0; j < numCorners-3; j++) {
if (inTriangle(mPoints[nr], p0,p1,p2)) {
mCorners[i1].isEar = false;
break;
}
nr = mCorners[nr].next;
}
}
}
}
int id = firstCorner;
mIndices.pushBack(id);
id = mCorners[id].next;
mIndices.pushBack(id);
id = mCorners[id].next;
mIndices.pushBack(id);
}
}
}
}
#endif

View File

@ -0,0 +1,86 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef POLYGON_TRIANGULATOR_BASE_H
#define POLYGON_TRIANGULATOR_BASE_H
#include <foundation/PxVec3.h>
#include <foundation/PxMath.h>
#include <PsArray.h>
#include <PsUserAllocated.h>
namespace physx
{
namespace fracture
{
namespace base
{
// ------------------------------------------------------------------------------
class PolygonTriangulator : public ::physx::shdfnd::UserAllocated {
friend class SimScene;
public:
// singleton pattern
//static PolygonTriangulator* getInstance();
//static void destroyInstance();
void triangulate(const PxVec3 *points, int numPoints, const int *indices = NULL, PxVec3 *planeNormal = NULL);
const shdfnd::Array<int> &getIndices() const { return mIndices; }
protected:
void importPoints(const PxVec3 *points, int numPoints, const int *indices, PxVec3 *planeNormal, bool &isConvex);
void clipEars();
inline float cross(const PxVec3 &p0, const PxVec3 &p1);
bool inTriangle(const PxVec3 &p, const PxVec3 &p0, const PxVec3 &p1, const PxVec3 &p2);
PolygonTriangulator(SimScene* scene);
virtual ~PolygonTriangulator();
SimScene* mScene;
shdfnd::Array<PxVec3> mPoints;
shdfnd::Array<int> mIndices;
struct Corner {
int prev;
int next;
bool isEar;
float angle;
};
shdfnd::Array<Corner> mCorners;
};
}
}
}
#endif
#endif

View File

@ -0,0 +1,364 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#include "PsHashMap.h"
#include "SimSceneBase.h"
#include <foundation/PxMat44.h>
#include "PxRigidBodyExt.h"
#include "PxPhysics.h"
#include "PxCooking.h"
#include "PxShape.h"
#include "ActorBase.h"
#include "CompoundBase.h"
#include "ConvexBase.h"
#include "CompoundCreatorBase.h"
#include "PolygonTriangulatorBase.h"
#include "RTdef.h"
#include "PhysXMacros.h"
#include "PxScene.h"
#include "PxD6Joint.h"
#define USE_CONVEX_RENDERER 1
#define NUM_NO_SOUND_FRAMES 1
#define REL_VEL_FRACTURE_THRESHOLD 5.0f
//#define REL_VEL_FRACTURE_THRESHOLD 0.1f
namespace physx
{
namespace fracture
{
namespace base
{
SimScene* SimScene::createSimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath)
{
SimScene* s = PX_NEW(SimScene)(pxPhysics,pxCooking, isGrbScene,minConvexSize,defaultMat,resourcePath);
s->createSingletons();
return s;
}
void SimScene::createSingletons()
{
mCompoundCreator = PX_NEW(CompoundCreator)(this);
mPolygonTriangulator = PX_NEW(PolygonTriangulator)(this);
addActor(createActor()); // make default actor
}
Convex* SimScene::createConvex()
{
return PX_NEW(Convex)(this);
}
Compound* SimScene::createCompound(const FracturePattern *pattern, const FracturePattern *secondaryPattern, PxReal contactOffset, PxReal restOffset)
{
return PX_NEW(Compound)(this,contactOffset,restOffset);
}
Actor* SimScene::createActor()
{
return PX_NEW(Actor)(this);
}
shdfnd::Array<Compound*> SimScene::getCompounds()
{
return mActors[0]->getCompounds();
}
///*extern*/ std::vector<Compound*> delCompoundList;
// --------------------------------------------------------------------------------------------
SimScene::SimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath)
{
mPxPhysics = pxPhysics; // used for cooking
mPxCooking = pxCooking;
mPxDefaultMaterial = defaultMat;
mResourcePath = resourcePath;
clear();
mRenderBuffers.init();
mSceneVersion = 1;
mRenderBufferVersion = 0;
mOptixBufferVersion = 0;
//create3dTexture();
mFractureForceThreshold = 500.0f;
mContactImpactRadius = 0.5f;
mNoFractureFrames = 0;
mNoSoundFrames = 0;
mFrameNr = 0;
mDebugDraw = false;
// mDebugDraw = true; // foo
mPickDepth = 0.0f;
mPickActor = NULL;
mPickJoint = NULL;
mPickPos = mPickLocalPos = PxVec3(0.0f, 0.0f, 0.0f);
mMinConvexSize = minConvexSize;
mNumNoFractureFrames = 2;
bumpTextureUVScale = 0.1f;
roughnessScale = 0.2f;
extraNoiseScale = 2.0f;
particleBumpTextureUVScale = 0.2f;
particleRoughnessScale = 0.8f;
particleExtraNoiseScale = 2.0f;
mPlaySounds = false;
mRenderDebris = true;
mCompoundCreator = NULL;
mPolygonTriangulator = NULL;
mAppNotify = NULL;
}
// --------------------------------------------------------------------------------------------
SimScene::~SimScene()
{
clear();
// Delete actors if not already deleted
for(int i = ((int)mActors.size() - 1) ; i >= 0; i--)
{
PX_DELETE(mActors[i]);
}
PX_DELETE(mCompoundCreator);
PX_DELETE(mPolygonTriangulator);
mCompoundCreator = NULL;
mPolygonTriangulator = NULL;
}
// --------------------------------------------------------------------------------------------
void SimScene::clear()
{
for(int i = 0 ; i < (int)mActors.size(); i++)
{
mActors[i]->clear();
}
deleteCompounds();
mPickActor = NULL;
++mSceneVersion;
}
void SimScene::addActor(Actor* a)
{
mActors.pushBack(a);
}
void SimScene::removeActor(Actor* a)
{
for(int i = 0; i < (int)mActors.size(); i++)
{
if( a == mActors[i] )
{
mActors[i] = mActors[mActors.size()-1];
mActors.popBack();
}
}
}
// --------------------------------------------------------------------------------------------
void SimScene::addCompound(Compound *c)
{
mActors[0]->addCompound(c);
}
// --------------------------------------------------------------------------------------------
void SimScene::removeCompound(Compound *c)
{
mActors[0]->removeCompound(c);
}
// --------------------------------------------------------------------------------------------
void SimScene::deleteCompounds()
{
for (int i = 0; i < (int)delCompoundList.size(); i++)
{
PX_DELETE(delCompoundList[i]);
}
delCompoundList.clear();
}
// --------------------------------------------------------------------------------------------
void SimScene::preSim(float dt)
{
for(int i = 0 ; i < (int)mActors.size(); i++)
{
mActors[i]->preSim(dt);
}
// make sure we use the apex user notify... if the application
// changes their custom one make sure we map to it.
mScene->lockWrite();
PxSimulationEventCallback* userNotify = mScene->getSimulationEventCallback();
if (userNotify != this)
{
mAppNotify = userNotify;
mScene->setSimulationEventCallback(this);
}
mScene->unlockWrite();
}
//float4* posVelG = 0;
//int numPosVelG = 0;
// --------------------------------------------------------------------------------------------
void SimScene::postSim(float dt)
{
for(int i = 0 ; i < (int)mActors.size(); i++)
{
mActors[i]->postSim(dt);
}
mFrameNr++;
mNoFractureFrames--;
mNoSoundFrames--;
}
//-----------------------------------------------------------------------------
bool SimScene::pickStart(const PxVec3 &orig, const PxVec3 &dir)
{
PX_ASSERT(mPickActor == NULL);
float dist = 1000.f;
PxRaycastBuffer buffer;
if (!getScene()->raycast(orig, dir, dist, buffer, PxHitFlag::eDEFAULT, PxQueryFilterData(PxQueryFlag::eDYNAMIC)))
return false;
PxRigidDynamic* pickedActor = buffer.getAnyHit(0).actor->is<PxRigidDynamic>();
dist = buffer.getAnyHit(0).distance;
//mPickActor = mActors[actorNr]->mCompounds[compoundNr]->getPxActor();
mPickPos = orig + dir * dist;
mPickActor = PxGetPhysics().createRigidDynamic(PxTransform(mPickPos));
mPickActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
getScene()->addActor(*mPickActor);
mPickLocalPos = PxVec3(0.f);
mPickJoint = PxD6JointCreate(PxGetPhysics(), mPickActor, PxTransform(PxIdentity), pickedActor, PxTransform(pickedActor->getGlobalPose().transformInv(mPickPos)));
mPickJoint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
mPickJoint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
mPickJoint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
mPickDepth = dist;
return true;
}
//-----------------------------------------------------------------------------
void SimScene::pickMove(const PxVec3 &orig, const PxVec3 &dir)
{
if (mPickActor == NULL)
return;
mPickPos = orig + dir * mPickDepth;
mPickActor->setKinematicTarget(PxTransform(mPickPos));
}
//-----------------------------------------------------------------------------
void SimScene::pickRelease()
{
if (mPickJoint)
mPickJoint->release();
mPickJoint = NULL;
if (mPickActor)
mPickActor->release();
mPickActor = NULL;
}
bool SimScene::findCompound(const Compound* c, int& actorNr, int& compoundNr)
{
actorNr = -1;
compoundNr = -1;
for(int i = 0; i < (int)mActors.size(); i++)
{
if (mActors[i]->findCompound(c,compoundNr))
{
actorNr = i;
return true;
}
}
return false;
}
// --------------------------------------------------------------------------------------------
// CPU
void SimScene::onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs)
{
// Pass along to application's callback, if defined
if (mAppNotify != NULL)
{
mAppNotify->onContact(pairHeader, pairs, nbPairs);
}
}
shdfnd::Array<PxVec3>& SimScene::getDebugPoints() {
return debugPoints;
}
bool SimScene::mapShapeToConvex(const PxShape& shape, Convex& convex)
{
return mShapeMap.insert(&shape, &convex);
}
bool SimScene::unmapShape(const PxShape& shape)
{
return mShapeMap.erase(&shape);
}
Convex* SimScene::findConvexForShape(const PxShape& shape)
{
const physx::shdfnd::HashMap<const PxShape*, Convex*>::Entry* entry = mShapeMap.find(&shape);
return entry != NULL ? entry->second : NULL; // Since we don't expect *entry to be NULL, we shouldn't lose information here
}
}
}
}
#endif

View File

@ -0,0 +1,275 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include "RTdef.h"
#if RT_COMPILE
#ifndef SIM_SCENE_BASE
#define SIM_SCENE_BASE
#include "PxSimulationEventCallback.h"
#include <PsArray.h>
#include <PsUserAllocated.h>
#include "PsHashMap.h"
#include "RTdef.h"
namespace physx
{
class PxPhysics;
class PxCooking;
class PxScene;
class PxRigidDynamic;
class PxD6Joint;
namespace fracture
{
namespace base
{
class Actor;
class Compound;
class Convex;
class FracturePattern;
class CompoundCreator;
class Delaunay2d;
class Delaunay3d;
class PolygonTriangulator;
// -----------------------------------------------------------------------------------
class SimScene :
public PxSimulationEventCallback, public ::physx::shdfnd::UserAllocated
{
friend class Actor;
public:
static SimScene* createSimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath);
protected:
SimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath);
public:
virtual ~SimScene();
// Creates Scene Level Singletons
virtual void createSingletons();
// Access singletons
CompoundCreator* getCompoundCreator() {return mCompoundCreator;}
PolygonTriangulator* getPolygonTriangulator() {return mPolygonTriangulator;}
// Create non-Singletons
virtual Actor* createActor();
virtual Convex* createConvex();
virtual Compound* createCompound(const FracturePattern *pattern, const FracturePattern *secondaryPattern = NULL, PxReal contactOffset = 0.005f, PxReal restOffset = -0.001f);
virtual void clear();
void addCompound(Compound *m);
void removeCompound(Compound *m);
// perform deferred deletion
void deleteCompounds();
void setScene(PxScene* scene) { mScene = scene; }
//
bool findCompound(const Compound* c, int& actorNr, int& compoundNr);
void removeActor(Actor* a);
// Profiler hooks
virtual void profileBegin(const char* /*name*/) {}
virtual void profileEnd(const char* /*name*/) {}
virtual void playSound(const char * /*name*/, int /*nr*/ = -1) {}
// accessors
shdfnd::Array<Compound*> getCompounds(); //{ return mCompounds; }
shdfnd::Array<Actor*> getActors() { return mActors; }
PxPhysics* getPxPhysics() { return mPxPhysics; }
PxCooking* getPxCooking() { return mPxCooking; }
PxScene* getScene() { return mScene; }
//ConvexRenderer &getConvexRenderer() { return mConvexRenderer; }
void preSim(float dt);
void postSim(float dt); //, RegularCell3D* fluidSim);
void setPlaySounds(bool play) { mPlaySounds = play; }
void setContactImpactRadius(float radius) { mContactImpactRadius = radius; }
void setNumNoFractureFrames(int num) { mNumNoFractureFrames = num; }
void setCamera(const PxVec3 &pos, const PxVec3 &dir, const PxVec3 &up, float fov ) {
mCameraPos = pos; mCameraDir = dir; mCameraUp = up; mCameraFov = fov;
}
//void draw(bool useShader, Shader* particleShader = NULL) {}
//void setShaderMaterial(Shader* shader, const ShaderMaterial& mat) {this->mShader = shader; this->mShaderMat = mat;}
//void setFractureForceThreshold(float threshold) { mFractureForceThreshold = threshold; }
PxMaterial *getPxDefaultMaterial() { return mPxDefaultMaterial; }
void toggleDebugDrawing() { mDebugDraw = !mDebugDraw; }
virtual bool pickStart(const PxVec3 &orig, const PxVec3 &dir);
virtual void pickMove(const PxVec3 &orig, const PxVec3 &dir);
virtual void pickRelease();
PxRigidDynamic* getPickActor() { return mPickActor; }
const PxVec3 &getPickPos() { return mPickPos; }
const PxVec3 &getPickLocalPos() { return mPickLocalPos; }
// callback interface
void onContactNotify(unsigned int arraySizes, void ** shape0Array, void ** shape1Array, void ** actor0Array, void ** actor1Array, float * positionArray, float * normalArray);
void onConstraintBreak(PxConstraintInfo* constraints, PxU32 count) { PX_UNUSED((constraints, count)); }
void onWake(PxActor** actors, PxU32 count) { PX_UNUSED((actors, count)); }
void onSleep(PxActor** actors, PxU32 count) { PX_UNUSED((actors, count)); }
void onTrigger(PxTriggerPair* pairs, PxU32 count) { PX_UNUSED((pairs, count)); }
void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs);
void onAdvance(const PxRigidBody*const* bodyBuffer, const PxTransform* poseBuffer, const PxU32 count) { PX_UNUSED(bodyBuffer); PX_UNUSED(poseBuffer); PX_UNUSED(count); }
void toggleRenderDebris() {mRenderDebris = !mRenderDebris;}
bool getRenderDebrs() {return mRenderDebris;}
//virtual void dumpSceneGeometry() {}
shdfnd::Array<PxVec3>& getDebugPoints();
//virtual void createRenderBuffers() {}
//void loadAndCreateTextureArrays();
shdfnd::Array<PxVec3>& getCrackNormals() {return crackNormals;}
shdfnd::Array<PxVec3>& getTmpPoints() {return tmpPoints;}
bool mapShapeToConvex(const PxShape& shape, Convex& convex);
bool unmapShape(const PxShape& shape);
Convex* findConvexForShape(const PxShape& shape);
bool owns(const PxShape& shape) {return NULL != findConvexForShape(shape);}
protected:
//virtual void create3dTexture() {}
//virtual void updateConvexesTex() {}
//void playShatterSound(float objectSize);
void addActor(Actor* a); // done internally upon creation
PxPhysics *mPxPhysics;
PxCooking *mPxCooking;
PxScene *mScene;
const char *mResourcePath;
bool mPlaySounds;
//shdfnd::Array<Compound*> mCompounds;
shdfnd::Array<Actor*> mActors;
float mFractureForceThreshold;
float mContactImpactRadius;
shdfnd::Array<PxContactPairPoint> mContactPoints;
struct FractureEvent {
void init() {
compound = NULL;
pos = normal = PxVec3(0.0f, 0.0f, 0.0f);
additionalRadialImpulse = additionalNormalImpulse = 0.0f;
withStatic = false;
}
Compound *compound;
PxVec3 pos;
PxVec3 normal;
float additionalRadialImpulse;
float additionalNormalImpulse;
bool withStatic;
};
struct RenderBuffers {
void init() {
numVertices = 0; numIndices = 0;
VBO = 0; IBO = 0; matTex = 0; volTex = 0;
texSize = 0; numConvexes = -1;
}
shdfnd::Array<float> tmpVertices;
shdfnd::Array<unsigned int> tmpIndices;
shdfnd::Array<float> tmpTexCoords;
int numVertices, numIndices;
unsigned int VBO;
unsigned int IBO;
unsigned int volTex;
unsigned int matTex;
int texSize;
int numConvexes;
};
RenderBuffers mRenderBuffers;
unsigned int mSceneVersion; // changed on each update
unsigned int mRenderBufferVersion; // to handle updates
unsigned int mOptixBufferVersion; // to handle updates
PxMaterial *mPxDefaultMaterial;
//ConvexRenderer mConvexRenderer;
int mNoFractureFrames;
int mNoSoundFrames;
int mFrameNr;
bool mDebugDraw;
float mPickDepth;
PxRigidDynamic *mPickActor;
PxD6Joint* mPickJoint;
PxVec3 mPickPos;
PxVec3 mPickLocalPos;
float mMinConvexSize;
int mNumNoFractureFrames; // > 1 to prevent a slow down by too many fracture events
PxVec3 mCameraPos, mCameraDir, mCameraUp;
float mCameraFov;
float bumpTextureUVScale;
float extraNoiseScale;
float roughnessScale;
float particleBumpTextureUVScale;
float particleRoughnessScale;
float particleExtraNoiseScale;
shdfnd::Array<PxVec3> debugPoints;
bool mRenderDebris;
PxSimulationEventCallback* mAppNotify;
//GLuint diffuseTexArray, bumpTexArray, specularTexArray, emissiveReflectSpecPowerTexArray;
//GLuint loadTextureArray(std::vector<std::string>& names);
//Singletons
CompoundCreator* mCompoundCreator;
PolygonTriangulator* mPolygonTriangulator;
//Array for use by Compound (effectively static)
shdfnd::Array<PxVec3> crackNormals;
shdfnd::Array<PxVec3> tmpPoints;
// Deferred Deletion list
shdfnd::Array<Compound*> delCompoundList;
// Map used to determine SimScene ownership of shape
shdfnd::HashMap<const PxShape*,Convex*> mShapeMap;
};
}
}
}
#endif
#endif

View File

@ -0,0 +1,192 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include <foundation/PxBounds3.h>
#include "Mesh.h"
#include <algorithm>
#include <iostream>
// -------------------------------------------------------------------
struct SimpleVertexRef {
int vert, normal, texCoord;
int indexNr, subMeshNr;
bool operator < (const SimpleVertexRef &r) const {
if (vert < r.vert) return true;
if (vert > r.vert) return false;
if (normal < r.normal) return true;
if (normal > r.normal) return false;
return texCoord < r.texCoord;
}
bool operator == (const SimpleVertexRef &r) const {
return vert == r.vert && normal == r.normal && texCoord == r.texCoord;
}
void parse(char *s, int indexNr) {
int nr[3] = {0,0,0};
char *p = s;
for (int i = 0; i < 3; i++) {
while (*p != 0 && *p != '/') p++;
bool end = (*p == 0);
*p = 0;
sscanf_s(s, "%i", &nr[i]);
if (end) break;
p++; s = p;
}
vert = nr[0]-1; texCoord = nr[1]-1; normal = nr[2]-1;
this->indexNr = indexNr;
}
};
#define OBJ_STR_LEN 256
// -------------------------------------------------------------------
bool Mesh::loadFromObjFile(const std::string &filename)
{
const int maxVertsPerFace = 8;
char s[OBJ_STR_LEN], ps[maxVertsPerFace][OBJ_STR_LEN], sub[OBJ_STR_LEN];
int matNr = -1;
PxVec3 p;
float u,v;
shdfnd::Array<SimpleVertexRef> refs;
SimpleVertexRef ref[maxVertsPerFace];
shdfnd::Array<PxVec3> vertices;
shdfnd::Array<PxVec3> normals;
shdfnd::Array<float> texCoords;
int numIndices = 0;
mSubMeshes.resize(1);
mNames.resize(1);
mSubMeshes[0].init();
mNames[0] = "";
mSubMeshes[0].firstIndex = 0;
FILE *f;
if (fopen_s(&f, filename.c_str(), "r") != 0) {
std::cerr << "Could not load OBJ file: " << filename << std::endl;
return false;
}
// first a vertex ref is generated for each v/n/t combination
while (!feof(f)) {
if (fgets(s, OBJ_STR_LEN, f) == NULL) break;
if (strncmp(s, "usemtl", 6) == 0 || strncmp(s, "g ", 2) == 0) { // new group
bool isGroup = strncmp(s, "g ", 2) == 0;
if (isGroup)
strcpy(sub, &s[2]);
else
strcpy(sub, &s[6]);
int numSubs = mSubMeshes.size();
if (mSubMeshes[numSubs-1].numIndices > 0) {
mSubMeshes.resize(numSubs+1);
mNames.resize(numSubs+1);
mSubMeshes[numSubs].init();
mNames[numSubs] = "";
mSubMeshes[numSubs].firstIndex = mIndices.size();
}
int subNr = mSubMeshes.size() - 1;
if (mNames[subNr] == "" || isGroup)
mNames[subNr] = std::string(sub);
}
else if (strncmp(s, "v ", 2) == 0) { // vertex
sscanf_s(s, "v %f %f %f", &p.x, &p.y, &p.z);
vertices.pushBack(p);
}
else if (strncmp(s, "vn ", 3) == 0) { // normal
sscanf_s(s, "vn %f %f %f", &p.x, &p.y, &p.z);
normals.pushBack(p);
}
else if (strncmp(s, "vt ", 3) == 0) { // texture coords
sscanf_s(s, "vt %f %f", &u, &v);
texCoords.pushBack(u);
texCoords.pushBack(v);
}
else if (strncmp(s, "f ", 2) == 0) { // face, tri or quad
int nr;
nr = sscanf_s(s, "f %s %s %s %s %s %s",
ps[0], OBJ_STR_LEN, ps[1], OBJ_STR_LEN, ps[2], OBJ_STR_LEN, ps[3], OBJ_STR_LEN,
ps[4], OBJ_STR_LEN, ps[5], OBJ_STR_LEN, ps[6], OBJ_STR_LEN, ps[7], OBJ_STR_LEN);
if (nr >= 3) {
for (int i = 0; i < nr; i++)
ref[i].parse(ps[i], 0);
for (int i = 1; i < nr-1; i++) {
ref[0].indexNr = numIndices++; refs.pushBack(ref[0]); mIndices.pushBack(0);
ref[i].indexNr = numIndices++; refs.pushBack(ref[i]); mIndices.pushBack(0);
ref[i+1].indexNr = numIndices++; refs.pushBack(ref[i+1]); mIndices.pushBack(0);
mSubMeshes[mSubMeshes.size()-1].numIndices += 3;
}
}
}
}
fclose(f);
// now we merge multiple v/n/t triplets
std::sort(refs.begin(), refs.end());
int i = 0;
PxVec3 defNormal(1.0f, 0.0f, 0.0f);
bool normalsOK = true;
bool mTextured = true;
int numTexCoords = texCoords.size();
int baseVertNr = 0;
while (i < (int)refs.size()) {
int vertNr = mVertices.size();
SimpleVertexRef &r = refs[i];
mVertices.pushBack(vertices[r.vert]);
if (r.normal >= 0) mNormals.pushBack(normals[r.normal]);
else { mNormals.pushBack(defNormal); normalsOK = false; }
if (r.texCoord >= 0 && r.texCoord < numTexCoords) {
//mTexCoords.pushBack(texCoords[2*r.texCoord]);
//mTexCoords.pushBack(texCoords[2*r.texCoord+1]);
mTexCoords.pushBack(PxVec2(texCoords[2*r.texCoord],texCoords[2*r.texCoord+1]));
}
else {
//mTexCoords.pushBack(0.0f);
//mTexCoords.pushBack(0.0f);
mTexCoords.pushBack(PxVec2(0.0f,0.0f));
}
mIndices[r.indexNr] = vertNr;
i++;
while (i < (int)refs.size() && r == refs[i]) {
mIndices[refs[i].indexNr] = vertNr;
i++;
}
}
if (!normalsOK)
updateNormals();
return true;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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