aboutsummaryrefslogtreecommitdiff
path: root/APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition')
-rw-r--r--APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition/TestConvexDecomposition.cpp351
-rw-r--r--APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition/wavefront.cpp854
-rw-r--r--APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition/wavefront.h53
3 files changed, 1258 insertions, 0 deletions
diff --git a/APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition/TestConvexDecomposition.cpp b/APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition/TestConvexDecomposition.cpp
new file mode 100644
index 00000000..3eae80b9
--- /dev/null
+++ b/APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition/TestConvexDecomposition.cpp
@@ -0,0 +1,351 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2013 NVIDIA Corporation. All rights reserved.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+#include <conio.h>
+
+#pragma warning(disable:4996 4100)
+
+#include "ConvexDecomposition.h"
+#include "wavefront.h"
+#include "PxAllocatorCallback.h"
+#include "PxErrorCallback.h"
+#include "PsShare.h"
+#include "PxFoundation.h"
+#include "PsFoundation.h"
+
+namespace CONVEX_DECOMPOSITION
+{
+ ConvexDecomposition *gConvexDecomposition = NULL;
+};
+
+float getFloatArg(int arg,int argc,const char **argv)
+{
+ float ret = 0;
+ if ( arg < argc )
+ {
+ ret = (float)atof(argv[arg]);
+ }
+ else
+ {
+ printf("Error: Missing input argument value at argument location %d.\r\n",arg+1);
+ }
+ return ret;
+}
+
+int getIntArg(int arg,int argc,const char **argv)
+{
+ int ret = 0;
+ if ( arg < argc )
+ {
+ ret = atoi(argv[arg]);
+ }
+ else
+ {
+ printf("Error: Missing input argument value at argument location %d.\r\n",arg+1);
+ }
+ return ret;
+}
+
+class AppUserAllocator : public physx::PxAllocatorCallback
+{
+public:
+
+ virtual void* allocate(size_t size, const char * , const char* , int )
+ {
+#ifdef PX_WINDOWS
+ return ::_aligned_malloc(size, 16);
+#else
+ return ::malloc(size);
+#endif
+ }
+
+ // this method needs to be removed
+ virtual void* allocate(size_t size, physx::PxU32 , const char* , int )
+ {
+#ifdef PX_WINDOWS
+ return ::_aligned_malloc(size, 16);
+#else
+ return ::malloc(size);
+#endif
+ }
+
+ virtual void deallocate(void* ptr)
+ {
+#ifdef PX_WINDOWS
+ ::_aligned_free(ptr);
+#else
+ ::free(ptr);
+#endif
+ }
+
+};
+
+class AppUserOutputStream : public physx::PxErrorCallback
+{
+public:
+ virtual void reportError(physx::PxErrorCode::Enum code, const char* message, const char* file, int line)
+ {
+
+ }
+
+};
+
+
+static AppUserAllocator appAlloc;
+static AppUserOutputStream appOutputStream;
+
+void main(int argc,const char ** argv)
+{
+ PX_UNUSED(argc);
+ PX_UNUSED(argv);
+
+ physx::Foundation::createInstance(PX_PUBLIC_FOUNDATION_VERSION, appOutputStream, appAlloc);
+
+
+ if ( argc == 1 )
+ {
+ printf("Usage: TestConvexDecomposition <wavefront.obj> (options)\r\n");
+ printf("\r\n");
+ printf("Options:\r\n");
+ printf("\r\n");
+ printf("-split : Tests mesh splitting.\r\n");
+ printf("-plane A B C D : Specifies the plane equation to split the mesh by, if testing split only.\r\n");
+ printf("-closed : Indicates that the mesh should be closed when it is split. Off by default; experimental.\r\n");
+ printf("-depth <value> : Specify the convex decomposition depth.\r\n");
+ printf("-merge <value> : Specify the merge threshold percentage. Reasonable ranges 0-10.\r\n");
+ printf("-concavity <value> : Specify the concavity threshold as a percentage reasonable ranges 0-10.\r\n");
+ printf("-hacd <concavity> <minCluster> : Use HACD (recommended). Specify the concavity value for HACD (default 100) and the mininum number of clusters (hulls)\r\n");
+ printf("-connect : Is using HACD; this specifies the connectivity distance.\r\n");
+ printf("-maxhullverts <v> : Specify the maxmium number of vertices in the output convex hulls.\r\n");
+ }
+ else
+ {
+ const char *wavefront = argv[1];
+
+ bool splitOnly = false;
+ bool closed = false;
+ bool useHACD = false;
+ physx::PxF32 hacdConcavity = 100;
+ physx::PxU32 hacdMinClusterSize = 10;
+ physx::PxF32 connectionDistance = 0;
+
+ physx::PxF32 plane[4] = { 1, 0, 0, 0 };
+ physx::PxU32 depth = 5;
+ physx::PxF32 mergePercentage = 3; //1;
+ physx::PxF32 concavityPercentage = 3; //;
+ physx::PxU32 maxHullVerts = 64;
+
+ int scan = 2;
+ while ( scan < argc )
+ {
+ const char *option = argv[scan];
+ if ( strcmp(option,"-split") == 0 )
+ {
+ splitOnly = true;
+ printf("Testing a single split operation.\r\n");
+ scan++;
+ }
+ else if ( strcmp(option,"-plane") == 0 )
+ {
+ plane[0] = getFloatArg(scan+1,argc,argv);
+ plane[1] = getFloatArg(scan+2,argc,argv);
+ plane[2] = getFloatArg(scan+3,argc,argv);
+ plane[3] = getFloatArg(scan+4,argc,argv);
+ scan+=5;
+ }
+ else if ( strcmp(option,"-closed") == 0 )
+ {
+ closed = true;
+ printf("Will produce closed split meshes.\r\n");
+ scan++;
+ }
+ else if ( strcmp(option,"-depth") == 0 )
+ {
+ depth = getIntArg(scan+1,argc,argv);
+ scan+=2;
+ }
+ else if ( strcmp(option,"-connect") == 0 )
+ {
+ connectionDistance = getFloatArg(scan+1,argc,argv);
+ scan+=2;
+ }
+ else if ( strcmp(option,"-merge") == 0 )
+ {
+ mergePercentage = getFloatArg(scan+1,argc,argv);
+ scan+=2;
+ }
+ else if ( strcmp(option,"-concavity") == 0 )
+ {
+ concavityPercentage = getFloatArg(scan+1,argc,argv);
+ scan+=2;
+ }
+ else if ( strcmp(option,"-maxhullverts") == 0 )
+ {
+ maxHullVerts = getIntArg(scan+1,argc,argv);
+ scan+=2;
+ }
+ else if ( strcmp(option,"-hacd")== 0)
+ {
+ useHACD = true;
+ hacdConcavity = getFloatArg(scan+1,argc,argv);
+ hacdMinClusterSize = getIntArg(scan+2,argc,argv);
+ scan+=3;
+ }
+ else
+ {
+ printf("Unknown option: %s\r\n", option );
+ scan++;
+ }
+
+ }
+
+ CONVEX_DECOMPOSITION::gConvexDecomposition = CONVEX_DECOMPOSITION::createConvexDecomposition();
+ if ( CONVEX_DECOMPOSITION::gConvexDecomposition )
+ {
+ WavefrontObj obj;
+ unsigned int tcount = obj.loadObj(wavefront,false);
+ if ( tcount )
+ {
+ if ( splitOnly )
+ {
+ CONVEX_DECOMPOSITION::TriangleMesh input;
+ CONVEX_DECOMPOSITION::TriangleMesh left;
+ CONVEX_DECOMPOSITION::TriangleMesh right;
+ input.mVcount = obj.mVertexCount;
+ input.mVertices = obj.mVertices;
+ input.mTriCount = obj.mTriCount;
+ input.mIndices = (physx::PxU32 *)obj.mIndices;
+ CONVEX_DECOMPOSITION::gConvexDecomposition->splitMesh(plane,input,left,right,closed);
+
+ if ( left.mTriCount )
+ {
+ printf("Left Half of the split mesh has %d triangles. Saving as 'left.obj'\r\n", left.mTriCount);
+ WavefrontObj::saveObj("left.obj", left.mVcount, left.mVertices, left.mTriCount,(const int *) left.mIndices );
+ }
+ else
+ {
+ printf("No triangles on the left half of the split mesh.\r\n");
+ }
+ if ( right.mTriCount )
+ {
+ printf("Left Half of the split mesh has %d triangles. Saving as 'right.obj'\r\n", right.mTriCount);
+ WavefrontObj::saveObj("right.obj", right.mVcount, right.mVertices, right.mTriCount, (const int *)right.mIndices );
+ }
+ else
+ {
+ printf("No triangles on the right half of the split mesh.\r\n");
+ }
+
+ CONVEX_DECOMPOSITION::gConvexDecomposition->releaseTriangleMeshMemory(left);
+ CONVEX_DECOMPOSITION::gConvexDecomposition->releaseTriangleMeshMemory(right);
+ }
+ else
+ {
+ CONVEX_DECOMPOSITION::DecompDesc desc;
+ desc.mClosedSplit = closed;
+ desc.mDepth = depth;
+ desc.mCpercent = concavityPercentage;
+ desc.mPpercent = mergePercentage;
+ desc.mTcount = obj.mTriCount;
+ desc.mVcount = obj.mVertexCount;
+ desc.mVertices = obj.mVertices;
+ desc.mIndices = (physx::PxU32 *)obj.mIndices;
+ desc.mUseHACD = useHACD;
+ desc.mConcavityHACD = hacdConcavity;
+ desc.mMinClusterSizeHACD = hacdMinClusterSize;
+ desc.mConnectionDistanceHACD = connectionDistance;
+
+
+ printf("Performing convex decomposition.\r\n");
+
+ physx::PxU32 count = CONVEX_DECOMPOSITION::gConvexDecomposition->performConvexDecomposition(desc);
+ if ( count )
+ {
+ printf("Produced %d output convex hulls.\r\n", count );
+ FILE *fph = fopen("ConvexDecomposition.obj", "wb");
+ if ( fph )
+ {
+ fprintf(fph,"# Input mesh '%s' produced %d convex hulls.\r\n", wavefront, count );
+ physx::PxU32 *baseVertex = new physx::PxU32[count];
+ physx::PxU32 vertexCount = 0;
+ for (physx::PxU32 i=0; i<count; i++)
+ {
+ baseVertex[i] = vertexCount;
+ const CONVEX_DECOMPOSITION::ConvexResult &r = *CONVEX_DECOMPOSITION::gConvexDecomposition->getConvexResult(i);
+ fprintf(fph,"## Hull %d has %d vertices.\r\n", i+1, r.mHullVcount );
+ for (physx::PxU32 i=0; i<r.mHullVcount; i++)
+ {
+ const physx::PxF32 *p = &r.mHullVertices[i*3];
+ fprintf(fph,"v %0.9f %0.9f %0.9f\r\n", p[0], p[1], p[2] );
+ }
+ vertexCount+=r.mHullVcount;
+ }
+
+ for (physx::PxU32 i=0; i<count; i++)
+ {
+ const CONVEX_DECOMPOSITION::ConvexResult &r = *CONVEX_DECOMPOSITION::gConvexDecomposition->getConvexResult(i);
+ physx::PxU32 startVertex = baseVertex[i];
+ fprintf(fph,"# Convex Hull %d contains %d triangles and %d vertices. Starting vertex index is: %d It has a volume of: %0.9f\r\n", i+1, r.mHullTcount, r.mHullVcount, startVertex, r.mHullVolume );
+ for (physx::PxU32 j=0; j<r.mHullTcount; j++)
+ {
+ physx::PxU32 i1 = r.mHullIndices[j*3+0]+startVertex+1;
+ physx::PxU32 i2 = r.mHullIndices[j*3+1]+startVertex+1;
+ physx::PxU32 i3 = r.mHullIndices[j*3+2]+startVertex+1;
+ fprintf(fph,"f %d %d %d\r\n", i1, i2, i3 );
+ }
+ }
+ fclose(fph);
+ delete []baseVertex;
+ }
+ else
+ {
+ printf("Failed to open file 'ConvexDecomposition.obj' for output.\r\n");
+ }
+ }
+ else
+ {
+ printf("Failed to produce any convex hull results!?\r\n");
+ }
+
+ }
+ }
+ else
+ {
+ printf("Failed to load Wavefront OBJ file '%s'\r\n",wavefront);
+ }
+ }
+ else
+ {
+ printf("Failed to load the convex decomposition plugin DLL.\r\n");
+ }
+ }
+}
diff --git a/APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition/wavefront.cpp b/APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition/wavefront.cpp
new file mode 100644
index 00000000..a6498fa3
--- /dev/null
+++ b/APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition/wavefront.cpp
@@ -0,0 +1,854 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2013 NVIDIA Corporation. All rights reserved.
+
+#ifndef __PPCGEKKO__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <vector>
+
+#include "wavefront.h"
+
+#ifdef _WIN32
+# define strcasecmp _stricmp
+#endif
+
+typedef std::vector< int > IntVector;
+typedef std::vector< float > FloatVector;
+
+#pragma warning(disable:4996)
+
+namespace WAVEFRONT
+{
+
+/*******************************************************************/
+/******************** InParser.h ********************************/
+/*******************************************************************/
+class InPlaceParserInterface
+{
+public:
+ virtual int ParseLine(int lineno,int argc,const char **argv) =0; // return TRUE to continue parsing, return FALSE to abort parsing process
+};
+
+enum SeparatorType
+{
+ ST_DATA, // is data
+ ST_HARD, // is a hard separator
+ ST_SOFT, // is a soft separator
+ ST_EOS // is a comment symbol, and everything past this character should be ignored
+};
+
+class InPlaceParser
+{
+public:
+ InPlaceParser(void)
+ {
+ Init();
+ }
+
+ InPlaceParser(char *data,int len)
+ {
+ Init();
+ SetSourceData(data,len);
+ }
+
+ InPlaceParser(const char *fname)
+ {
+ Init();
+ SetFile(fname);
+ }
+
+ ~InPlaceParser(void);
+
+ void Init(void)
+ {
+ mQuoteChar = 34;
+ mData = 0;
+ mLen = 0;
+ mMyAlloc = false;
+ for (int i=0; i<256; i++)
+ {
+ mHard[i] = ST_DATA;
+ mHardString[i*2] = (char)i;
+ mHardString[i*2+1] = 0;
+ }
+ mHard[0] = ST_EOS;
+ mHard[32] = ST_SOFT;
+ mHard[9] = ST_SOFT;
+ mHard[13] = ST_SOFT;
+ mHard[10] = ST_SOFT;
+ }
+
+ void SetFile(const char *fname); // use this file as source data to parse.
+
+ void SetSourceData(char *data,int len)
+ {
+ mData = data;
+ mLen = len;
+ mMyAlloc = false;
+ };
+
+ int Parse(InPlaceParserInterface *callback); // returns true if entire file was parsed, false if it aborted for some reason
+
+ int ProcessLine(int lineno,char *line,InPlaceParserInterface *callback);
+
+ const char ** GetArglist(char *source,int &count); // convert source string into an arg list, this is a destructive parse.
+
+ void SetHardSeparator(char c) // add a hard separator
+ {
+ mHard[c] = ST_HARD;
+ }
+
+ void SetHard(char c) // add a hard separator
+ {
+ mHard[c] = ST_HARD;
+ }
+
+
+ void SetCommentSymbol(char c) // comment character, treated as 'end of string'
+ {
+ mHard[c] = ST_EOS;
+ }
+
+ void ClearHardSeparator(char c)
+ {
+ mHard[c] = ST_DATA;
+ }
+
+
+ void DefaultSymbols(void); // set up default symbols for hard seperator and comment symbol of the '#' character.
+
+ bool EOS(char c)
+ {
+ if ( mHard[c] == ST_EOS )
+ {
+ return true;
+ }
+ return false;
+ }
+
+ void SetQuoteChar(char c)
+ {
+ mQuoteChar = c;
+ }
+
+private:
+
+
+ inline char * AddHard(int &argc,const char **argv,char *foo);
+ inline bool IsHard(char c);
+ inline char * SkipSpaces(char *foo);
+ inline bool IsWhiteSpace(char c);
+ inline bool IsNonSeparator(char c); // non seperator,neither hard nor soft
+
+ bool mMyAlloc; // whether or not *I* allocated the buffer and am responsible for deleting it.
+ char *mData; // ascii data to parse.
+ int mLen; // length of data
+ SeparatorType mHard[256];
+ char mHardString[256*2];
+ char mQuoteChar;
+};
+
+/*******************************************************************/
+/******************** InParser.cpp ********************************/
+/*******************************************************************/
+void InPlaceParser::SetFile(const char *fname)
+{
+ if ( mMyAlloc )
+ {
+ free(mData);
+ }
+ mData = 0;
+ mLen = 0;
+ mMyAlloc = false;
+
+ FILE *fph = fopen(fname,"rb");
+ if ( fph )
+ {
+ fseek(fph,0L,SEEK_END);
+ mLen = ftell(fph);
+ fseek(fph,0L,SEEK_SET);
+ if ( mLen )
+ {
+ mData = (char *) malloc(sizeof(char)*(mLen+1));
+ size_t ok = fread(mData, mLen, 1, fph);
+ if ( !ok )
+ {
+ free(mData);
+ mData = 0;
+ }
+ else
+ {
+ mData[mLen] = 0; // zero byte terminate end of file marker.
+ mMyAlloc = true;
+ }
+ }
+ fclose(fph);
+ }
+
+}
+
+InPlaceParser::~InPlaceParser(void)
+{
+ if ( mMyAlloc )
+ {
+ free(mData);
+ }
+}
+
+#define MAXARGS 512
+
+bool InPlaceParser::IsHard(char c)
+{
+ return mHard[c] == ST_HARD;
+}
+
+char * InPlaceParser::AddHard(int &argc,const char **argv,char *foo)
+{
+ while ( IsHard(*foo) )
+ {
+ const char *hard = &mHardString[*foo*2];
+ if ( argc < MAXARGS )
+ {
+ argv[argc++] = hard;
+ }
+ foo++;
+ }
+ return foo;
+}
+
+bool InPlaceParser::IsWhiteSpace(char c)
+{
+ return mHard[c] == ST_SOFT;
+}
+
+char * InPlaceParser::SkipSpaces(char *foo)
+{
+ while ( !EOS(*foo) && IsWhiteSpace(*foo) ) foo++;
+ return foo;
+}
+
+bool InPlaceParser::IsNonSeparator(char c)
+{
+ if ( !IsHard(c) && !IsWhiteSpace(c) && c != 0 ) return true;
+ return false;
+}
+
+
+int InPlaceParser::ProcessLine(int lineno,char *line,InPlaceParserInterface *callback)
+{
+ int ret = 0;
+
+ const char *argv[MAXARGS];
+ int argc = 0;
+
+ char *foo = line;
+
+ while ( !EOS(*foo) && argc < MAXARGS )
+ {
+
+ foo = SkipSpaces(foo); // skip any leading spaces
+
+ if ( EOS(*foo) ) break;
+
+ if ( *foo == mQuoteChar ) // if it is an open quote
+ {
+ foo++;
+ if ( argc < MAXARGS )
+ {
+ argv[argc++] = foo;
+ }
+ while ( !EOS(*foo) && *foo != mQuoteChar ) foo++;
+ if ( !EOS(*foo) )
+ {
+ *foo = 0; // replace close quote with zero byte EOS
+ foo++;
+ }
+ }
+ else
+ {
+
+ foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces
+
+ if ( IsNonSeparator(*foo) ) // add non-hard argument.
+ {
+ bool quote = false;
+ if ( *foo == mQuoteChar )
+ {
+ foo++;
+ quote = true;
+ }
+
+ if ( argc < MAXARGS )
+ {
+ argv[argc++] = foo;
+ }
+
+ if ( quote )
+ {
+ while (*foo && *foo != mQuoteChar ) foo++;
+ if ( *foo ) *foo = 32;
+ }
+
+ // continue..until we hit an eos ..
+ while ( !EOS(*foo) ) // until we hit EOS
+ {
+ if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit
+ {
+ *foo = 0;
+ foo++;
+ break;
+ }
+ else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument
+ {
+ const char *hard = &mHardString[*foo*2];
+ *foo = 0;
+ if ( argc < MAXARGS )
+ {
+ argv[argc++] = hard;
+ }
+ foo++;
+ break;
+ }
+ foo++;
+ } // end of while loop...
+ }
+ }
+ }
+
+ if ( argc )
+ {
+ ret = callback->ParseLine(lineno, argc, argv );
+ }
+
+ return ret;
+}
+
+int InPlaceParser::Parse(InPlaceParserInterface *callback) // returns true if entire file was parsed, false if it aborted for some reason
+{
+ assert( callback );
+ if ( !mData ) return 0;
+
+ int ret = 0;
+
+ int lineno = 0;
+
+ char *foo = mData;
+ char *begin = foo;
+
+
+ while ( *foo )
+ {
+ if ( *foo == 10 || *foo == 13 )
+ {
+ lineno++;
+ *foo = 0;
+
+ if ( *begin ) // if there is any data to parse at all...
+ {
+ int v = ProcessLine(lineno,begin,callback);
+ if ( v ) ret = v;
+ }
+
+ foo++;
+ if ( *foo == 10 ) foo++; // skip line feed, if it is in the carraige-return line-feed format...
+ begin = foo;
+ }
+ else
+ {
+ foo++;
+ }
+ }
+
+ lineno++; // lasst line.
+
+ int v = ProcessLine(lineno,begin,callback);
+ if ( v ) ret = v;
+ return ret;
+}
+
+
+void InPlaceParser::DefaultSymbols(void)
+{
+ SetHardSeparator(',');
+ SetHardSeparator('(');
+ SetHardSeparator(')');
+ SetHardSeparator('=');
+ SetHardSeparator('[');
+ SetHardSeparator(']');
+ SetHardSeparator('{');
+ SetHardSeparator('}');
+ SetCommentSymbol('#');
+}
+
+
+const char ** InPlaceParser::GetArglist(char *line,int &count) // convert source string into an arg list, this is a destructive parse.
+{
+ const char **ret = 0;
+
+ static const char *argv[MAXARGS];
+ int argc = 0;
+
+ char *foo = line;
+
+ while ( !EOS(*foo) && argc < MAXARGS )
+ {
+
+ foo = SkipSpaces(foo); // skip any leading spaces
+
+ if ( EOS(*foo) ) break;
+
+ if ( *foo == mQuoteChar ) // if it is an open quote
+ {
+ foo++;
+ if ( argc < MAXARGS )
+ {
+ argv[argc++] = foo;
+ }
+ while ( !EOS(*foo) && *foo != mQuoteChar ) foo++;
+ if ( !EOS(*foo) )
+ {
+ *foo = 0; // replace close quote with zero byte EOS
+ foo++;
+ }
+ }
+ else
+ {
+
+ foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces
+
+ if ( IsNonSeparator(*foo) ) // add non-hard argument.
+ {
+ bool quote = false;
+ if ( *foo == mQuoteChar )
+ {
+ foo++;
+ quote = true;
+ }
+
+ if ( argc < MAXARGS )
+ {
+ argv[argc++] = foo;
+ }
+
+ if ( quote )
+ {
+ while (*foo && *foo != mQuoteChar ) foo++;
+ if ( *foo ) *foo = 32;
+ }
+
+ // continue..until we hit an eos ..
+ while ( !EOS(*foo) ) // until we hit EOS
+ {
+ if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit
+ {
+ *foo = 0;
+ foo++;
+ break;
+ }
+ else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument
+ {
+ const char *hard = &mHardString[*foo*2];
+ *foo = 0;
+ if ( argc < MAXARGS )
+ {
+ argv[argc++] = hard;
+ }
+ foo++;
+ break;
+ }
+ foo++;
+ } // end of while loop...
+ }
+ }
+ }
+
+ count = argc;
+ if ( argc )
+ {
+ ret = argv;
+ }
+
+ return ret;
+}
+
+/*******************************************************************/
+/******************** Geometry.h ********************************/
+/*******************************************************************/
+
+class GeometryVertex
+{
+public:
+ float mPos[3];
+ float mNormal[3];
+ float mTexel[2];
+};
+
+
+class GeometryInterface
+{
+public:
+
+ virtual void NodeTriangle(const GeometryVertex * /*v1*/,const GeometryVertex * /*v2*/,const GeometryVertex * /*v3*/, bool /*textured*/)
+ {
+ }
+
+};
+
+
+/*******************************************************************/
+/******************** Obj.h ********************************/
+/*******************************************************************/
+
+
+class OBJ : public InPlaceParserInterface
+{
+public:
+ int LoadMesh(const char *fname,GeometryInterface *callback, bool textured);
+ int ParseLine(int lineno,int argc,const char **argv); // return TRUE to continue parsing, return FALSE to abort parsing process
+private:
+
+ void GetVertex(GeometryVertex &v,const char *face) const;
+
+ FloatVector mVerts;
+ FloatVector mTexels;
+ FloatVector mNormals;
+
+ bool mTextured;
+
+ GeometryInterface *mCallback;
+};
+
+
+/*******************************************************************/
+/******************** Obj.cpp ********************************/
+/*******************************************************************/
+
+int OBJ::LoadMesh(const char *fname,GeometryInterface *iface, bool textured)
+{
+ mTextured = textured;
+ int ret = 0;
+
+ mVerts.clear();
+ mTexels.clear();
+ mNormals.clear();
+
+ mCallback = iface;
+
+ InPlaceParser ipp(fname);
+
+ ipp.Parse(this);
+
+return ret;
+}
+
+/***
+static const char * GetArg(const char **argv,int i,int argc)
+{
+ const char * ret = 0;
+ if ( i < argc ) ret = argv[i];
+ return ret;
+}
+****/
+
+void OBJ::GetVertex(GeometryVertex &v,const char *face) const
+{
+ v.mPos[0] = 0;
+ v.mPos[1] = 0;
+ v.mPos[2] = 0;
+
+ v.mTexel[0] = 0;
+ v.mTexel[1] = 0;
+
+ v.mNormal[0] = 0;
+ v.mNormal[1] = 1;
+ v.mNormal[2] = 0;
+
+ int index = atoi( face )-1;
+
+ const char *texel = strstr(face,"/");
+
+ if ( texel )
+ {
+ int tindex = atoi( texel+1) - 1;
+
+ if ( tindex >=0 && tindex < (int)(mTexels.size()/2) )
+ {
+ const float *t = &mTexels[tindex*2];
+
+ v.mTexel[0] = t[0];
+ v.mTexel[1] = t[1];
+
+ }
+
+ const char *normal = strstr(texel+1,"/");
+ if ( normal )
+ {
+ int nindex = atoi( normal+1 ) - 1;
+
+ if (nindex >= 0 && nindex < (int)(mNormals.size()/3) )
+ {
+ const float *n = &mNormals[nindex*3];
+
+ v.mNormal[0] = n[0];
+ v.mNormal[1] = n[1];
+ v.mNormal[2] = n[2];
+ }
+ }
+ }
+
+ if ( index >= 0 && index < (int)(mVerts.size()/3) )
+ {
+
+ const float *p = &mVerts[index*3];
+
+ v.mPos[0] = p[0];
+ v.mPos[1] = p[1];
+ v.mPos[2] = p[2];
+ }
+
+}
+
+int OBJ::ParseLine(int /*lineno*/,int argc,const char **argv) // return TRUE to continue parsing, return FALSE to abort parsing process
+{
+ int ret = 0;
+
+ if ( argc >= 1 )
+ {
+ const char *foo = argv[0];
+ if ( *foo != '#' )
+ {
+ if ( strcasecmp(argv[0],"v") == 0 && argc == 4 )
+ {
+ float vx = (float) atof( argv[1] );
+ float vy = (float) atof( argv[2] );
+ float vz = (float) atof( argv[3] );
+ mVerts.push_back(vx);
+ mVerts.push_back(vy);
+ mVerts.push_back(vz);
+ }
+ else if ( strcasecmp(argv[0],"vt") == 0 && (argc == 3 || argc == 4))
+ {
+ // ignore 4rd component if present
+ float tx = (float) atof( argv[1] );
+ float ty = (float) atof( argv[2] );
+ mTexels.push_back(tx);
+ mTexels.push_back(ty);
+ }
+ else if ( strcasecmp(argv[0],"vn") == 0 && argc == 4 )
+ {
+ float normalx = (float) atof(argv[1]);
+ float normaly = (float) atof(argv[2]);
+ float normalz = (float) atof(argv[3]);
+ mNormals.push_back(normalx);
+ mNormals.push_back(normaly);
+ mNormals.push_back(normalz);
+ }
+ else if ( strcasecmp(argv[0],"f") == 0 && argc >= 4 )
+ {
+ GeometryVertex v[32];
+
+ int vcount = argc-1;
+
+ for (int i=1; i<argc; i++)
+ {
+ GetVertex(v[i-1],argv[i] );
+ }
+
+
+ mCallback->NodeTriangle(&v[0],&v[1],&v[2], mTextured);
+
+ if ( vcount >=3 ) // do the fan
+ {
+ for (int i=2; i<(vcount-1); i++)
+ {
+ mCallback->NodeTriangle(&v[0],&v[i],&v[i+1], mTextured);
+ }
+ }
+
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+
+
+class BuildMesh : public GeometryInterface
+{
+public:
+
+ int GetIndex(const float *p, const float *texCoord)
+ {
+
+ int vcount = (int)mVertices.size()/3;
+
+ if(vcount>0)
+ {
+ //New MS STL library checks indices in debug build, so zero causes an assert if it is empty.
+ const float *v = &mVertices[0];
+ const float *t = texCoord != NULL ? &mTexCoords[0] : NULL;
+
+ for (int i=0; i<vcount; i++)
+ {
+ if ( v[0] == p[0] && v[1] == p[1] && v[2] == p[2] )
+ {
+ if (texCoord == NULL || (t[0] == texCoord[0] && t[1] == texCoord[1]))
+ {
+ return i;
+ }
+ }
+ v+=3;
+ if (t != NULL)
+ t += 2;
+ }
+ }
+
+ mVertices.push_back( p[0] );
+ mVertices.push_back( p[1] );
+ mVertices.push_back( p[2] );
+
+ if (texCoord != NULL)
+ {
+ mTexCoords.push_back( texCoord[0] );
+ mTexCoords.push_back( texCoord[1] );
+ }
+
+ return vcount;
+ }
+
+ virtual void NodeTriangle(const GeometryVertex *v1,const GeometryVertex *v2,const GeometryVertex *v3, bool textured)
+ {
+ mIndices.push_back( GetIndex(v1->mPos, textured ? v1->mTexel : NULL) );
+ mIndices.push_back( GetIndex(v2->mPos, textured ? v2->mTexel : NULL) );
+ mIndices.push_back( GetIndex(v3->mPos, textured ? v3->mTexel : NULL) );
+ }
+
+ const FloatVector& GetVertices(void) const { return mVertices; };
+ const FloatVector& GetTexCoords(void) const { return mTexCoords; };
+ const IntVector& GetIndices(void) const { return mIndices; };
+
+private:
+ FloatVector mVertices;
+ FloatVector mTexCoords;
+ IntVector mIndices;
+};
+
+};
+
+using namespace WAVEFRONT;
+
+WavefrontObj::WavefrontObj(void)
+{
+ mVertexCount = 0;
+ mTriCount = 0;
+ mIndices = 0;
+ mVertices = NULL;
+ mTexCoords = NULL;
+}
+
+WavefrontObj::~WavefrontObj(void)
+{
+ delete mIndices;
+ delete mVertices;
+}
+
+unsigned int WavefrontObj::loadObj(const char *fname, bool textured) // load a wavefront obj returns number of triangles that were loaded. Data is persists until the class is destructed.
+{
+
+ unsigned int ret = 0;
+
+ delete mVertices;
+ mVertices = 0;
+ delete mIndices;
+ mIndices = 0;
+ mVertexCount = 0;
+ mTriCount = 0;
+
+
+ BuildMesh bm;
+
+ OBJ obj;
+
+ obj.LoadMesh(fname,&bm, textured);
+
+
+ const FloatVector &vlist = bm.GetVertices();
+ const IntVector &indices = bm.GetIndices();
+ if ( vlist.size() )
+ {
+ mVertexCount = (int)vlist.size()/3;
+ mVertices = new float[mVertexCount*3];
+ memcpy( mVertices, &vlist[0], sizeof(float)*mVertexCount*3 );
+
+ if (textured)
+ {
+ mTexCoords = new float[mVertexCount * 2];
+ const FloatVector& tList = bm.GetTexCoords();
+ memcpy( mTexCoords, &tList[0], sizeof(float) * mVertexCount * 2);
+ }
+
+ mTriCount = (int)indices.size()/3;
+ mIndices = new int[mTriCount*3*sizeof(int)];
+ memcpy(mIndices, &indices[0], sizeof(int)*mTriCount*3);
+ ret = mTriCount;
+ }
+
+
+ return ret;
+}
+
+
+bool WavefrontObj::saveObj(const char *fname,int vcount,const float *vertices,int tcount,const int *indices)
+{
+ bool ret = false;
+
+ FILE *fph = fopen(fname,"wb");
+ if ( fph )
+ {
+ for (int i=0; i<vcount; i++)
+ {
+ fprintf(fph,"v %0.9f %0.9f %0.9f\r\n", vertices[0], vertices[1], vertices[2] );
+ vertices+=3;
+ }
+ for (int i=0; i<tcount; i++)
+ {
+ fprintf(fph,"f %d %d %d\r\n", indices[0]+1, indices[1]+1, indices[2]+1 );
+ indices+=3;
+ }
+ fclose(fph);
+ ret = true;
+ }
+ return ret;
+}
+
+#endif
diff --git a/APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition/wavefront.h b/APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition/wavefront.h
new file mode 100644
index 00000000..57e0f7e6
--- /dev/null
+++ b/APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition/wavefront.h
@@ -0,0 +1,53 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2013 NVIDIA Corporation. All rights reserved.
+
+#ifndef WAVEFRONT_OBJ_H
+
+
+#define WAVEFRONT_OBJ_H
+
+
+class WavefrontObj
+{
+public:
+
+ WavefrontObj(void);
+ ~WavefrontObj(void);
+
+ unsigned int loadObj(const char *fname, bool textured); // load a wavefront obj returns number of triangles that were loaded. Data is persists until the class is destructed.
+
+
+ static bool saveObj(const char *fname,int vcount,const float *vertices,int tcount,const int *indices);
+
+ int mVertexCount;
+ int mTriCount;
+ int *mIndices;
+ float *mVertices;
+ float *mTexCoords;
+};
+
+#endif