diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/shared/general/ConvexDecomposition/app/TestConvexDecomposition | |
| download | physx-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')
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 |