aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Samples/SampleFramework/framework/src
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 /PhysX_3.4/Samples/SampleFramework/framework/src
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 'PhysX_3.4/Samples/SampleFramework/framework/src')
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/ODBlock.cpp530
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/SampleApplication.cpp487
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/SampleAsset.cpp44
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/SampleAssetManager.cpp436
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/SampleCommandLine.cpp426
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/SampleDirManager.cpp121
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/SampleInputAsset.cpp100
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/SampleLineDebugRender.cpp215
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/SampleMaterialAsset.cpp308
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/SamplePointDebugRender.cpp207
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/SampleTextureAsset.cpp342
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/SampleTree.cpp70
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/SampleTriangleDebugRender.cpp244
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/nv_dds.cpp1115
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/nv_dds.h378
-rw-r--r--PhysX_3.4/Samples/SampleFramework/framework/src/windows/WindowsSampleAssetManager.cpp48
16 files changed, 5071 insertions, 0 deletions
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/ODBlock.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/ODBlock.cpp
new file mode 100644
index 00000000..2e3bd040
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/ODBlock.cpp
@@ -0,0 +1,530 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+
+/*-------------------------------------------------------------*\
+| |
+| ODBlock class - object description script |
+| |
+| Copyright (C) 1999 Adam Moravanszky |
+| |
+| |
+\*-------------------------------------------------------------*/
+/*-Revision----------------------\
+| At: 10/3/99 5:51:37 PM
+|
+| Changed vector container from
+| storing val to refernce.
+\-------------------------------*/
+/*-Revision----------------------\
+| At: 5/18/00 9:29:43 PM
+| changed static sized indentifiers
+| to arbitrary dynamic identifiers.
+|
+\-------------------------------*/
+/*-Revision----------------------\
+| At: 6/19/02
+| added multiline comments.
+|
+|
+\-------------------------------*/
+/*-Revision----------------------\
+| At: 5/19/03
+| fixed commend bug with
+| file > 0xffff chars.
+|
+\-------------------------------*/
+/*-Revision----------------------\
+| At: 19/10/09
+| removed encryption
+| converted to FILE * usage.
+|
+\-------------------------------*/
+#include "ODBlock.h"
+#include "PxTkFile.h"
+
+const char * ODBlock::lastError = NULL;
+
+
+const char * ODBlock::ODSyntaxError::asString()
+{
+ static const char unex1[] = "Quote unexpected.";
+ static const char unex2[] = "Opening brace unexpected.";
+ static const char unex3[] = "Closing brace unexpected.";
+ static const char unex4[] = "Literal or semicolon unexpected.";
+ static const char unex5[] = "Unexpected end of file found.";
+ static const char encun[] = "Unknown encryption algo code.";
+ switch (err)
+ {
+ case ODSE_UNEX_QUOTE:
+ return unex1;
+ case ODSE_UNEX_OBRACE:
+ return unex2;
+ case ODSE_UNEX_CBRACE:
+ return unex3;
+ case ODSE_UNEX_LITERAL:
+ return unex4;
+ case ODSE_UNEX_EOF:
+ return unex5;
+ case ODSE_ENC_UNKNOWN:
+ return encun;
+ default:
+ return NULL;
+ }
+}
+
+static inline bool isNewLine(char c)
+{
+ return c == '\n' || c == '\r';
+}
+
+bool ODBlock::loadScript(SampleFramework::File * fp) //loads block from script, including subbocks
+{
+ int c;
+ unsigned currindex = 0;
+ bool bQuote = false; //if we're inside a pair of quotes
+ identifier[0] = '\0';
+ identSize = 0;
+ bTerminal = true;
+ termiter = NULL;
+ bool ignoreWhiteSpace = true;
+
+ State state;
+
+ state = WAIT_IDENT;
+
+
+ //0) read possible comments starting with # to end of line
+ //1) read our identifier. -->forget quotes for now.
+
+ while(!feof(fp))
+ {
+ do
+ {
+ c = fgetc(fp);
+ }
+ while (ignoreWhiteSpace && ((c == ' ') || (c == '\t') || isNewLine((char)c)) && !feof(fp));
+
+ if (c == '"')
+ {
+ if (state == BLOCK)
+ {
+ bTerminal = false;
+ ungetc(c, fp);
+ ODBlock * child = new ODBlock();
+ addStatement(*child);
+ if (!child->loadScript(fp))
+ return false;
+ }
+ else
+ {
+ if (state != WAIT_IDENT && state != IDENT)
+ {
+ lastError = ODSyntaxError(ODSyntaxError::ODSE_UNEX_QUOTE).asString();
+ return false;
+ }
+ ignoreWhiteSpace = bQuote;
+ bQuote = !bQuote;
+ state = IDENT;
+ }
+ }
+ else
+ {
+ if (bQuote)
+ {
+ PX_ASSERT(state == IDENT);
+ //if (currindex >= identSize)
+ // {
+ // identSize = 2*currindex + 4;
+ // char * newi = new char [identSize+1];
+ // if (identifier)
+ // strcpy(newi,identifier);
+ // delete [] identifier;
+ // identifier = newi;
+ // }
+ identifier[currindex] = (char) c;
+ identifier[currindex+1] = 0;
+ currindex++;
+ }
+ else
+ {
+ switch (c)
+ {
+ case '#':
+ while(!isNewLine((char)fgetc(fp))) ; //read and discard line
+ break;
+ case '/':
+ while(fgetc(fp) != '/') ; //read and discard comment
+ break;
+ case '{':
+ if (state != WAIT_BLOCK && state != IDENT)
+ {
+ lastError = ODSyntaxError(ODSyntaxError::ODSE_UNEX_OBRACE).asString();//identifier can be followed by block w/o whitespace inbetween
+ return false;
+ }
+ state = BLOCK;
+ break;
+ case '}':
+ if (state != BLOCK)
+ {
+ lastError = ODSyntaxError(ODSyntaxError::ODSE_UNEX_CBRACE).asString();
+ return false;
+ }
+ return true;
+ default:
+ //text
+ //our identifier?
+ if (state == BLOCK)
+ {
+ bTerminal = false;
+ ungetc(c, fp);
+ ODBlock * child = new ODBlock();
+ addStatement(*child);
+ if (!child->loadScript(fp))
+ return false;
+ }
+ else
+ {
+ if (state != WAIT_IDENT && state != IDENT)
+ {
+ lastError = ODSyntaxError(ODSyntaxError::ODSE_UNEX_LITERAL).asString();
+ return false;
+ }
+ if (state == IDENT && c == ';') //terminal ended
+ return true;
+ state = IDENT;
+ //if (currindex >= identSize)
+ // {
+ // identSize = 2*currindex + 4;
+ // char * newi = new char [identSize+1];
+ // if (identifier)
+ // strcpy(newi,identifier);
+ // delete [] identifier;
+ // identifier = newi;
+ // }
+ identifier[currindex] = (char)c;
+ identifier[currindex+1] = 0;
+ currindex++;
+ }
+ }
+ }
+ }
+ }
+ //eof and block didn't close
+ lastError = ODSyntaxError(ODSyntaxError::ODSE_UNEX_EOF).asString();
+ return false;
+}
+
+ODBlock::ODBlock()
+{
+ //create empty block
+ identifier[0] = '\0';
+ identSize = 0;
+ bTerminal = true;
+ termiter = NULL;
+ subBlocks.reserve(32);
+}
+
+ODBlock::~ODBlock()
+{
+ //free the contents
+ ODBlockList::Iterator i;
+ for (i = subBlocks.begin(); i != subBlocks.end(); ++i)
+ delete (*i);
+ //free the pointers
+ subBlocks.clear();
+
+ //delete [] identifier;
+ identifier[0] = '\0';
+ identSize = 0;
+}
+
+
+bool ODBlock::saveScript(SampleFramework::File * fp,bool bQuote)
+{
+ static int tablevel = 1;
+ static int retVal = 0;
+ int j;
+ //save the script in said file should be stream!!
+ for (j=0; j<tablevel-1; j++)
+ retVal = fprintf(fp,"\t");
+ if (bQuote)
+ retVal = fprintf(fp,"\"");
+ if (identifier)
+ retVal = fprintf(fp, "%s", identifier);
+ else
+ retVal = fprintf(fp,"_noname");
+ if (bQuote)
+ retVal = fprintf(fp,"\"");
+ if (!bTerminal)
+ {
+ retVal =fprintf(fp,"\n");
+ for (j=0; j<tablevel; j++)
+ retVal = fprintf(fp,"\t");
+ retVal = fprintf(fp,"{\n");
+ tablevel ++;
+ for (physx::PxU32 i = 0; i < subBlocks.size(); ++i)
+ (subBlocks[i])->saveScript(fp,bQuote);
+ tablevel --;
+ for (j=0; j<tablevel; j++)
+ retVal = fprintf(fp,"\t");
+ retVal = fprintf(fp,"}\n");
+ }
+ else
+ retVal = fprintf(fp,";\n");
+
+ PX_ASSERT( retVal >= 0 );
+ // added this return to make this compile on snc & release
+ return retVal >= 0;
+}
+
+
+const char * ODBlock::ident()
+{
+ static char noname[] = "_noname";
+ if (identifier)
+ return identifier;
+ else
+ return noname;
+}
+
+
+bool ODBlock::isTerminal()
+{
+ return bTerminal;
+}
+
+
+void ODBlock::ident(const char * i)
+{
+ if (!i) return;
+ strcpy(identifier,i);
+}
+
+
+void ODBlock::addStatement(ODBlock &b)
+{
+ bTerminal = false;
+ subBlocks.pushBack(&b);
+}
+
+void ODBlock::reset() //prepares to get first immediate terminal child of current block
+{
+ termiter = subBlocks.begin();
+}
+
+bool ODBlock::moreTerminals() //returns true if more terminals are available
+{
+ //skip any nonterminals
+ while ( (termiter != subBlocks.end()) && !(*termiter)->bTerminal)
+ ++termiter;
+ return termiter != subBlocks.end(); //return true if not the end yet
+}
+
+char * ODBlock::nextTerminal() //returns a pointer to the next terminal string.
+{
+ char * s = (*termiter)->identifier;
+ ++termiter;
+
+ static char noname[] = "_noname";
+ if (s)
+ return s;
+ else
+ return noname;
+}
+
+bool ODBlock::moreSubBlocks() //returns true if more sub blocks are available
+{
+ return termiter != subBlocks.end(); //return true if not the end yet
+}
+ODBlock * ODBlock::nextSubBlock() //returns a pointer to the next sub block.
+{
+ ODBlock * b = (*termiter);
+ ++termiter;
+ return b;
+}
+
+
+ODBlock * ODBlock::getBlock(const char * ident,bool bRecursiveSearch) //returns block with given identifier, or NULL.
+{
+ ODBlock * b;
+ if (identifier && ident && strncmp(identifier,ident,OD_MAXID) == 0)
+ return this;
+ else
+ {
+ if (bTerminal)
+ return NULL;
+ else
+ {
+ ODBlockList::Iterator i;
+ for (i = subBlocks.begin(); i != subBlocks.end(); ++i)
+ if (bRecursiveSearch)
+ {
+ b = (*i)->getBlock(ident,true);
+ if (b)
+ return b;
+ }
+ else
+ {
+ if ((*i)->identifier && ident && strncmp((*i)->identifier,ident,OD_MAXID) == 0)
+ return (*i);
+ }
+ return NULL;
+ }
+ }
+
+}
+
+// hig level macro functs, return true on success:
+bool ODBlock::getBlockInt(const char * ident, int* p, unsigned count) //reads blocks of form: ident{ 123; 123; ... }
+{
+ ODBlock* temp = getBlock(ident);
+ if (temp)
+ {
+ temp->reset();
+ for(; count && temp->moreTerminals(); --count)
+ if(p)
+ sscanf(temp->nextTerminal(),"%d", p++);
+
+ return !count;
+ }
+ return false;
+}
+
+// hig level macro functs, return true on success:
+bool ODBlock::getBlockU32(const char * ident, physx::PxU32* p, unsigned count) //reads blocks of form: ident{ 123;}
+{
+ ODBlock* temp = getBlock(ident);
+ if (temp)
+ {
+ temp->reset();
+ for(; count && temp->moreTerminals(); --count)
+ if(p)
+ sscanf(temp->nextTerminal(),"%u", p++);
+
+ return !count;
+ }
+ return false;
+}
+
+bool ODBlock::getBlockString(const char * ident, const char ** p) //of form: ident{abcdef;}
+{
+ ODBlock * temp = getBlock(ident);
+ if (temp)
+ {
+ temp->reset();
+ if (temp->moreTerminals())
+ {
+ *p = temp->nextTerminal();
+ return true;
+ }
+ }
+ return false;
+}
+bool ODBlock::getBlockStrings(const char * ident, const char ** p, unsigned numStrings) //of form: ident{abcdef; abcdef;...}
+{
+ ODBlock * temp= getBlock(ident);
+ if (temp)
+ {
+ temp->reset();
+ for (unsigned int n=0; n<numStrings; n++)
+ {
+ if (temp->moreTerminals())
+ {
+ p[n] = temp->nextTerminal();
+ }
+ }
+ }
+ return false;
+}
+bool ODBlock::getBlockFloat(const char * ident, float *p) //of form: ident{123.456;}
+{
+ ODBlock * temp = getBlock(ident);
+ if (temp)
+ {
+ temp->reset();
+ if (temp->moreTerminals())
+ {
+ if(p) sscanf(temp->nextTerminal(),"%f",p);
+ return true;
+ }
+ }
+ return false;
+}
+bool ODBlock::getBlockFloats(const char * ident, float *p, unsigned numfloats)//form: ident{12.3; 12.3; 12.3; ... };
+{
+ ODBlock * temp = getBlock(ident);
+ if (temp)
+ {
+ temp->reset();
+ for (unsigned int n=0; n<numfloats; n++)
+ if (temp->moreTerminals()) sscanf(temp->nextTerminal(),"%f",&(p[n]));
+
+ return true;
+ }
+ return false;
+}
+
+bool ODBlock::addBlockFloats(const char * ident, float *f, unsigned numfloats)
+{
+ char buf[32];
+ ODBlock & newBlock = *new ODBlock();
+
+ addStatement(newBlock);
+ newBlock.ident(ident);
+
+ for (unsigned i = 0; i < numfloats; i++)
+ {
+ ODBlock & floatBlock = *new ODBlock();
+ newBlock.addStatement(floatBlock);
+
+ //_gcvt_s(buf, 32, f[i],5); //gcc doesn't support this
+ sprintf(buf, "%.5f", f[i]);
+
+ floatBlock.ident(buf);
+ }
+ return true;
+}
+
+bool ODBlock::addBlockInts(const char * ident, int *f, unsigned numInts)
+{
+ char buf[32];
+ ODBlock & newBlock = *new ODBlock();
+
+ addStatement(newBlock);
+ newBlock.ident(ident);
+
+ for (unsigned i = 0; i < numInts; i++)
+ {
+ ODBlock & floatBlock = *new ODBlock();
+ newBlock.addStatement(floatBlock);
+ //_itoa_s(f[i], buf, 32, 10); //gcc doesn't support this
+ sprintf(buf, "%d", f[i]);
+ floatBlock.ident(buf);
+ }
+ return true;
+}
+
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/SampleApplication.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleApplication.cpp
new file mode 100644
index 00000000..bb188f4b
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleApplication.cpp
@@ -0,0 +1,487 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+#include <PsUtilities.h>
+#include <SampleApplication.h>
+#include <SampleCommandLine.h>
+#include <SampleAssetManager.h>
+#include <Renderer.h>
+#include <RendererMemoryMacros.h>
+#include <SamplePlatform.h>
+#include "SampleFrameworkInputEventIds.h"
+
+#include "PsString.h"
+#include "PsFoundation.h"
+#include "PsUtilities.h"
+
+namespace Ps = physx::shdfnd;
+
+//#define RENDERER_USE_OPENGL_ON_WINDONWS 1
+
+#if defined(SMOOTH_CAM)
+const float g_smoothCamBaseVel = 6.0f;
+const float g_smoothCamFastMul = 4.0f;
+const float g_smoothCamPosLerp = 0.4f;
+
+const float g_smoothCamRotSpeed = 0.005f;
+const float g_smoothCamRotLerp = 0.4f;
+#endif
+
+#include "FrameworkFoundation.h"
+
+using namespace SampleFramework;
+
+static PxMat44 EulerToMat33(const PxVec3& e)
+{
+ const float c1 = cosf(e.z);
+ const float s1 = sinf(e.z);
+ const float c2 = cosf(e.y);
+ const float s2 = sinf(e.y);
+ const float c3 = cosf(e.x);
+ const float s3 = sinf(e.x);
+ PxMat44 m;
+ m.column0 = PxVec4(c1*c2, -s1*c2, s2, 0.0f);
+ m.column1 = PxVec4((s1*c3)+(c1*s2*s3), (c1*c3)-(s1*s2*s3),-c2*s3, 0.0f);
+ m.column2 = PxVec4((s1*s3)-(c1*s2*c3), (c1*s3)+(s1*s2*c3), c2*c3, 0.0f);
+ m.column3 = PxVec4(0,0,0,1);
+ return m;
+}
+
+static PxVec3 Mat33ToEuler(const PxMat44& m)
+{
+ const PxF32 epsilon = 0.99999f;
+ PxVec3 e, x, y, z;
+
+ x = PxVec3(m.column0.x, m.column1.x, m.column2.x);
+ y = PxVec3(m.column0.y, m.column1.y, m.column2.y);
+ z = PxVec3(m.column0.z, m.column1.z, m.column2.z);
+
+ if(x.z > epsilon)
+ {
+ e.x = PxAtan2(z.y, y.y);
+ e.y = PxPi * 0.5f;
+ e.z = 0;
+ }
+ else if(x.z < -epsilon)
+ {
+ e.x = PxAtan2(z.y, y.y);
+ e.y = -PxPi * 0.5f;
+ e.z = 0;
+ }
+ else
+ {
+ e.x = PxAtan2(-y.z, z.z);
+ e.y = PxAsin(x.z);
+ e.z = PxAtan2(-x.y, x.x);
+ }
+ return e;
+}
+
+SampleApplication::SampleApplication(const SampleCommandLine &cmdline, const char *assetPathPrefix, PxI32 camMoveButton) :
+ m_cmdline(cmdline)
+, m_disableRendering(false)
+, m_rotationSpeedScale(200.0f)
+, m_moveSpeedScale(40.0f)
+, m_rightStickRotate(false)
+, m_rewriteBuffers(false)
+{
+ m_platform->setCWDToEXE();
+
+ if (assetPathPrefix)
+ {
+ if (!searchForPath(assetPathPrefix, m_assetPathPrefix, PX_ARRAY_SIZE(m_assetPathPrefix), true, 20))
+ {
+ RENDERER_ASSERT(false, "assetPathPrefix could not be found in any of the parent directories!");
+ m_assetPathPrefix[0] = 0;
+ }
+ }
+ else
+ {
+ RENDERER_ASSERT(assetPathPrefix, "assetPathPrefix must not be NULL (try \"media\" instead)");
+ m_assetPathPrefix[0] = 0;
+ }
+
+ m_renderer = 0;
+ m_sceneSize = 1.0f;
+ m_assetManager = 0;
+ m_timeCounter = 0;
+ m_camMoveButton = camMoveButton;
+
+}
+
+SampleApplication::~SampleApplication(void)
+{
+ RENDERER_ASSERT(!m_renderer, "Renderer was not released prior to window closure.");
+ RENDERER_ASSERT(!m_assetManager, "Asset Manager was not released prior to window closure.");
+
+ DELETESINGLE(m_platform);
+
+ clearSearchPaths();
+}
+
+void SampleApplication::setEyeTransform(const PxMat44& eyeTransform)
+{
+ m_worldToView.setInverseTransform(eyeTransform);
+ m_eyeRot = Mat33ToEuler(eyeTransform);
+#if defined(SMOOTH_CAM)
+ m_targetEyePos = m_worldToView.getInverseTransform().getPosition();
+ m_targetEyeRot = m_eyeRot;
+#endif
+}
+
+void SampleApplication::setEyeTransform(const PxVec3& pos, const PxVec3& rot)
+{
+ PxMat44 eye;
+ m_eyeRot = rot;
+ eye = EulerToMat33(m_eyeRot);
+ eye.setPosition(pos);
+#if defined(SMOOTH_CAM)
+ m_targetEyePos = pos;
+ m_targetEyeRot = m_eyeRot;
+#endif
+
+ m_worldToView.setInverseTransform(eye);
+}
+
+void SampleApplication::setViewTransform(const PxMat44 &viewTransform)
+{
+ m_worldToView.setForwardTransform(viewTransform);
+ m_eyeRot = Mat33ToEuler( m_worldToView.getInverseTransform() );
+#if defined(SMOOTH_CAM)
+ m_targetEyePos = m_worldToView.getInverseTransform().getPosition();
+ m_targetEyeRot = m_eyeRot;
+#endif
+}
+
+const PxMat44& SampleApplication::getViewTransform() const
+{
+ return m_worldToView.getForwardTransform();
+}
+
+void SampleApplication::onOpen(void)
+{
+ m_platform->preRendererSetup();
+
+ char assetDir[1024];
+ Ps::strlcpy(assetDir, sizeof(assetDir), m_assetPathPrefix);
+ Ps::strlcat(assetDir, sizeof(assetDir), "/SampleRenderer/4/");
+
+ m_eyeRot = PxVec3(0,0,0);
+ PxMat44 eye = PxMat44(PxIdentity);
+ const PxVec3 pos = PxVec3(0.0f, 2.0f, 16.0f);
+ eye.setPosition(pos);
+ m_worldToView.setInverseTransform(eye);
+#if defined(SMOOTH_CAM)
+ m_targetEyePos = pos;
+ m_targetEyeRot = m_eyeRot;
+#endif
+
+ // default renderer drivers for various platforms...
+ SampleRenderer::RendererDesc renDesc;
+ setupRendererDescription(renDesc);
+#if defined RENDERER_USE_OPENGL_ON_WINDONWS
+ renDesc.driver = SampleRenderer::Renderer::DRIVER_OPENGL;
+#endif
+
+ // check to see if the user wants to override the renderer driver...
+ if(m_cmdline.hasSwitch("ogl")) renDesc.driver = SampleRenderer::Renderer::DRIVER_OPENGL;
+ else if(m_cmdline.hasSwitch("gles2")) renDesc.driver = SampleRenderer::Renderer::DRIVER_GLES2;
+ else if(m_cmdline.hasSwitch("d3d9")) renDesc.driver = SampleRenderer::Renderer::DRIVER_DIRECT3D9;
+ else if(m_cmdline.hasSwitch("d3d11")) renDesc.driver = SampleRenderer::Renderer::DRIVER_DIRECT3D11;
+ else if(m_cmdline.hasSwitch("gcm")) renDesc.driver = SampleRenderer::Renderer::DRIVER_LIBGCM;
+ else if(m_cmdline.hasSwitch("null")) renDesc.driver = SampleRenderer::Renderer::DRIVER_NULL;
+
+#if defined(RENDERER_ANDROID)
+ renDesc.windowHandle = (physx::PxU64)android_window_ptr;
+#endif
+
+ m_renderer = SampleRenderer::Renderer::createRenderer(renDesc, assetDir);
+ m_platform->postRendererSetup(m_renderer);
+
+ m_timeCounter = m_time.getCurrentCounterValue();
+
+ m_assetManager = new SampleAssetManager(*m_renderer);
+ addSearchPath(m_assetPathPrefix);
+ addSearchPath(assetDir);
+ onInit();
+
+ // make sure the resize method is called once
+ if (m_renderer)
+ {
+ PxU32 width,height;
+ m_renderer->getWindowSize(width, height);
+ onResize(width, height);
+ }
+}
+
+bool SampleApplication::onClose(void)
+{
+ onShutdown();
+ DELETESINGLE(m_assetManager);
+
+ SAFE_RELEASE(m_renderer);
+ m_platform->postRendererRelease();
+
+ return true;
+}
+
+inline float SmoothStepPolynomial( float s )
+{
+ if( s <= 0 ) return 0;
+ if( s >= 1 ) return 1;
+ return s*s*(3-2*s);
+}
+
+template <typename T>
+T SmoothStep( const T& start, const T& end, float s )
+{
+ float ss = SmoothStepPolynomial( s );
+ return ss * (end - start) + start;
+}
+
+void SampleApplication::onDraw(void)
+{
+
+ if (!getRenderer())
+ {
+ return;
+ }
+
+ PX_PROFILE_ZONE("OnDraw", 0);
+
+ physx::PxU64 qpc = m_time.getCurrentCounterValue();
+ static float sToSeconds = float(m_time.getBootCounterFrequency().mNumerator) / float(m_time.getBootCounterFrequency().mDenominator * m_time.sNumTensOfNanoSecondsInASecond);
+ float dtime = float(qpc - m_timeCounter) * sToSeconds;
+ m_lastDTime = dtime;
+ m_timeCounter = qpc;
+ PX_ASSERT(dtime > 0);
+ if(dtime > 0)
+ {
+ dtime = tweakElapsedTime(dtime);
+
+ {
+ PX_PROFILE_ZONE("PreRender", 0);
+ onTickPreRender(dtime);
+ }
+ if(m_renderer)
+ {
+ PX_PROFILE_ZONE("onRender", 0);
+ if(!m_disableRendering)
+ {
+ onRender();
+ }
+ }
+ {
+ PX_PROFILE_ZONE("onPostRender", 0);
+ onTickPostRender(dtime);
+ }
+
+ if(m_renderer && !m_disableRendering)
+ {
+ m_rewriteBuffers = m_renderer->swapBuffers();
+ }
+
+ // update scene...
+
+ PxMat44 tmp = m_worldToView.getInverseTransform();
+ PxMat44 eye = EulerToMat33(m_eyeRot);
+ eye.column3 = tmp.column3;
+
+ PxVec3* targetParam;
+#if defined(SMOOTH_CAM)
+ const float eyeSpeed = m_sceneSize * g_smoothCamBaseVel * dtime * (getPlatform()->getSampleUserInput()->getDigitalInputEventState(CAMERA_SHIFT_SPEED) ? g_smoothCamFastMul : 1.0f);
+ targetParam = &m_targetEyePos;
+#else
+ const float eyeSpeed = m_sceneSize * 4.0f * dtime * (getPlatform()->getSampleUserInput()->getDigitalInputEventState(CAMERA_SHIFT_SPEED) ? 4.0f : 1.0f);
+ targetParam = &eye.t;
+#endif
+
+ const PxVec3 column2 = eye.getBasis(2);
+ const PxVec3 column0 = eye.getBasis(0);
+ const PxVec3 column1 = eye.getBasis(1);
+
+ if(getPlatform()->getSampleUserInput()->getDigitalInputEventState(CAMERA_MOVE_FORWARD))
+ *targetParam -= column2 * eyeSpeed;
+ if(getPlatform()->getSampleUserInput()->getDigitalInputEventState(CAMERA_MOVE_LEFT))
+ *targetParam -= column0 * eyeSpeed;
+ if(getPlatform()->getSampleUserInput()->getDigitalInputEventState(CAMERA_MOVE_BACKWARD))
+ *targetParam += column2 * eyeSpeed;
+ if(getPlatform()->getSampleUserInput()->getDigitalInputEventState(CAMERA_MOVE_RIGHT))
+ *targetParam += column0 * eyeSpeed;
+ if(getPlatform()->getSampleUserInput()->getDigitalInputEventState(CAMERA_MOVE_UP))
+ *targetParam += column1 * eyeSpeed;
+ if(getPlatform()->getSampleUserInput()->getDigitalInputEventState(CAMERA_MOVE_DOWN))
+ *targetParam -= column1 * eyeSpeed;
+
+ // move forward from gamepad
+ *targetParam -= column2 * eyeSpeed * getPlatform()->getSampleUserInput()->getAnalogInputEventState(CAMERA_GAMEPAD_MOVE_FORWARD_BACK) * m_moveSpeedScale * dtime;
+ // strafe from gamepad
+ *targetParam += column0 * eyeSpeed * getPlatform()->getSampleUserInput()->getAnalogInputEventState(CAMERA_GAMEPAD_MOVE_LEFT_RIGHT) * m_moveSpeedScale* dtime;
+
+#if defined(SMOOTH_CAM)
+ PxVec3 eye_t = eye.getPosition();
+ eye_t = eye_t + (m_targetEyePos - eye_t) * g_smoothCamPosLerp;
+ eye.setPosition(eye_t);
+#endif
+
+ // rotate from gamepad
+ {
+ const PxF32 rotationSpeed = m_rotationSpeedScale * dtime;
+ PxF32 dx = getPlatform()->getSampleUserInput()->getAnalogInputEventState(CAMERA_GAMEPAD_ROTATE_LEFT_RIGHT) * rotationSpeed;
+ PxF32 dy = getPlatform()->getSampleUserInput()->getAnalogInputEventState(CAMERA_GAMEPAD_ROTATE_UP_DOWN) * rotationSpeed;
+ rotateCamera(dx, dy);
+ }
+
+ m_worldToView.setInverseTransform(eye);
+ }
+}
+
+// When holding down the mouse button and dragging across the edge of the window,
+// the input provider will spit out nonsensical delta values... so threshold appropriately
+void thresholdCameraRotate(physx::PxReal& dx, physx::PxReal& dy)
+{
+ static const physx::PxReal invalidDelta = 1000.f;
+ if ( physx::PxAbs(dx) > invalidDelta )
+ dx = physx::PxSign(dx);
+ if ( physx::PxAbs(dy) > invalidDelta )
+ dy = physx::PxSign(dy);
+}
+
+void SampleApplication::onPointerInputEvent(const InputEvent& ie, physx::PxU32 x, physx::PxU32 y, physx::PxReal dx, physx::PxReal dy, bool val)
+{
+ switch (ie.m_Id)
+ {
+ case CAMERA_MOUSE_LOOK:
+ {
+ if(getPlatform()->getSampleUserInput()->getDigitalInputEventState(CAMERA_MOVE_BUTTON))
+ {
+ thresholdCameraRotate(dx, dy);
+ rotateCamera(dx, dy);
+ }
+ }
+ break;
+ }
+}
+
+void SampleApplication::onDigitalInputEvent(const InputEvent& , bool val)
+{
+}
+
+void SampleApplication::moveCamera(PxF32 dx, PxF32 dy)
+{
+ PxMat44 tmp = m_worldToView.getInverseTransform();
+ PxMat44 eye = EulerToMat33(m_eyeRot);
+ eye.column3 = tmp.column3;
+
+ PxVec3* targetParam;
+#if defined(SMOOTH_CAM)
+ const float eyeSpeed = m_sceneSize * g_smoothCamBaseVel * m_lastDTime * (getPlatform()->getSampleUserInput()->getDigitalInputEventState(CAMERA_SHIFT_SPEED) ? g_smoothCamFastMul : 1.0f);
+ targetParam = &m_targetEyePos;
+#else
+ const float eyeSpeed = m_sceneSize * 4.0f * m_lastDTime * (getPlatform()->getSampleUserInput()->getDigitalInputEventState(CAMERA_SHIFT_SPEED) ? 4.0f : 1.0f);
+ targetParam = &eye.t;
+#endif
+
+ const PxVec3 column2 = eye.getBasis(2);
+ const PxVec3 column0 = eye.getBasis(0);
+
+ // strafe from gamepad
+ *targetParam += column0 * eyeSpeed * dx * m_moveSpeedScale* m_lastDTime;
+ // move forward from gamepad
+ *targetParam -= column2 * eyeSpeed * dy * m_moveSpeedScale * m_lastDTime;
+
+#if defined(SMOOTH_CAM)
+ PxVec3 eye_t = eye.getPosition();
+ eye_t = eye_t + (m_targetEyePos - eye_t) * g_smoothCamPosLerp;
+ eye.setPosition(eye_t);
+#endif
+
+ m_worldToView.setInverseTransform(eye);
+}
+
+void SampleApplication::onAnalogInputEvent(const InputEvent& ie, float val)
+{
+ switch (ie.m_Id)
+ {
+ case CAMERA_GAMEPAD_ROTATE_LEFT_RIGHT:
+ {
+ rotateCamera((PxF32)val, (PxF32)0.0);
+ }
+ break;
+ case CAMERA_GAMEPAD_ROTATE_UP_DOWN:
+ {
+ rotateCamera((PxF32)0.0, (PxF32)val);
+ }
+ break;
+ case CAMERA_GAMEPAD_MOVE_LEFT_RIGHT:
+ {
+ moveCamera((PxF32)val, (PxF32)0.0);
+ }
+ break;
+ case CAMERA_GAMEPAD_MOVE_FORWARD_BACK:
+ {
+ moveCamera((PxF32)0.0, (PxF32)val);
+ }
+ break;
+ }
+}
+
+void SampleApplication::rotateCamera(PxF32 dx, PxF32 dy)
+{
+ const float eyeCap = 1.5f;
+#if defined(SMOOTH_CAM)
+ m_targetEyeRot.x -= dy * g_smoothCamRotSpeed;
+ m_targetEyeRot.y += dx * g_smoothCamRotSpeed;
+ if(m_targetEyeRot.x > eyeCap) m_targetEyeRot.x = eyeCap;
+ if(m_targetEyeRot.x < -eyeCap) m_targetEyeRot.x = -eyeCap;
+
+ m_eyeRot= m_eyeRot + (m_targetEyeRot - m_eyeRot) * g_smoothCamRotLerp;
+#else
+ const float eyeRotSpeed = 0.005f;
+ m_eyeRot.x -= dy * eyeRotSpeed;
+ m_eyeRot.y += dx * eyeRotSpeed;
+ if(m_eyeRot.x > eyeCap) m_eyeRot.x = eyeCap;
+ if(m_eyeRot.x < -eyeCap) m_eyeRot.x = -eyeCap;
+#endif
+}
+
+void SampleApplication::fatalError(const char * msg)
+{
+shdfnd::printFormatted("Fatal Error in SampleApplication: %s\n", msg);
+close();
+exit(1);
+}
+
+void SampleApplication::doInput()
+{
+ m_platform->doInput();
+}
+
+void SampleApplication::setupRendererDescription(SampleRenderer::RendererDesc& renDesc)
+{
+ m_platform->setupRendererDescription(renDesc);
+}
+
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/SampleAsset.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleAsset.cpp
new file mode 100644
index 00000000..dd7db24b
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleAsset.cpp
@@ -0,0 +1,44 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+#include <SampleAsset.h>
+#include "PsString.h"
+
+using namespace SampleFramework;
+
+SampleAsset::SampleAsset(Type type, const char *path) :
+ m_type(type)
+{
+ size_t len = strlen(path)+1;
+ m_path = new char[len];
+ physx::shdfnd::strlcpy(m_path, len, path);
+ m_numUsers = 0;
+}
+
+SampleAsset::~SampleAsset(void)
+{
+ if(m_path) delete [] m_path;
+}
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/SampleAssetManager.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleAssetManager.cpp
new file mode 100644
index 00000000..c1e19c4d
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleAssetManager.cpp
@@ -0,0 +1,436 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+#include <SampleAssetManager.h>
+#include <SampleAsset.h>
+#include <SampleMaterialAsset.h>
+#include <SampleTextureAsset.h>
+#include <SampleInputAsset.h>
+
+#include <Renderer.h>
+
+#include <stdio.h>
+#include "SamplePlatform.h"
+#include "ODBlock.h"
+
+// for PsString.h
+#include <PsString.h>
+#include <PxTkFile.h>
+
+namespace Ps = physx::shdfnd;
+
+#include "SampleXml.h"
+#include "extensions/PxDefaultStreams.h"
+
+using namespace SampleFramework;
+
+///////////////////////////////////////////////////////////////////////////////
+
+static std::vector<char*>* gSearchPaths = NULL;
+
+void SampleFramework::addSearchPath(const char* path)
+{
+ if(!path)
+ return;
+
+ const PxU32 len = *path ? (PxU32)strlen(path) : 0;
+ if(!len)
+ return;
+
+ const PxU32 len2 = len+2;
+ char* searchPath = new char[len2];
+ Ps::strlcpy(searchPath, len2, path);
+ if(path[len-1] != '/' && path[len-1] != '\\')
+ {
+ Ps::strlcat(searchPath, len2, "/");
+ }
+ if(!gSearchPaths)
+ gSearchPaths = new std::vector<char*>;
+ gSearchPaths->push_back(searchPath);
+}
+
+void SampleFramework::clearSearchPaths()
+{
+ if(!gSearchPaths)
+ return;
+ const PxU32 numSearchPaths = (PxU32)gSearchPaths->size();
+ for(PxU32 i=0; i<numSearchPaths; i++)
+ {
+ delete [] (*gSearchPaths)[i];
+ }
+ delete gSearchPaths;
+ gSearchPaths = NULL;
+}
+
+static void FixSeparators(char* path)
+{
+ for (unsigned i = 0; i < strlen(path); ++i)
+ if (path[i] == '\\' || path[i] == '/')
+ path[i] = SampleFramework::SamplePlatform::platform()->getPathSeparator()[0];
+}
+
+File* SampleFramework::findFile(const char* path, bool binary)
+{
+ if(!gSearchPaths)
+ return NULL;
+
+ File* file = NULL;
+ const PxU32 numSearchPaths = (PxU32)gSearchPaths->size();
+ for(PxU32 i=0; i<numSearchPaths; i++)
+ {
+ const char* prefix = (*gSearchPaths)[i];
+
+ char fullPath[512];
+ Ps::strlcpy(fullPath, 512, prefix);
+ Ps::strlcat(fullPath, 512, path);
+ FixSeparators(fullPath);
+ if(binary)
+ PxToolkit::fopen_s(&file, fullPath, "rb");
+ else
+ {
+ // text files open also for write
+ PxToolkit::fopen_s(&file, fullPath, "r+");
+ }
+ if(file) break;
+ }
+ return file;
+}
+
+const char* SampleFramework::findPath(const char* path)
+{
+ if(!gSearchPaths)
+ return path;
+
+ static char fullPath[512];
+
+ File* file = NULL;
+ const PxU32 numSearchPaths = (PxU32)gSearchPaths->size();
+ for(PxU32 i=0; i<numSearchPaths; i++)
+ {
+ const char* prefix = (*gSearchPaths)[i];
+ Ps::strlcpy(fullPath, 512, prefix);
+ Ps::strlcat(fullPath, 512, path);
+ FixSeparators(fullPath);
+ PxToolkit::fopen_s(&file, fullPath, "rb");
+ if(file) break;
+ }
+ if(file)
+ {
+ fclose(file);
+ return fullPath;
+ }
+ else
+ return path;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+SampleAssetManager::SampleAssetManager(SampleRenderer::Renderer& renderer,
+ SampleAssetCreator* fallbackAssetCreator) :
+ m_renderer(renderer),
+ m_fallbackAssetCreator(fallbackAssetCreator)
+{
+}
+
+SampleAssetManager::~SampleAssetManager(void)
+{
+ PX_ASSERT(m_assets.size() == 0);
+}
+
+SampleAsset* SampleAssetManager::getAsset(const char* path, SampleAsset::Type type)
+{
+ SampleAsset* asset = findAsset(path);
+ if(!asset)
+ {
+ asset = loadAsset(path, type);
+ }
+ if(asset && asset->getType() != type)
+ {
+ releaseAsset(*asset);
+ asset = 0;
+ }
+ if(asset)
+ {
+ addAssetUser(*asset);
+ }
+ return asset;
+}
+
+void SampleAssetManager::returnAsset(SampleAsset& asset)
+{
+ PX_ASSERT(asset.m_numUsers > 0);
+ if(asset.m_numUsers > 0)
+ {
+ asset.m_numUsers--;
+ }
+ if(asset.m_numUsers == 0)
+ {
+ releaseAsset(asset);
+ }
+}
+
+SampleAsset* SampleAssetManager::findAsset(const char* path)
+{
+ SampleAsset* asset = NULL;
+ PxU32 numAssets = (PxU32)m_assets.size();
+ for(PxU32 i=0; i<numAssets; i++)
+ {
+ if(!strcmp(m_assets[i]->getPath(), path))
+ {
+ asset = m_assets[i];
+ break;
+ }
+ }
+ return asset;
+}
+
+static const char* strext(const char* str)
+{
+ const char* ext = str;
+ while(str)
+ {
+ str = strchr(str, '.');
+ if(str)
+ {
+ str++;
+ ext = str;
+ }
+ }
+ return ext;
+}
+
+class FileExtensions
+{
+public:
+ explicit FileExtensions(const char** extensions, PxU32 numExtensions)
+ : mExtensions(extensions), mNumExtensions(numExtensions) { }
+
+ template<typename EnumType>
+ EnumType typeOf(const char* extension)
+ {
+ PxU32 type = 0;
+ while (type < mNumExtensions && (Ps::stricmp(extension, mExtensions[type]) != 0)) ++type;
+ return static_cast<EnumType>(type);
+ }
+
+protected:
+ const char** mExtensions;
+ PxU32 mNumExtensions;
+};
+
+enum FileType { TYPE_XML = 0, TYPE_DDS, TYPE_TGA, TYPE_ODS, TYPE_PVR, TYPE_BMP, NUM_TYPES, TYPE_NOT_SUPPORTED = NUM_TYPES };
+static const char* sSupportedExtensions[NUM_TYPES] = {"xml", "dds", "tga", "ods", "pvr", "bmp"};
+static FileExtensions sFileExtensions(sSupportedExtensions, NUM_TYPES);
+
+#if defined(RENDERER_ENABLE_PVR_SUPPORT)
+static FILE* findFileExchangeExtension(const char* path, bool binary, const char* origEnding, const char* newEnding)
+{
+ char pathPVR[512];
+ strcpy(pathPVR, path);
+ char* endStr = strstr(pathPVR, origEnding);
+ strcpy(endStr, newEnding);
+ return findFile(pathPVR, binary);
+}
+#endif
+
+SampleAsset* SampleAssetManager::loadAsset(const char* path, SampleAsset::Type type)
+{
+ SampleAsset* asset = NULL;
+ const char* extension = strext(path);
+ if(extension && *extension)
+ {
+ FileType fileType = sFileExtensions.typeOf<FileType>(extension);
+ if (TYPE_NOT_SUPPORTED != fileType )
+ {
+ File* file = NULL;
+#if defined(RENDERER_ENABLE_PVR_SUPPORT)
+ if(fileType == TYPE_DDS)
+ {
+ file = findFileExchangeExtension(path, true, ".dds", ".pvr");
+ fileType = TYPE_PVR;
+ }
+#endif
+ if(!file)
+ file = findFile(path, fileType != TYPE_ODS);
+
+ if(!file)
+ PxToolkit::fopen_s(&file, path, fileType != TYPE_ODS ? "rb" : "r+");
+
+ if(file)
+ {
+ switch(fileType)
+ {
+ case TYPE_XML:
+ asset = loadXMLAsset(*file, path);
+ break;
+ case TYPE_DDS:
+ asset = loadTextureAsset(*file, path, SampleTextureAsset::DDS);
+ break;
+ case TYPE_PVR:
+ asset = loadTextureAsset(*file, path, SampleTextureAsset::PVR);
+ break;
+ case TYPE_BMP:
+ asset = loadTextureAsset(*file, path, SampleTextureAsset::BMP);
+ break;
+ case TYPE_TGA:
+ asset = loadTextureAsset(*file, path, SampleTextureAsset::TGA);
+ break;
+ case TYPE_ODS:
+ asset = loadODSAsset(*file, path);
+ break;
+ case TYPE_NOT_SUPPORTED:
+ default:
+ PX_ALWAYS_ASSERT();
+ };
+ fclose(file);
+ }
+ }
+
+ if (NULL == asset)
+ {
+ if (m_fallbackAssetCreator)
+ {
+ asset = m_fallbackAssetCreator->create(path, type);
+ }
+ if (NULL == asset)
+ {
+
+#define SAM_DEFAULT_MATERIAL "materials/simple_lit.xml"
+
+#if defined(RENDERER_ENABLE_PVR_SUPPORT)
+# define SAM_DEFAULT_TEXTURE "textures/test.pvr"
+#else
+# define SAM_DEFAULT_TEXTURE "textures/test.dds"
+#endif
+
+ // report the missing asset
+ char msg[1024];
+
+ if (type == SampleAsset::ASSET_MATERIAL && strcmp(path, SAM_DEFAULT_MATERIAL) ) // Avoid infinite recursion
+ {
+ Ps::snprintf(msg, sizeof(msg), "Could not find material: %s, loading default material: %s",
+ path, SAM_DEFAULT_MATERIAL);
+ RENDERER_OUTPUT_MESSAGE(&m_renderer, msg);
+
+ return loadAsset(SAM_DEFAULT_MATERIAL, type); // Try to use the default asset
+ }
+ else if (type == SampleAsset::ASSET_TEXTURE)
+ {
+ Ps::snprintf(msg, sizeof(msg), "Could not find texture: %s, loading default texture: %s",
+ path, SAM_DEFAULT_TEXTURE);
+ RENDERER_OUTPUT_MESSAGE(&m_renderer, msg);
+
+ return loadAsset(SAM_DEFAULT_TEXTURE, type); // Try to use the default asset
+ }
+ else if (fileType == TYPE_ODS)
+ {
+ Ps::snprintf(msg, sizeof(msg), "Could not find input definition: %s", path);
+ RENDERER_OUTPUT_MESSAGE(&m_renderer, msg);
+ }
+ }
+ }
+ }
+ //PX_ASSERT(asset && asset->isOk());
+ if(asset && !asset->isOk())
+ {
+ deleteAsset(asset);
+ asset = 0;
+ }
+ if(asset)
+ {
+ addAsset(asset);
+ }
+ return asset;
+}
+
+void SampleAssetManager::releaseAsset(SampleAsset& asset)
+{
+ PxU32 numAssets = (PxU32)m_assets.size();
+ PxU32 found = numAssets;
+ for(PxU32 i=0; i<numAssets; i++)
+ {
+ if(&asset == m_assets[i])
+ {
+ found = i;
+ break;
+ }
+ }
+ PX_ASSERT(found < numAssets);
+ if(found < numAssets)
+ {
+ m_assets[found] = m_assets.back();
+ m_assets.pop_back();
+ deleteAsset(&asset);
+ }
+}
+
+void SampleAssetManager::addAssetUser(SampleAsset& asset)
+{
+ asset.m_numUsers++;
+}
+
+void SampleAssetManager::addAsset(SampleAsset* asset)
+{
+ if (asset)
+ m_assets.push_back(asset);
+}
+
+void SampleAssetManager::deleteAsset(SampleAsset* asset)
+{
+ if (asset)
+ asset->release();
+}
+
+SampleAsset* SampleAssetManager::loadXMLAsset(File& file, const char* path)
+{
+ SampleAsset* asset = NULL;
+
+ PxDefaultFileInputData theBuffer(findPath(path));
+ FAST_XML::XmlBuilder builder;
+ physx::shdfnd::FastXml *xml = createFastXml(&builder);
+ xml->processXml(theBuffer, false);
+ FAST_XML::xml_node* rootnode = builder.rootnode();
+ if(!strcmp(rootnode->name(), "material"))
+ {
+ asset = new SampleMaterialAsset(*this, *rootnode, path);
+ }
+ xml->release();
+
+ return asset;
+}
+
+SampleAsset* SampleAssetManager::loadTextureAsset(File& file, const char* path, SampleTextureAsset::Type texType)
+{
+ SampleTextureAsset* asset = new SampleTextureAsset(getRenderer(), file, path, texType);
+ return asset;
+}
+
+SampleAsset* SampleAssetManager::loadODSAsset(File& file, const char* path)
+{
+ SampleAsset* asset = new SampleInputAsset(&file, path);
+ return asset;
+}
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/SampleCommandLine.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleCommandLine.cpp
new file mode 100644
index 00000000..91d21840
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleCommandLine.cpp
@@ -0,0 +1,426 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+#include "FrameworkFoundation.h"
+#include <SampleCommandLine.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "PxTkFile.h"
+#include "foundation/PxAssert.h"
+
+#ifdef WIN32
+#include <windows.h>
+#elif defined(ANDROID)
+typedef int errno_t;
+#endif
+
+#include "PsString.h"
+
+using namespace SampleFramework;
+namespace Ps = physx::shdfnd;
+
+static char **CommandLineToArgvA(const char *cmdLine, unsigned int &_argc)
+{
+ char **argv = 0;
+ char *_argv = 0;
+ unsigned int len = 0;
+ unsigned int argc = 0;
+ char a = 0;
+ unsigned int i = 0;
+ unsigned int j = 0;
+ bool in_QM = false;
+ bool in_TEXT = false;
+ bool in_SPACE = true;
+
+ len = (unsigned int)strlen(cmdLine);
+ i = ((len+2)/2)*sizeof(char*) + sizeof(char*);
+ argv = (char **)malloc(i + (len+2)*sizeof(char));
+ _argv = (char *)(((char *)argv)+i);
+ argv[0] = _argv;
+
+ i = 0;
+
+ a = cmdLine[i];
+ while(a)
+ {
+ if(in_QM)
+ {
+ if(a == '\"')
+ {
+ in_QM = false;
+ }
+ else
+ {
+ _argv[j] = a;
+ j++;
+ }
+ }
+ else
+ {
+ switch(a)
+ {
+ case '\"':
+ in_QM = true;
+ in_TEXT = true;
+ if(in_SPACE)
+ {
+ argv[argc] = _argv+j;
+ argc++;
+ }
+ in_SPACE = false;
+ break;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ if(in_TEXT)
+ {
+ _argv[j] = '\0';
+ j++;
+ }
+ in_TEXT = false;
+ in_SPACE = true;
+ break;
+ default:
+ in_TEXT = true;
+ if(in_SPACE)
+ {
+ argv[argc] = _argv+j;
+ argc++;
+ }
+ _argv[j] = a;
+ j++;
+ in_SPACE = false;
+ break;
+ }
+ }
+ i++;
+ a = cmdLine[i];
+ }
+ _argv[j] = '\0';
+ argv[argc] = 0;
+ _argc = argc;
+ return argv;
+}
+
+static bool isSwitchChar(char c)
+{
+ return (c == '-' || c == '/');
+}
+
+namespace
+{
+void operationOK(int e)
+{
+ PX_UNUSED(e);
+ PX_ASSERT(0 == e);
+}
+
+const char * const * getCommandLineArgumentsFromFile(unsigned int & argc, const char * programName, const char * commandLineFilePath)
+{
+ const char * const * argv = NULL;
+ argc = 0;
+ PX_ASSERT(NULL != programName);
+ PX_ASSERT(NULL != commandLineFilePath);
+ if(NULL != programName && NULL != commandLineFilePath)
+ {
+ File* commandLineFile = NULL;
+ operationOK(PxToolkit::fopen_s(&commandLineFile, commandLineFilePath, "r"));
+ if(NULL != commandLineFile)
+ {
+ operationOK(fseek(commandLineFile, 0, SEEK_END));
+ const unsigned int commandLineFileCount = static_cast<unsigned int>(ftell(commandLineFile));
+ rewind(commandLineFile);
+ const unsigned int bufferCount = static_cast<unsigned int>(::strlen(programName)) + 1 + commandLineFileCount + 1;
+ if(bufferCount > 0)
+ {
+ char * argsOwn = static_cast<char*>(::malloc(bufferCount));
+ Ps::strlcpy(argsOwn, bufferCount, programName);
+ Ps::strlcat(argsOwn, bufferCount, " ");
+ const unsigned int offset = static_cast<unsigned int>(::strlen(argsOwn));
+ PX_ASSERT((bufferCount - offset - 1) == commandLineFileCount);
+ if(NULL != fgets(argsOwn + offset, bufferCount - offset, commandLineFile))
+ {
+ argv = CommandLineToArgvA(argsOwn, argc);
+ }
+ ::free(argsOwn);
+ argsOwn = NULL;
+ }
+ operationOK(fclose(commandLineFile));
+ commandLineFile = NULL;
+ }
+ }
+ return argv;
+}
+} //namespace nameless
+
+SampleCommandLine::SampleCommandLine(unsigned int argc, const char * const * argv, const char * commandLineFilePathFallback)
+ :m_argc(0)
+ ,m_argv(NULL)
+ ,m_freeme(NULL)
+ ,m_argUsed(NULL)
+{
+ //initially, set to use inherent command line arguments
+ PX_ASSERT((0 != argc) && (NULL != argv) && "This class assumes argument 0 is always the executable path!");
+ m_argc = argc;
+ m_argv = argv;
+
+ //finalize init
+ initCommon(commandLineFilePathFallback);
+}
+
+SampleCommandLine::SampleCommandLine(const char * args, const char * commandLineFilePathFallback)
+ :m_argc(0)
+ ,m_argv(NULL)
+ ,m_freeme(NULL)
+ ,m_argUsed(NULL)
+{
+ //initially, set to use inherent command line arguments
+ unsigned int argc = 0;
+ const char * const * argvOwning = NULL;
+ argvOwning = CommandLineToArgvA(args, argc);
+ PX_ASSERT((0 != argc) && (NULL != argvOwning) && "This class assumes argument 0 is always the executable path!");
+ m_argc = argc;
+ m_argv = argvOwning;
+ m_freeme = const_cast<void *>(static_cast<const void *>(argvOwning));
+ argvOwning = NULL;
+
+ //finalize init
+ initCommon(commandLineFilePathFallback);
+}
+
+SampleCommandLine::~SampleCommandLine(void)
+{
+ if(m_freeme)
+ {
+ free(m_freeme);
+ m_freeme = NULL;
+ }
+ if(m_argUsed)
+ {
+ delete[] m_argUsed;
+ m_argUsed = NULL;
+ }
+}
+
+void SampleCommandLine::initCommon(const char * commandLineFilePathFallback)
+{
+ //if available, set to use command line arguments from file
+ const bool tryUseCommandLineArgumentsFromFile = ((1 == m_argc) && (NULL != commandLineFilePathFallback));
+ if(tryUseCommandLineArgumentsFromFile)
+ {
+ unsigned int argcFile = 0;
+ const char * const * argvFileOwn = NULL;
+ argvFileOwn = getCommandLineArgumentsFromFile(argcFile, m_argv[0], commandLineFilePathFallback);
+ if((0 != argcFile) && (NULL != argvFileOwn))
+ {
+ if(NULL != m_freeme)
+ {
+ ::free(m_freeme);
+ m_freeme = NULL;
+ }
+ m_argc = argcFile;
+ m_argv = argvFileOwn;
+ m_freeme = const_cast<void *>(static_cast<const void *>(argvFileOwn));
+ argvFileOwn = NULL;
+ }
+ }
+
+ //for tracking use-status of arguments
+ if((0 != m_argc) && (NULL != m_argv))
+ {
+ m_argUsed = new bool[m_argc];
+ for(unsigned int i = 0; i < m_argc; i++)
+ {
+ m_argUsed[i] = false;
+ }
+ }
+}
+
+unsigned int SampleCommandLine::getNumArgs(void) const
+{
+ return(m_argc);
+}
+
+const char * SampleCommandLine::getProgramName(void) const
+{
+ return(m_argv[0]);
+}
+
+unsigned int SampleCommandLine::unusedArgsBufSize(void) const
+{
+ unsigned int bufLen = 0;
+ for(unsigned int i = 1; i < m_argc; i++)
+ {
+ if((!m_argUsed[i]) && isSwitchChar(m_argv[i][0]))
+ {
+ bufLen += (unsigned int) strlen(m_argv[i]) + 1; // + 1 is for the space between unused args
+ }
+ }
+ if(bufLen != 0)
+ {
+ bufLen++; // if there are unused args add a space for the '\0' char.
+ }
+ return(bufLen);
+}
+
+const char* SampleCommandLine::getUnusedArgs(char *buf, unsigned int bufSize) const
+{
+ if(bufSize != 0)
+ {
+ buf[0] = '\0';
+ for(unsigned int i = 1; i < m_argc; i++)
+ {
+ if((!m_argUsed[i]) && isSwitchChar(m_argv[i][0]))
+ {
+ Ps::strlcat(buf, bufSize, m_argv[i]);
+ Ps::strlcat(buf, bufSize, " ");
+ }
+ }
+ }
+ return(buf);
+}
+
+//! has a given command-line switch?
+// e.g. s=="foo" checks for -foo
+bool SampleCommandLine::hasSwitch(const char *s, unsigned int argNum) const
+{
+ bool has = false;
+ PX_ASSERT(*s);
+ if(*s)
+ {
+ unsigned int n = (unsigned int) strlen(s);
+ unsigned int firstArg;
+ unsigned int lastArg;
+ if(argNum != invalidArgNum)
+ {
+ firstArg = argNum;
+ lastArg = argNum;
+ }
+ else
+ {
+ firstArg = 1;
+ lastArg = (m_argc > 1) ? (m_argc - 1) : 0;
+ }
+ for(unsigned int i=firstArg; i<=lastArg; i++)
+ {
+ const char *arg = m_argv[i];
+ // allow switches of '/', '-', and double character versions of both.
+ if( (isSwitchChar(*arg) && !Ps::strnicmp(arg+1, s, n) && ((arg[n+1]=='\0')||(arg[n+1]=='='))) ||
+ (isSwitchChar(*(arg+1)) && !Ps::strnicmp(arg+2, s, n) && ((arg[n+2]=='\0')||(arg[n+2]=='='))) )
+ {
+ m_argUsed[i] = true;
+ has = true;
+ break;
+ }
+ }
+ }
+ return has;
+}
+
+//! gets the value of a switch...
+// e.g. s="foo" returns "bar" if '-foo=bar' is in the commandline.
+const char *SampleCommandLine::getValue(const char *s, unsigned int argNum) const
+{
+ const char *value = 0;
+ PX_ASSERT(*s);
+ if(*s)
+ {
+ unsigned int firstArg;
+ unsigned int lastArg;
+ if(argNum != invalidArgNum)
+ {
+ firstArg = argNum;
+ lastArg = argNum;
+ }
+ else
+ {
+ firstArg = 1;
+ lastArg = m_argc - 1;
+ }
+ for(unsigned int i=firstArg; i<=lastArg; i++)
+ {
+ const char *arg = m_argv[i];
+ if(isSwitchChar(*arg))
+ {
+ arg++;
+ if(isSwitchChar(*arg)) // is it a double dash arg? '--'
+ {
+ arg++;
+ }
+ const char *st=s;
+ for(; *st && *arg && toupper(*st)==toupper(*arg) && *arg!='='; st++,arg++)
+ {
+ }
+ if(!*st && *arg=='=')
+ {
+ m_argUsed[i] = true;
+ value = arg+1;
+ break;
+ }
+ if(!*st && !*arg && ((i+1)<m_argc) && (!isSwitchChar(*m_argv[i+1])))
+ {
+ m_argUsed[i] = true;
+ value = m_argv[i+1];
+ break;
+ }
+ }
+ }
+ }
+ return value;
+}
+
+//! if the first argument is the given command.
+bool SampleCommandLine::isCommand(const char *s) const
+{
+ bool has = false;
+ const char *command = getCommand();
+ if(command && !Ps::stricmp(command, s))
+ {
+ has = true;
+ }
+ return has;
+}
+
+//! get the first argument assuming it isn't a switch.
+// e.g. for the command-line "myapp.exe editor -foo" it will return "editor".
+const char *SampleCommandLine::getCommand(void) const
+{
+ const char *command = 0;
+ if(m_argc > 1 && !isSwitchChar(*m_argv[1]))
+ {
+ command = m_argv[1];
+ }
+ return command;
+}
+
+//! whether or not an argument has been read already
+bool SampleCommandLine::isUsed(unsigned int argNum) const
+{
+ return argNum < m_argc ? m_argUsed[argNum] : false;
+}
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/SampleDirManager.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleDirManager.cpp
new file mode 100644
index 00000000..12bd98d7
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleDirManager.cpp
@@ -0,0 +1,121 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+#include "SampleDirManager.h"
+#include "SampleAssetManager.h"
+#include "SamplePlatform.h"
+#include "PsUtilities.h"
+#include "PxTkFile.h"
+#include "PsString.h"
+
+using namespace SampleFramework;
+
+static void FixPathSeparator(char* pathBuffer)
+{
+ char separator = SampleFramework::SamplePlatform::platform()->getPathSeparator()[0];
+
+ const size_t length = strlen(pathBuffer);
+ for(size_t i=0; i<length ; ++i)
+ {
+ if ('/' == pathBuffer[i] || '\\' == pathBuffer[i])
+ pathBuffer[i] = separator;
+ }
+}
+
+SampleDirManager::SampleDirManager(const char* relativePathRoot, bool isReadOnly, int maxRecursion) : mIsReadOnly(isReadOnly)
+{
+ if(!relativePathRoot || !SampleFramework::searchForPath(relativePathRoot, mPathRoot, PX_ARRAY_SIZE(mPathRoot), isReadOnly, maxRecursion))
+ {
+ shdfnd::printFormatted("path \"%s\" not found\n", relativePathRoot);
+ mPathRoot[0] = '\0';
+ }
+}
+
+#define MAX_PATH_LENGTH 256
+
+const char* SampleDirManager::getFilePath(const char* relativeFilePath, char* pathBuffer, bool testFileValidity)
+{
+ PX_ASSERT(pathBuffer);
+
+ bool flattenRelativeFilePaths = false;
+#if defined (RENDERER_IOS)
+ //iOS doesn't allow to share files in folders...
+ flattenRelativeFilePaths = !mIsReadOnly;
+#endif
+
+ strcpy(pathBuffer, getPathRoot());
+ strcat(pathBuffer, "/");
+
+ if (flattenRelativeFilePaths)
+ {
+ char flattendPath[MAX_PATH_LENGTH];
+ strcpy(flattendPath, relativeFilePath);
+ for (size_t i = 0; i < strlen(flattendPath); ++i)
+ {
+ if ('/' == flattendPath[i] || '\\' == flattendPath[i])
+ flattendPath[i] = '_';
+ }
+ strcat(pathBuffer, flattendPath);
+ }
+ else
+ {
+ strcat(pathBuffer, relativeFilePath);
+ if (!mIsReadOnly)
+ {
+ FixPathSeparator(pathBuffer);
+ //strip file from path and make sure the output directory exists
+ const char* ptr = strrchr(pathBuffer, '/');
+ if (!ptr)
+ ptr = strrchr(pathBuffer, '\\');
+
+ if (ptr)
+ {
+ char dir[MAX_PATH_LENGTH];
+ assert(MAX_PATH_LENGTH >= strlen(pathBuffer));
+ strcpy(dir, pathBuffer);
+ dir[ptr - pathBuffer] = '\0';
+ FixPathSeparator(dir);
+ SampleFramework::SamplePlatform::platform()->makeSureDirectoryPathExists(dir);
+ }
+ }
+ }
+
+ FixPathSeparator(pathBuffer);
+
+ if(testFileValidity)
+ {
+ File* fp = NULL;
+ PxToolkit::fopen_s(&fp, pathBuffer, "rb");
+ if(!fp)
+ {
+ // Kai: user can still get full path in the path buffer (side effect)
+ return NULL;
+ }
+ fclose(fp);
+ }
+
+ return pathBuffer;
+}
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/SampleInputAsset.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleInputAsset.cpp
new file mode 100644
index 00000000..2de45556
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleInputAsset.cpp
@@ -0,0 +1,100 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+
+#include "SampleInputAsset.h"
+#include "ODBlock.h"
+#include <PxTkFile.h>
+#include <PsString.h>
+
+using namespace SampleFramework;
+
+SampleInputAsset::SampleInputAsset(File* file, const char *path)
+: SampleAsset(SampleAsset::ASSET_INPUT, path)
+, m_SettingsBlock(NULL)
+, m_File(file)
+{
+ m_SampleInputData.reserve(128);
+
+ PX_ASSERT(file);
+
+ if (!m_Mapping.loadScript(file))
+ {
+ shdfnd::printFormatted("ODS parse error: %s in file: %s\n", m_Mapping.lastError, path);
+ PX_ASSERT(0);
+ }
+
+ m_SettingsBlock = m_Mapping.getBlock("InputMapping");
+ if (!m_SettingsBlock)
+ {
+ shdfnd::printFormatted("No \"InputEventSettings\" block found!\n");
+ PX_ASSERT(0);
+ }
+ else
+ {
+ LoadData(m_SettingsBlock);
+ }
+}
+
+SampleInputAsset::~SampleInputAsset()
+{
+ if(m_File)
+ {
+ fclose(m_File);
+ }
+}
+
+void SampleInputAsset::LoadData(ODBlock* odsSettings)
+{
+ odsSettings->reset();
+ while (odsSettings->moreSubBlocks())
+ {
+ ODBlock* subBlock = odsSettings->nextSubBlock();
+ subBlock->reset();
+
+ SampleInputData inputData;
+ if (!strcmp(subBlock->ident(), "map"))
+ {
+ if (subBlock->moreTerminals())
+ {
+ const char* p = subBlock->nextTerminal();
+ strcpy(inputData.m_UserInputName, p);
+ }
+ if (subBlock->moreTerminals())
+ {
+ const char* p = subBlock->nextTerminal();
+ strcpy(inputData.m_InputEventName, p);
+ }
+
+ m_SampleInputData.push_back(inputData);
+ }
+ }
+}
+
+bool SampleInputAsset::isOk(void) const
+{
+ return true;
+}
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/SampleLineDebugRender.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleLineDebugRender.cpp
new file mode 100644
index 00000000..243d1671
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleLineDebugRender.cpp
@@ -0,0 +1,215 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+#include <SampleLineDebugRender.h>
+#include <Renderer.h>
+#include <RendererVertexBuffer.h>
+#include <RendererVertexBufferDesc.h>
+#include <RendererMesh.h>
+#include <RendererMeshDesc.h>
+#include <SampleAssetManager.h>
+#include <SampleMaterialAsset.h>
+#include <RendererMemoryMacros.h>
+
+using namespace SampleFramework;
+
+SampleLineDebugRender::SampleLineDebugRender(SampleRenderer::Renderer &renderer, SampleAssetManager &assetmanager) :
+ m_renderer(renderer),
+ m_assetmanager(assetmanager)
+{
+ m_material = static_cast<SampleMaterialAsset*>(m_assetmanager.getAsset("materials/simple_unlit.xml", SampleAsset::ASSET_MATERIAL));
+ PX_ASSERT(m_material);
+ PX_ASSERT(m_material->getNumVertexShaders() == 1);
+ m_meshContext.material = m_material ? m_material->getMaterial(0) : 0;
+
+ m_maxVerts = 0;
+ m_numVerts = 0;
+ m_vertexbuffer = 0;
+ m_mesh = 0;
+ m_lockedPositions = 0;
+ m_positionStride = 0;
+ m_lockedColors = 0;
+ m_colorStride = 0;
+
+ checkResizeLine(2048);
+}
+
+SampleLineDebugRender::~SampleLineDebugRender(void)
+{
+ checkUnlock();
+ SAFE_RELEASE(m_vertexbuffer);
+ SAFE_RELEASE(m_mesh);
+ if(m_material)
+ {
+ m_assetmanager.returnAsset(*m_material);
+ }
+}
+
+void SampleLineDebugRender::addLine(const PxVec3 &p0, const PxVec3 &p1, const SampleRenderer::RendererColor &color)
+{
+ checkResizeLine(m_numVerts+2);
+ addVert(p0, color);
+ addVert(p1, color);
+}
+
+void SampleLineDebugRender::queueForRenderLine(void)
+{
+ if(m_meshContext.mesh)
+ {
+ checkUnlock();
+ m_mesh->setVertexBufferRange(0, m_numVerts);
+ m_renderer.queueMeshForRender(m_meshContext);
+ }
+}
+
+void SampleLineDebugRender::clearLine(void)
+{
+ m_numVerts = 0;
+}
+
+void SampleLineDebugRender::checkResizeLine(PxU32 maxVerts)
+{
+ if(maxVerts > m_maxVerts)
+ {
+ m_maxVerts = maxVerts + (PxU32)(maxVerts*0.2f);
+
+ SampleRenderer::RendererVertexBufferDesc vbdesc;
+ vbdesc.hint = SampleRenderer::RendererVertexBuffer::HINT_DYNAMIC;
+ vbdesc.semanticFormats[SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION] = SampleRenderer::RendererVertexBuffer::FORMAT_FLOAT3;
+ vbdesc.semanticFormats[SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR] = SampleRenderer::RendererVertexBuffer::FORMAT_COLOR_NATIVE; // same as RendererColor
+ vbdesc.maxVertices = m_maxVerts;
+ SampleRenderer::RendererVertexBuffer *vertexbuffer = m_renderer.createVertexBuffer(vbdesc);
+ PX_ASSERT(vertexbuffer);
+
+ if(vertexbuffer)
+ {
+ PxU32 positionStride = 0;
+ void *positions = vertexbuffer->lockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION, positionStride);
+
+ PxU32 colorStride = 0;
+ void *colors = vertexbuffer->lockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR, colorStride);
+
+ PX_ASSERT(positions && colors);
+ if(positions && colors)
+ {
+ if(m_numVerts > 0)
+ {
+ // if we have existing verts, copy them to the new VB...
+ PX_ASSERT(m_lockedPositions);
+ PX_ASSERT(m_lockedColors);
+ if(m_lockedPositions && m_lockedColors)
+ {
+ for(PxU32 i=0; i<m_numVerts; i++)
+ {
+ memcpy(((PxU8*)positions) + (positionStride*i), ((PxU8*)m_lockedPositions) + (m_positionStride*i), sizeof(PxVec3));
+ memcpy(((PxU8*)colors) + (colorStride*i), ((PxU8*)m_lockedColors) + (m_colorStride*i), sizeof(SampleRenderer::RendererColor));
+ }
+ }
+ m_vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR);
+ m_vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION);
+ }
+ }
+ vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR);
+ vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION);
+ }
+ if(m_vertexbuffer)
+ {
+ m_vertexbuffer->release();
+ m_vertexbuffer = 0;
+ m_lockedPositions = 0;
+ m_positionStride = 0;
+ m_lockedColors = 0;
+ m_colorStride = 0;
+ }
+ SAFE_RELEASE(m_mesh);
+ if(vertexbuffer)
+ {
+ m_vertexbuffer = vertexbuffer;
+ SampleRenderer::RendererMeshDesc meshdesc;
+ meshdesc.primitives = SampleRenderer::RendererMesh::PRIMITIVE_LINES;
+ meshdesc.vertexBuffers = &m_vertexbuffer;
+ meshdesc.numVertexBuffers = 1;
+ meshdesc.firstVertex = 0;
+ meshdesc.numVertices = m_numVerts;
+ m_mesh = m_renderer.createMesh(meshdesc);
+ PX_ASSERT(m_mesh);
+ }
+ m_meshContext.mesh = m_mesh;
+ }
+}
+
+void SampleLineDebugRender::checkLock(void)
+{
+ if(m_vertexbuffer)
+ {
+ if(!m_lockedPositions)
+ {
+ m_lockedPositions = m_vertexbuffer->lockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION, m_positionStride);
+ PX_ASSERT(m_lockedPositions);
+ }
+ if(!m_lockedColors)
+ {
+ m_lockedColors = m_vertexbuffer->lockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR, m_colorStride);
+ PX_ASSERT(m_lockedColors);
+ }
+ }
+}
+
+void SampleLineDebugRender::checkUnlock(void)
+{
+ if(m_vertexbuffer)
+ {
+ if(m_lockedPositions)
+ {
+ m_vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION);
+ m_lockedPositions = 0;
+ }
+ if(m_lockedColors)
+ {
+ m_vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR);
+ m_lockedColors = 0;
+ }
+ }
+}
+
+void SampleLineDebugRender::addVert(const PxVec3 &p, const SampleRenderer::RendererColor &color)
+{
+ PX_ASSERT(m_maxVerts > m_numVerts);
+ {
+ checkLock();
+ if(m_lockedPositions && m_lockedColors)
+ {
+ memcpy(((PxU8*)m_lockedPositions) + (m_positionStride*m_numVerts), &p, sizeof(PxVec3));
+#if defined(RENDERER_XBOX360)
+ PxU8 colors[4] = {color.a, color.r, color.g, color.b};
+ memcpy(((PxU8*)m_lockedColors) + (m_colorStride*m_numVerts), colors, sizeof(PxU8) * 4);
+#else
+ memcpy(((PxU8*)m_lockedColors) + (m_colorStride*m_numVerts), &color, sizeof(SampleRenderer::RendererColor));
+#endif
+ m_numVerts++;
+ }
+ }
+}
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/SampleMaterialAsset.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleMaterialAsset.cpp
new file mode 100644
index 00000000..238217ee
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleMaterialAsset.cpp
@@ -0,0 +1,308 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+#include <SampleMaterialAsset.h>
+
+#include <Renderer.h>
+#include <RendererMaterial.h>
+#include <RendererMaterialDesc.h>
+#include <RendererMaterialInstance.h>
+
+#include <SampleAssetManager.h>
+#include <SampleTextureAsset.h>
+
+#include "SampleXml.h"
+#include <ctype.h>
+
+using namespace SampleFramework;
+
+static SampleRenderer::RendererMaterial::BlendFunc
+getBlendFunc(const char* nodeValue,
+ SampleRenderer::RendererMaterial::BlendFunc defaultBlendFunc = SampleRenderer::RendererMaterial::BLEND_ONE)
+{
+ using SampleRenderer::RendererMaterial;
+ RendererMaterial::BlendFunc blendFunc = defaultBlendFunc;
+ if( !strcmp(nodeValue, "ZERO")) blendFunc = RendererMaterial::BLEND_ZERO;
+ else if(!strcmp(nodeValue, "ONE")) blendFunc = RendererMaterial::BLEND_ONE;
+ else if(!strcmp(nodeValue, "SRC_COLOR")) blendFunc = RendererMaterial::BLEND_SRC_COLOR;
+ else if(!strcmp(nodeValue, "ONE_MINUS_SRC_COLOR")) blendFunc = RendererMaterial::BLEND_ONE_MINUS_SRC_COLOR;
+ else if(!strcmp(nodeValue, "SRC_ALPHA")) blendFunc = RendererMaterial::BLEND_SRC_ALPHA;
+ else if(!strcmp(nodeValue, "ONE_MINUS_SRC_ALPHA")) blendFunc = RendererMaterial::BLEND_ONE_MINUS_SRC_ALPHA;
+ else if(!strcmp(nodeValue, "DST_COLOR")) blendFunc = RendererMaterial::BLEND_DST_COLOR;
+ else if(!strcmp(nodeValue, "ONE_MINUS_DST_COLOR")) blendFunc = RendererMaterial::BLEND_ONE_MINUS_DST_COLOR;
+ else if(!strcmp(nodeValue, "DST_ALPHA")) blendFunc = RendererMaterial::BLEND_DST_ALPHA;
+ else if(!strcmp(nodeValue, "ONE_MINUS_DST_ALPHA")) blendFunc = RendererMaterial::BLEND_ONE_MINUS_DST_ALPHA;
+ else if(!strcmp(nodeValue, "SRC_ALPHA_SATURATE")) blendFunc = RendererMaterial::BLEND_SRC_ALPHA_SATURATE;
+ else PX_ASSERT(0); // Unknown blend func!
+
+ return blendFunc;
+}
+
+static void readFloats(const char *str, float *floats, unsigned int numFloats)
+{
+ PxU32 fcount = 0;
+ while(*str && !((*str>='0'&&*str<='9') || *str=='.')) str++;
+ for(PxU32 i=0; i<numFloats; i++)
+ {
+ if(*str)
+ {
+ floats[i] = (float)atof(str);
+ while(*str && ((*str>='0'&&*str<='9') || *str=='.')) str++;
+ while(*str && !((*str>='0'&&*str<='9') || *str=='.')) str++;
+ fcount++;
+ }
+ }
+ PX_ASSERT(fcount==numFloats);
+}
+
+SampleMaterialAsset::SampleMaterialAsset(SampleAssetManager &assetManager, FAST_XML::xml_node &xmlroot, const char *path) :
+SampleAsset(ASSET_MATERIAL, path),
+ m_assetManager(assetManager)
+{
+
+ std::vector<const char*> mVertexShaderPaths;
+ //m_material = 0;
+ //m_materialInstance = 0;
+
+ SampleRenderer::Renderer &renderer = assetManager.getRenderer();
+
+ SampleRenderer::RendererMaterialDesc matdesc;
+ const char *materialTypeName = xmlroot.getXMLAttribute("type");
+ if(materialTypeName && !strcmp(materialTypeName, "lit"))
+ {
+ matdesc.type = SampleRenderer::RendererMaterial::TYPE_LIT;
+ }
+ else if(materialTypeName && !strcmp(materialTypeName, "unlit"))
+ {
+ matdesc.type = SampleRenderer::RendererMaterial::TYPE_UNLIT;
+ }
+ for(FAST_XML::xml_node *child=xmlroot.first_node(); child; child=child->next_sibling())
+ {
+ const char *nodeName = child->name();
+ const char *nodeValue = child->value();
+ const char *name = child->getXMLAttribute("name");
+ if(nodeName && nodeValue)
+ {
+ while(isspace(*nodeValue)) nodeValue++; // skip leading spaces.
+ if(!strcmp(nodeName, "shader"))
+ {
+ if(name && !strcmp(name, "vertex"))
+ {
+ //matdesc.vertexShaderPath = nodeValue;
+ mVertexShaderPaths.push_back(nodeValue);
+ }
+ else if(name && !strcmp(name, "fragment"))
+ {
+ matdesc.fragmentShaderPath = nodeValue;
+ }
+ else if(name && !strcmp(name, "geometry"))
+ {
+ matdesc.geometryShaderPath = nodeValue;
+ }
+ else if(name && !strcmp(name, "hull"))
+ {
+ matdesc.hullShaderPath = nodeValue;
+ }
+ else if(name && !strcmp(name, "domain"))
+ {
+ matdesc.domainShaderPath = nodeValue;
+ }
+ }
+ else if(!strcmp(nodeName, "alphaTestFunc"))
+ {
+ if( !strcmp(nodeValue, "EQUAL")) matdesc.alphaTestFunc = SampleRenderer::RendererMaterial::ALPHA_TEST_EQUAL;
+ else if(!strcmp(nodeValue, "NOT_EQUAL")) matdesc.alphaTestFunc = SampleRenderer::RendererMaterial::ALPHA_TEST_NOT_EQUAL;
+ else if(!strcmp(nodeValue, "LESS")) matdesc.alphaTestFunc = SampleRenderer::RendererMaterial::ALPHA_TEST_LESS;
+ else if(!strcmp(nodeValue, "LESS_EQUAL")) matdesc.alphaTestFunc = SampleRenderer::RendererMaterial::ALPHA_TEST_LESS_EQUAL;
+ else if(!strcmp(nodeValue, "GREATER")) matdesc.alphaTestFunc = SampleRenderer::RendererMaterial::ALPHA_TEST_GREATER;
+ else if(!strcmp(nodeValue, "GREATER_EQUAL")) matdesc.alphaTestFunc = SampleRenderer::RendererMaterial::ALPHA_TEST_GREATER_EQUAL;
+ else PX_ASSERT(0); // Unknown alpha test func!
+ }
+ else if(!strcmp(nodeName, "alphaTestRef"))
+ {
+ matdesc.alphaTestRef = PxClamp((float)atof(nodeValue), 0.0f, 1.0f);
+ }
+ else if(!strcmp(nodeName, "blending") && strstr(nodeValue, "true"))
+ {
+ matdesc.blending = true;
+
+ static const PxU32 numBlendFuncs = 2;
+ static const char* blendFuncNames[numBlendFuncs] =
+ {
+ "srcBlendFunc",
+ "dstBlendFunc"
+ };
+ static const SampleRenderer::RendererMaterial::BlendFunc blendFuncDefaults[numBlendFuncs] =
+ {
+ SampleRenderer::RendererMaterial::BLEND_SRC_ALPHA,
+ SampleRenderer::RendererMaterial::BLEND_ONE_MINUS_SRC_ALPHA
+ };
+ SampleRenderer::RendererMaterial::BlendFunc* blendFuncs[numBlendFuncs] =
+ {
+ &matdesc.srcBlendFunc,
+ &matdesc.dstBlendFunc
+ };
+
+ // Parse optional src/dst blend funcs
+ for (PxU32 i = 0; i < numBlendFuncs; ++i)
+ {
+ FAST_XML::xml_node *blendNode = child->first_node(blendFuncNames[i]);
+ if (blendNode && blendNode->value())
+ *blendFuncs[i] = getBlendFunc(blendNode->value(), blendFuncDefaults[i]);
+ else
+ *blendFuncs[i] = blendFuncDefaults[i];
+ }
+ }
+ }
+ }
+
+ for (size_t materialIndex = 0; materialIndex < mVertexShaderPaths.size(); materialIndex++)
+ {
+ MaterialStruct materialStruct;
+
+ matdesc.vertexShaderPath = mVertexShaderPaths[materialIndex];
+ materialStruct.m_material = NULL;
+ materialStruct.m_materialInstance = NULL;
+ materialStruct.m_maxBones = 0;
+ if (strstr(mVertexShaderPaths[materialIndex], "skeletalmesh") != NULL)
+ materialStruct.m_maxBones = RENDERER_MAX_BONES;
+
+ materialStruct.m_material = renderer.createMaterial(matdesc);
+ PX_ASSERT(materialStruct.m_material);
+ if(materialStruct.m_material)
+ {
+ FAST_XML::xml_node *varsnode = xmlroot.first_node("variables");
+ if(varsnode)
+ {
+ materialStruct.m_materialInstance = new SampleRenderer::RendererMaterialInstance(*materialStruct.m_material);
+ for(FAST_XML::xml_node *child=varsnode->first_node(); child; child=child->next_sibling())
+ {
+ const char *nodename = child->name();
+ const char *varname = child->getXMLAttribute("name");
+ const char *value = child->value();
+
+ if(!strcmp(nodename, "float"))
+ {
+ float f = (float)atof(value);
+ const SampleRenderer::RendererMaterial::Variable *var = materialStruct.m_materialInstance->findVariable(varname, SampleRenderer::RendererMaterial::VARIABLE_FLOAT);
+ //PX_ASSERT(var);
+ if(var) materialStruct.m_materialInstance->writeData(*var, &f);
+ }
+ else if(!strcmp(nodename, "float2"))
+ {
+ float f[2];
+ readFloats(value, f, 2);
+ const SampleRenderer::RendererMaterial::Variable *var = materialStruct.m_materialInstance->findVariable(varname, SampleRenderer::RendererMaterial::VARIABLE_FLOAT2);
+ //PX_ASSERT(var);
+ if(var) materialStruct.m_materialInstance->writeData(*var, f);
+ }
+ else if(!strcmp(nodename, "float3"))
+ {
+ float f[3];
+ readFloats(value, f, 3);
+ const SampleRenderer::RendererMaterial::Variable *var = materialStruct.m_materialInstance->findVariable(varname, SampleRenderer::RendererMaterial::VARIABLE_FLOAT3);
+ //PX_ASSERT(var);
+ if(var) materialStruct.m_materialInstance->writeData(*var, f);
+ }
+ else if(!strcmp(nodename, "float4"))
+ {
+ float f[4];
+ readFloats(value, f, 4);
+ const SampleRenderer::RendererMaterial::Variable *var = materialStruct.m_materialInstance->findVariable(varname, SampleRenderer::RendererMaterial::VARIABLE_FLOAT4);
+ //PX_ASSERT(var);
+ if(var) materialStruct.m_materialInstance->writeData(*var, f);
+ }
+ else if(!strcmp(nodename, "sampler2D") || !strcmp(nodename, "sampler3D"))
+ {
+ SampleTextureAsset *textureAsset = static_cast<SampleTextureAsset*>(assetManager.getAsset(value, ASSET_TEXTURE));
+ PX_ASSERT(textureAsset);
+ if(textureAsset)
+ {
+ m_assets.push_back(textureAsset);
+ SampleRenderer::RendererMaterial::VariableType vartype = (0 == strcmp(nodename, "sampler2D")) ? SampleRenderer::RendererMaterial::VARIABLE_SAMPLER2D : SampleRenderer::RendererMaterial::VARIABLE_SAMPLER3D;
+ const SampleRenderer::RendererMaterial::Variable *var = materialStruct.m_materialInstance->findVariable(varname, vartype);
+ //PX_ASSERT(var);
+ if(var)
+ {
+ SampleRenderer::RendererTexture *texture = textureAsset->getTexture();
+ materialStruct.m_materialInstance->writeData(*var, &texture);
+ }
+ }
+ }
+
+ }
+ }
+
+ m_vertexShaders.push_back(materialStruct);
+ }
+ }
+}
+
+SampleFramework::SampleMaterialAsset::SampleMaterialAsset(SampleAssetManager &assetManager, Type type, const char *path)
+: SampleAsset(type, path),
+ m_assetManager(assetManager)
+{
+
+}
+
+SampleMaterialAsset::~SampleMaterialAsset(void)
+{
+ PxU32 numAssets = (PxU32)m_assets.size();
+ for(PxU32 i=0; i<numAssets; i++)
+ {
+ m_assetManager.returnAsset(*m_assets[i]);
+ }
+ for (size_t index = 0; index < m_vertexShaders.size(); index++)
+ {
+ if(m_vertexShaders[index].m_materialInstance) delete m_vertexShaders[index].m_materialInstance;
+ if(m_vertexShaders[index].m_material) m_vertexShaders[index].m_material->release();
+ }
+}
+
+size_t SampleMaterialAsset::getNumVertexShaders() const
+{
+ return m_vertexShaders.size();
+}
+
+SampleRenderer::RendererMaterial *SampleMaterialAsset::getMaterial(size_t vertexShaderIndex)
+{
+ return m_vertexShaders[vertexShaderIndex].m_material;
+}
+
+SampleRenderer::RendererMaterialInstance *SampleMaterialAsset::getMaterialInstance(size_t vertexShaderIndex)
+{
+ return m_vertexShaders[vertexShaderIndex].m_materialInstance;
+}
+
+bool SampleMaterialAsset::isOk(void) const
+{
+ return !m_vertexShaders.empty();
+}
+
+unsigned int SampleMaterialAsset::getMaxBones(size_t vertexShaderIndex) const
+{
+ return m_vertexShaders[vertexShaderIndex].m_maxBones;
+}
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/SamplePointDebugRender.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/SamplePointDebugRender.cpp
new file mode 100644
index 00000000..65a6e5a4
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/SamplePointDebugRender.cpp
@@ -0,0 +1,207 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+#include <SamplePointDebugRender.h>
+#include <Renderer.h>
+#include <RendererVertexBuffer.h>
+#include <RendererVertexBufferDesc.h>
+#include <RendererMesh.h>
+#include <RendererMeshDesc.h>
+#include <SampleAssetManager.h>
+#include <SampleMaterialAsset.h>
+#include <RendererMemoryMacros.h>
+
+using namespace SampleFramework;
+
+SamplePointDebugRender::SamplePointDebugRender(SampleRenderer::Renderer &renderer, SampleAssetManager &assetmanager) :
+ m_renderer(renderer),
+ m_assetmanager(assetmanager)
+{
+ m_material = static_cast<SampleMaterialAsset*>(m_assetmanager.getAsset("materials/simple_unlit.xml", SampleAsset::ASSET_MATERIAL));
+ PX_ASSERT(m_material);
+ PX_ASSERT(m_material->getNumVertexShaders() == 1);
+ m_meshContext.material = m_material ? m_material->getMaterial(0) : 0;
+
+ m_maxVerts = 0;
+ m_numVerts = 0;
+ m_vertexbuffer = 0;
+ m_mesh = 0;
+ m_lockedPositions = 0;
+ m_positionStride = 0;
+ m_lockedColors = 0;
+ m_colorStride = 0;
+}
+
+SamplePointDebugRender::~SamplePointDebugRender(void)
+{
+ checkUnlock();
+ SAFE_RELEASE(m_vertexbuffer);
+ SAFE_RELEASE(m_mesh);
+ if(m_material)
+ {
+ m_assetmanager.returnAsset(*m_material);
+ }
+}
+
+void SamplePointDebugRender::addPoint(const PxVec3 &p0, const SampleRenderer::RendererColor &color)
+{
+ checkResizePoint(m_numVerts+1);
+ addVert(p0, color);
+}
+
+void SamplePointDebugRender::queueForRenderPoint(void)
+{
+ if(m_meshContext.mesh)
+ {
+ checkUnlock();
+ m_mesh->setVertexBufferRange(0, m_numVerts);
+ m_renderer.queueMeshForRender(m_meshContext);
+ }
+}
+
+void SamplePointDebugRender::clearPoint(void)
+{
+ m_numVerts = 0;
+}
+
+void SamplePointDebugRender::checkResizePoint(PxU32 maxVerts)
+{
+ if(maxVerts > m_maxVerts)
+ {
+ m_maxVerts = maxVerts + (PxU32)(maxVerts*0.2f);
+
+ SampleRenderer::RendererVertexBufferDesc vbdesc;
+ vbdesc.hint = SampleRenderer::RendererVertexBuffer::HINT_DYNAMIC;
+ vbdesc.semanticFormats[SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION] = SampleRenderer::RendererVertexBuffer::FORMAT_FLOAT3;
+ vbdesc.semanticFormats[SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR] = SampleRenderer::RendererVertexBuffer::FORMAT_COLOR_NATIVE; // same as RendererColor
+ vbdesc.maxVertices = m_maxVerts;
+ SampleRenderer::RendererVertexBuffer *vertexbuffer = m_renderer.createVertexBuffer(vbdesc);
+ PX_ASSERT(vertexbuffer);
+
+ if(vertexbuffer)
+ {
+ PxU32 positionStride = 0;
+ void *positions = vertexbuffer->lockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION, positionStride);
+
+ PxU32 colorStride = 0;
+ void *colors = vertexbuffer->lockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR, colorStride);
+
+ PX_ASSERT(positions && colors);
+ if(positions && colors)
+ {
+ if(m_numVerts > 0)
+ {
+ // if we have existing verts, copy them to the new VB...
+ PX_ASSERT(m_lockedPositions);
+ PX_ASSERT(m_lockedColors);
+ if(m_lockedPositions && m_lockedColors)
+ {
+ for(PxU32 i=0; i<m_numVerts; i++)
+ {
+ memcpy(((PxU8*)positions) + (positionStride*i), ((PxU8*)m_lockedPositions) + (m_positionStride*i), sizeof(PxVec3));
+ memcpy(((PxU8*)colors) + (colorStride*i), ((PxU8*)m_lockedColors) + (m_colorStride*i), sizeof(SampleRenderer::RendererColor));
+ }
+ }
+ m_vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR);
+ m_vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION);
+ }
+ }
+ vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR);
+ vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION);
+ }
+ if(m_vertexbuffer)
+ {
+ m_vertexbuffer->release();
+ m_vertexbuffer = 0;
+ m_lockedPositions = 0;
+ m_positionStride = 0;
+ m_lockedColors = 0;
+ m_colorStride = 0;
+ }
+ SAFE_RELEASE(m_mesh);
+ if(vertexbuffer)
+ {
+ m_vertexbuffer = vertexbuffer;
+ SampleRenderer::RendererMeshDesc meshdesc;
+ meshdesc.primitives = SampleRenderer::RendererMesh::PRIMITIVE_POINTS;
+ meshdesc.vertexBuffers = &m_vertexbuffer;
+ meshdesc.numVertexBuffers = 1;
+ meshdesc.firstVertex = 0;
+ meshdesc.numVertices = m_numVerts;
+ m_mesh = m_renderer.createMesh(meshdesc);
+ PX_ASSERT(m_mesh);
+ }
+ m_meshContext.mesh = m_mesh;
+ }
+}
+
+void SamplePointDebugRender::checkLock(void)
+{
+ if(m_vertexbuffer)
+ {
+ if(!m_lockedPositions)
+ {
+ m_lockedPositions = m_vertexbuffer->lockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION, m_positionStride);
+ PX_ASSERT(m_lockedPositions);
+ }
+ if(!m_lockedColors)
+ {
+ m_lockedColors = m_vertexbuffer->lockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR, m_colorStride);
+ PX_ASSERT(m_lockedColors);
+ }
+ }
+}
+
+void SamplePointDebugRender::checkUnlock(void)
+{
+ if(m_vertexbuffer)
+ {
+ if(m_lockedPositions)
+ {
+ m_vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION);
+ m_lockedPositions = 0;
+ }
+ if(m_lockedColors)
+ {
+ m_vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR);
+ m_lockedColors = 0;
+ }
+ }
+}
+
+void SamplePointDebugRender::addVert(const PxVec3 &p, const SampleRenderer::RendererColor &color)
+{
+ PX_ASSERT(m_maxVerts > m_numVerts);
+ {
+ checkLock();
+ if(m_lockedPositions && m_lockedColors)
+ {
+ memcpy(((PxU8*)m_lockedPositions) + (m_positionStride*m_numVerts), &p, sizeof(PxVec3));
+ memcpy(((PxU8*)m_lockedColors) + (m_colorStride*m_numVerts), &color, sizeof(SampleRenderer::RendererColor));
+ m_numVerts++;
+ }
+ }
+}
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/SampleTextureAsset.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleTextureAsset.cpp
new file mode 100644
index 00000000..c6302895
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleTextureAsset.cpp
@@ -0,0 +1,342 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+#include <SampleTextureAsset.h>
+
+#include <Renderer.h>
+#include <RendererTexture2D.h>
+#include <RendererTexture2DDesc.h>
+#include <RendererMemoryMacros.h>
+#include "PxTkBmpLoader.h"
+
+#include "nv_dds.h"
+#include "PxTkFile.h"
+
+#ifdef RENDERER_ENABLE_TGA_SUPPORT
+# include <targa.h>
+#endif
+
+#ifdef RENDERER_ENABLE_PVR_SUPPORT
+#include "pvrt.h"
+#endif
+
+using namespace SampleFramework;
+
+SampleTextureAsset::SampleTextureAsset(SampleRenderer::Renderer &renderer, File &file, const char *path, Type texType) :
+ SampleAsset(ASSET_TEXTURE, path)
+{
+ m_texture = 0;
+
+ switch(texType)
+ {
+ case DDS: loadDDS(renderer, file); break;
+ case TGA: loadTGA(renderer, file); break;
+ case PVR: loadPVR(renderer, file); break;
+ case BMP: loadBMP(renderer, file); break;
+ default: PX_ASSERT(0 && "Invalid texture type requested"); break;
+ }
+}
+
+SampleTextureAsset::~SampleTextureAsset(void)
+{
+ SAFE_RELEASE(m_texture);
+}
+
+void SampleTextureAsset::loadDDS(SampleRenderer::Renderer &renderer, File &file)
+{
+ nv_dds::CDDSImage ddsimage;
+ bool ok = ddsimage.load(&file, false);
+ PX_ASSERT(ok);
+ if(ok)
+ {
+ SampleRenderer::RendererTexture2DDesc tdesc;
+ nv_dds::TextureFormat ddsformat = ddsimage.get_format();
+ switch(ddsformat)
+ {
+ case nv_dds::TextureBGRA: tdesc.format = SampleRenderer::RendererTexture2D::FORMAT_B8G8R8A8; break;
+ case nv_dds::TextureDXT1: tdesc.format = SampleRenderer::RendererTexture2D::FORMAT_DXT1; break;
+ case nv_dds::TextureDXT3: tdesc.format = SampleRenderer::RendererTexture2D::FORMAT_DXT3; break;
+ case nv_dds::TextureDXT5: tdesc.format = SampleRenderer::RendererTexture2D::FORMAT_DXT5; break;
+ default: break;
+ }
+ tdesc.width = ddsimage.get_width();
+ tdesc.height = ddsimage.get_height();
+ // if there is 1 mipmap, nv_dds reports 0
+ tdesc.numLevels = ddsimage.get_num_mipmaps()+1;
+ PX_ASSERT(tdesc.isValid());
+ m_texture = renderer.createTexture2D(tdesc);
+ PX_ASSERT(m_texture);
+ if(m_texture)
+ {
+ PxU32 pitch = 0;
+ void *buffer = m_texture->lockLevel(0, pitch);
+ PX_ASSERT(buffer);
+ if(buffer)
+ {
+ //PxU32 size = ddsimage.get_size();
+
+ PxU8 *levelDst = (PxU8*)buffer;
+ const PxU8 *levelSrc = (PxU8*)(unsigned char*)ddsimage;
+ const PxU32 levelWidth = m_texture->getWidthInBlocks();
+ const PxU32 levelHeight = m_texture->getHeightInBlocks();
+ const PxU32 rowSrcSize = levelWidth * m_texture->getBlockSize();
+ PX_ASSERT(rowSrcSize <= pitch); // the pitch can't be less than the source row size.
+ for(PxU32 row=0; row<levelHeight; row++)
+ {
+ memcpy(levelDst, levelSrc, rowSrcSize);
+ levelDst += pitch;
+ levelSrc += rowSrcSize;
+ }
+ }
+ m_texture->unlockLevel(0);
+
+ for(PxU32 i=1; i<tdesc.numLevels; i++)
+ {
+ void *buffer = m_texture->lockLevel(i, pitch);
+ PX_ASSERT(buffer);
+ if(buffer && pitch )
+ {
+ const nv_dds::CSurface &surface = ddsimage.get_mipmap(i-1);
+ //PxU32 size = surface.get_size();
+
+ PxU8 *levelDst = (PxU8*)buffer;
+ const PxU8 *levelSrc = (PxU8*)(unsigned char*)surface;
+ const PxU32 levelWidth = SampleRenderer::RendererTexture2D::getFormatNumBlocks(surface.get_width(), m_texture->getFormat());
+ const PxU32 levelHeight = SampleRenderer::RendererTexture2D::getFormatNumBlocks(surface.get_height(), m_texture->getFormat());
+ const PxU32 rowSrcSize = levelWidth * m_texture->getBlockSize();
+ PX_ASSERT(rowSrcSize <= pitch); // the pitch can't be less than the source row size.
+ for(PxU32 row=0; row<levelHeight; row++)
+ {
+ memcpy(levelDst, levelSrc, rowSrcSize);
+ levelDst += pitch;
+ levelSrc += rowSrcSize;
+ }
+ }
+ m_texture->unlockLevel(i);
+ }
+ }
+ }
+}
+
+void SampleTextureAsset::loadPVR(SampleRenderer::Renderer& renderer, File& file)
+{
+#ifdef RENDERER_ENABLE_PVR_SUPPORT
+ fseek(&file, 0, SEEK_END);
+ size_t size = ftell(&file);
+ fseek(&file, 0, SEEK_SET);
+ char* fileBuffer = new char[size+1];
+ fread(fileBuffer, 1, size, &file);
+ fclose(&file);
+ fileBuffer[size] = '\0';
+
+ const PVRTextureInfo info(fileBuffer);
+ PX_ASSERT(info.data);
+
+ SampleRenderer::RendererTexture2DDesc tdesc;
+ if (info.glFormat == GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG)
+ {
+ tdesc.format = SampleRenderer::RendererTexture2D::FORMAT_PVR_4BPP;
+ }
+ else
+ {
+ tdesc.format = SampleRenderer::RendererTexture2D::FORMAT_PVR_2BPP;
+ }
+
+ tdesc.width = info.width;
+ tdesc.height = info.height;
+ tdesc.numLevels = info.mipCount + 1;
+ tdesc.data = NULL;
+
+ PX_ASSERT(tdesc.isValid());
+ m_texture = renderer.createTexture2D(tdesc);
+ PX_ASSERT(m_texture);
+ if (!info.data)
+ {
+ delete[] fileBuffer;
+ return;
+ }
+
+ PxU32 pitch = 0;
+ PxU8* levelDst = (PxU8*)m_texture->lockLevel(0, pitch);
+ const PxU8* levelSrc = (PxU8*)info.data;
+
+ PX_ASSERT(levelDst && levelSrc);
+ {
+ PxU32 levelWidth = tdesc.width;
+ PxU32 levelHeight = tdesc.height;
+ const PxU32 levelSize = m_texture->computeImageByteSize(levelWidth, levelHeight, 1, tdesc.format);
+ memcpy(levelDst, levelSrc, levelSize);
+ levelSrc += levelSize;
+ }
+ m_texture->unlockLevel(0);
+
+ for(PxU32 i=1; i<tdesc.numLevels; i++)
+ {
+ PxU8* levelDst = (PxU8*)m_texture->lockLevel(i, pitch);
+ PX_ASSERT(levelDst);
+ {
+ const PxU32 levelWidth = m_texture->getLevelDimension(tdesc.width, i);
+ const PxU32 levelHeight = m_texture->getLevelDimension(tdesc.height, i);
+ const PxU32 levelSize = m_texture->computeImageByteSize(levelWidth, levelHeight, 1, tdesc.format);
+ memcpy(levelDst, levelSrc, levelSize);
+ levelSrc += levelSize;
+ }
+ m_texture->unlockLevel(i);
+ }
+
+ delete[] fileBuffer;
+
+#endif
+}
+
+void SampleTextureAsset::loadTGA(SampleRenderer::Renderer &renderer, File &file)
+{
+#ifdef RENDERER_ENABLE_TGA_SUPPORT
+ tga_image* image = new tga_image();
+ bool ok = (TGA_NOERR == tga_read_from_FILE( image, &file ));
+
+ // flip it to make it look correct in the SampleFramework's renderer
+ tga_flip_vert( image );
+
+ PX_ASSERT(ok);
+ if( ok )
+ {
+ SampleRenderer::RendererTexture2DDesc tdesc;
+ int componentCount = image->pixel_depth/8;
+ if( componentCount == 3 || componentCount == 4 )
+ {
+ tdesc.format = SampleRenderer::RendererTexture2D::FORMAT_B8G8R8A8;
+
+ tdesc.width = image->width;
+ tdesc.height = image->height;
+
+ tdesc.numLevels = 1;
+ PX_ASSERT(tdesc.isValid());
+ m_texture = renderer.createTexture2D(tdesc);
+ PX_ASSERT(m_texture);
+
+ if(m_texture)
+ {
+ PxU32 pitch = 0;
+ void *buffer = m_texture->lockLevel(0, pitch);
+ PX_ASSERT(buffer);
+ if(buffer)
+ {
+ PxU8 *levelDst = (PxU8*)buffer;
+ const PxU8 *levelSrc = (PxU8*)image->image_data;
+ const PxU32 levelWidth = m_texture->getWidthInBlocks();
+ const PxU32 levelHeight = m_texture->getHeightInBlocks();
+ const PxU32 rowSrcSize = levelWidth * m_texture->getBlockSize();
+ PX_ASSERT(rowSrcSize <= pitch); // the pitch can't be less than the source row size.
+ for(PxU32 row=0; row<levelHeight; row++)
+ {
+ if( componentCount == 3 )
+ {
+ // copy per pixel to handle RBG case, based on component count
+ for(PxU32 col=0; col<levelWidth; col++)
+ {
+ *levelDst++ = levelSrc[0];
+ *levelDst++ = levelSrc[1];
+ *levelDst++ = levelSrc[2];
+ *levelDst++ = 0xFF; //alpha
+ levelSrc += componentCount;
+ }
+ }
+ else
+ {
+ memcpy(levelDst, levelSrc, rowSrcSize);
+ levelDst += pitch == 0xFFFFFFFF ? rowSrcSize : pitch;
+ levelSrc += rowSrcSize;
+ }
+ }
+ }
+ m_texture->unlockLevel(0);
+ }
+ }
+ }
+ tga_free_buffers(image);
+ delete image;
+
+#endif /* RENDERER_ENABLE_TGA_SUPPORT */
+}
+
+void SampleTextureAsset::loadBMP(SampleRenderer::Renderer &renderer, File &file)
+{
+ PxToolkit::BmpLoader loader;
+ bool ok = loader.loadBmp(&file);
+ PX_ASSERT(ok);
+ if(ok)
+ {
+ SampleRenderer::RendererTexture2DDesc tdesc;
+#if !defined(RENDERER_PS3)
+ tdesc.format = SampleRenderer::RendererTexture2D::FORMAT_B8G8R8A8;
+#else
+ tdesc.format = SampleRenderer::RendererTexture2D::FORMAT_R8G8B8A8;
+#endif
+ tdesc.width = loader.mWidth;
+ tdesc.height = loader.mHeight;
+ tdesc.numLevels = 1;
+ PX_ASSERT(tdesc.isValid());
+ m_texture = renderer.createTexture2D(tdesc);
+ PX_ASSERT(m_texture);
+ if(m_texture)
+ {
+ PxU32 pitch = 0;
+ void *buffer = m_texture->lockLevel(0, pitch);
+ PX_ASSERT(buffer);
+ if(buffer)
+ {
+ const PxU32 levelWidth = m_texture->getWidthInBlocks();
+ const PxU32 levelHeight = m_texture->getHeightInBlocks();
+ SampleRenderer::RendererColor* levelDst = (SampleRenderer::RendererColor*)buffer + levelWidth * levelHeight;
+ const PxU8* levelSrc = (PxU8*)loader.mRGB;
+ for(PxU32 row=0; row<levelHeight; row++)
+ {
+ levelDst -= levelWidth;
+ // copy per pixel to handle RBG case
+ for(PxU32 col=0; col<levelWidth; col++)
+ {
+ levelDst[col].r = *levelSrc++;
+ levelDst[col].g = *levelSrc++;
+ levelDst[col].b = *levelSrc++;
+ levelDst[col].a = loader.mHasAlpha ? *levelSrc++ : 0xff;
+ }
+ }
+ }
+ m_texture->unlockLevel(0);
+ }
+ }
+}
+
+SampleRenderer::RendererTexture2D *SampleTextureAsset::getTexture(void)
+{
+ return m_texture;
+}
+
+bool SampleTextureAsset::isOk(void) const
+{
+ return m_texture ? true : false;
+}
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/SampleTree.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleTree.cpp
new file mode 100644
index 00000000..8d24e364
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleTree.cpp
@@ -0,0 +1,70 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+
+#include "SampleTree.h"
+
+using namespace SampleFramework;
+
+bool Tree::Node::appendChild(Node& node)
+{
+ if (!node.isRoot() || isOffspringOf(node))
+ return false;
+
+ node.mParent = this;
+ node.mPrev = mTail;
+
+ if (NULL == mTail)
+ mHead = &node;
+ else
+ mTail->mNext = &node;
+
+ mTail = &node;
+
+ return true;
+}
+
+bool Tree::Node::removeChild(Node& node)
+{
+ if (this != node.mParent)
+ return false;
+
+ Node* prev = node.mPrev;
+ Node* next = node.mNext;
+
+ if (NULL == prev)
+ mHead = next;
+ else
+ prev->mNext = next;
+
+ if (NULL == next)
+ mTail = prev;
+ else
+ next->mPrev = prev;
+
+ node.mParent = NULL;
+ return true;
+}
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/SampleTriangleDebugRender.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleTriangleDebugRender.cpp
new file mode 100644
index 00000000..c596d6ab
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/SampleTriangleDebugRender.cpp
@@ -0,0 +1,244 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+#include <SampleTriangleDebugRender.h>
+#include <Renderer.h>
+#include <RendererVertexBuffer.h>
+#include <RendererVertexBufferDesc.h>
+#include <RendererMesh.h>
+#include <RendererMeshDesc.h>
+#include <SampleAssetManager.h>
+#include <SampleMaterialAsset.h>
+#include <RendererMemoryMacros.h>
+
+using namespace SampleFramework;
+
+SampleTriangleDebugRender::SampleTriangleDebugRender(SampleRenderer::Renderer &renderer, SampleAssetManager &assetmanager) :
+ m_renderer(renderer),
+ m_assetmanager(assetmanager)
+{
+ m_material = static_cast<SampleMaterialAsset*>(m_assetmanager.getAsset("materials/simple_lit_color.xml", SampleAsset::ASSET_MATERIAL));
+ PX_ASSERT(m_material);
+ PX_ASSERT(m_material->getNumVertexShaders() == 1);
+ m_meshContext.material = m_material ? m_material->getMaterial(0) : 0;
+
+ m_maxVerts = 0;
+ m_numVerts = 0;
+ m_vertexbuffer = 0;
+ m_mesh = 0;
+ m_lockedPositions = 0;
+ m_positionStride = 0;
+ m_lockedNormals = 0;
+ m_normalStride = 0;
+ m_lockedColors = 0;
+ m_colorStride = 0;
+}
+
+SampleTriangleDebugRender::~SampleTriangleDebugRender(void)
+{
+ checkUnlock();
+ SAFE_RELEASE(m_vertexbuffer);
+ SAFE_RELEASE(m_mesh);
+ if(m_material)
+ {
+ m_assetmanager.returnAsset(*m_material);
+ }
+}
+
+void SampleTriangleDebugRender::addTriangle(const PxVec3 &p0, const PxVec3 &p1, const PxVec3 &p2, const SampleRenderer::RendererColor &color)
+{
+ checkResizeTriangle(m_numVerts+3);
+ PxVec3 normal = (p1-p0).cross(p2-p0);
+ normal.normalize();
+ addVert(p0, normal, color);
+ addVert(p1, normal, color);
+ addVert(p2, normal, color);
+}
+
+void SampleTriangleDebugRender::addTriangle(const PxVec3 &p0, const PxVec3 &p1, const PxVec3 &p2, const PxVec3& n0, const PxVec3& n1, const PxVec3& n2, const SampleRenderer::RendererColor &color)
+{
+ checkResizeTriangle(m_numVerts+3);
+ addVert(p0, n0, color);
+ addVert(p1, n1, color);
+ addVert(p2, n2, color);
+}
+
+void SampleTriangleDebugRender::queueForRenderTriangle(void)
+{
+ if(m_meshContext.mesh)
+ {
+ checkUnlock();
+ m_mesh->setVertexBufferRange(0, m_numVerts);
+ m_renderer.queueMeshForRender(m_meshContext);
+ }
+}
+
+void SampleTriangleDebugRender::clearTriangle(void)
+{
+ m_numVerts = 0;
+}
+
+void SampleTriangleDebugRender::checkResizeTriangle(PxU32 maxVerts)
+{
+ if(maxVerts > m_maxVerts)
+ {
+ m_maxVerts = maxVerts + (PxU32)(maxVerts*0.2f);
+
+ SampleRenderer::RendererVertexBufferDesc vbdesc;
+ vbdesc.hint = SampleRenderer::RendererVertexBuffer::HINT_DYNAMIC;
+ vbdesc.semanticFormats[SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION] = SampleRenderer::RendererVertexBuffer::FORMAT_FLOAT3;
+ vbdesc.semanticFormats[SampleRenderer::RendererVertexBuffer::SEMANTIC_NORMAL] = SampleRenderer::RendererVertexBuffer::FORMAT_FLOAT3;
+ vbdesc.semanticFormats[SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR] = SampleRenderer::RendererVertexBuffer::FORMAT_COLOR_NATIVE; // Same format as RendererColor
+ vbdesc.maxVertices = m_maxVerts;
+ SampleRenderer::RendererVertexBuffer *vertexbuffer = m_renderer.createVertexBuffer(vbdesc);
+ PX_ASSERT(vertexbuffer);
+
+ if(vertexbuffer)
+ {
+ PxU32 positionStride = 0;
+ void *positions = vertexbuffer->lockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION, positionStride);
+
+ PxU32 normalStride = 0;
+ void *normals = vertexbuffer->lockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_NORMAL, normalStride);
+
+ PxU32 colorStride = 0;
+ void *colors = vertexbuffer->lockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR, colorStride);
+
+ PX_ASSERT(positions && colors);
+ if(positions && colors)
+ {
+ if(m_numVerts > 0)
+ {
+ // if we have existing verts, copy them to the new VB...
+ PX_ASSERT(m_lockedPositions);
+ PX_ASSERT(m_lockedNormals);
+ PX_ASSERT(m_lockedColors);
+ if(m_lockedPositions && m_lockedNormals && m_lockedColors)
+ {
+ for(PxU32 i=0; i<m_numVerts; i++)
+ {
+ memcpy(((PxU8*)positions) + (positionStride*i), ((PxU8*)m_lockedPositions) + (m_positionStride*i), sizeof(PxVec3));
+ memcpy(((PxU8*)normals) + (normalStride*i), ((PxU8*)m_lockedNormals) + (m_normalStride*i), sizeof(PxVec3));
+ memcpy(((PxU8*)colors) + (colorStride*i), ((PxU8*)m_lockedColors) + (m_colorStride*i), sizeof(SampleRenderer::RendererColor));
+ }
+ }
+ m_vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR);
+ m_vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_NORMAL);
+ m_vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION);
+ }
+ }
+ vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR);
+ vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_NORMAL);
+ vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION);
+ }
+ if(m_vertexbuffer)
+ {
+ m_vertexbuffer->release();
+ m_vertexbuffer = 0;
+ m_lockedPositions = 0;
+ m_positionStride = 0;
+ m_lockedNormals = 0;
+ m_normalStride = 0;
+ m_lockedColors = 0;
+ m_colorStride = 0;
+ }
+ SAFE_RELEASE(m_mesh);
+ if(vertexbuffer)
+ {
+ m_vertexbuffer = vertexbuffer;
+ SampleRenderer::RendererMeshDesc meshdesc;
+ meshdesc.primitives = SampleRenderer::RendererMesh::PRIMITIVE_TRIANGLES;
+ meshdesc.vertexBuffers = &m_vertexbuffer;
+ meshdesc.numVertexBuffers = 1;
+ meshdesc.firstVertex = 0;
+ meshdesc.numVertices = m_numVerts;
+ m_mesh = m_renderer.createMesh(meshdesc);
+ PX_ASSERT(m_mesh);
+ }
+ m_meshContext.mesh = m_mesh;
+ m_meshContext.cullMode = SampleRenderer::RendererMeshContext::NONE;
+ }
+}
+
+void SampleTriangleDebugRender::checkLock(void)
+{
+ if(m_vertexbuffer)
+ {
+ if(!m_lockedPositions)
+ {
+ m_lockedPositions = m_vertexbuffer->lockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION, m_positionStride);
+ PX_ASSERT(m_lockedPositions);
+ }
+ if(!m_lockedNormals)
+ {
+ m_lockedNormals = m_vertexbuffer->lockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_NORMAL, m_normalStride);
+ PX_ASSERT(m_lockedNormals);
+ }
+ if(!m_lockedColors)
+ {
+ m_lockedColors = m_vertexbuffer->lockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR, m_colorStride);
+ PX_ASSERT(m_lockedColors);
+ }
+ }
+}
+
+void SampleTriangleDebugRender::checkUnlock(void)
+{
+ if(m_vertexbuffer)
+ {
+ if(m_lockedPositions)
+ {
+ m_vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_POSITION);
+ m_lockedPositions = 0;
+ }
+ if (m_lockedNormals)
+ {
+ m_vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_NORMAL);
+ m_lockedNormals = 0;
+ }
+ if(m_lockedColors)
+ {
+ m_vertexbuffer->unlockSemantic(SampleRenderer::RendererVertexBuffer::SEMANTIC_COLOR);
+ m_lockedColors = 0;
+ }
+ }
+}
+
+void SampleTriangleDebugRender::addVert(const PxVec3 &p, const PxVec3 &n, const SampleRenderer::RendererColor &color)
+{
+ PX_ASSERT(m_maxVerts > m_numVerts);
+ {
+ checkLock();
+ if(m_lockedPositions && m_lockedNormals && m_lockedColors)
+ {
+ *(PxVec3*)(((PxU8*)m_lockedPositions) + (m_positionStride*m_numVerts)) = p;
+ *(PxVec3*)(((PxU8*)m_lockedNormals) + (m_normalStride*m_numVerts)) = n;
+ *(SampleRenderer::RendererColor*)(((PxU8*)m_lockedColors) + (m_colorStride*m_numVerts)) = color;
+
+ m_numVerts++;
+ }
+ }
+}
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/nv_dds.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/nv_dds.cpp
new file mode 100644
index 00000000..9bd9628a
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/nv_dds.cpp
@@ -0,0 +1,1115 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+// PHYSX-CHANGES:
+// - Removed dependency on OpenGL. -jdolan
+// - MACOS does not always equate to BIG_ENDIAN... fixed it for all platforms. -jdolan
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Description:
+//
+// Loads DDS images (DXTC1, DXTC3, DXTC5, RGB (888, 888X), and RGBA (8888) are
+// supported) for use in OpenGL. Image is flipped when its loaded as DX images
+// are stored with different coordinate system. If file has mipmaps and/or
+// cubemaps then these are loaded as well. Volume textures can be loaded as
+// well but they must be uncompressed.
+//
+// When multiple textures are loaded (i.e a volume or cubemap texture),
+// additional faces can be accessed using the array operator.
+//
+// The mipmaps for each face are also stored in a list and can be accessed like
+// so: image.get_mipmap() (which accesses the first mipmap of the first
+// image). To get the number of mipmaps call the get_num_mipmaps function for
+// a given texture.
+//
+// Call the is_volume() or is_cubemap() function to check that a loaded image
+// is a volume or cubemap texture respectively. If a volume texture is loaded
+// then the get_depth() function should return a number greater than 1.
+// Mipmapped volume textures and DXTC compressed volume textures are supported.
+//
+///////////////////////////////////////////////////////////////////////////////
+//
+// Update: 9/15/2003
+//
+// Added functions to create new image from a buffer of pixels. Added function
+// to save current image to disk.
+//
+// Update: 6/11/2002
+//
+// Added some convenience functions to handle uploading textures to OpenGL. The
+// following functions have been added:
+//
+// bool upload_texture1D();
+// bool upload_texture2D(unsigned int imageIndex = 0, GLenum target = GL_TEXTURE_2D);
+// bool upload_textureRectangle();
+// bool upload_texture3D();
+// bool upload_textureCubemap();
+//
+// See function implementation below for instructions/comments on using each
+// function.
+//
+// The open function has also been updated to take an optional second parameter
+// specifying whether the image should be flipped on load. This defaults to
+// true.
+//
+///////////////////////////////////////////////////////////////////////////////
+// Sample usage
+///////////////////////////////////////////////////////////////////////////////
+//
+// Loading a compressed texture:
+//
+// CDDSImage image;
+// GLuint texobj;
+//
+// image.load("compressed.dds");
+//
+// glGenTextures(1, &texobj);
+// glEnable(GL_TEXTURE_2D);
+// glBindTexture(GL_TEXTURE_2D, texobj);
+//
+// glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, image.get_format(),
+// image.get_width(), image.get_height(), 0, image.get_size(),
+// image);
+//
+// for (int i = 0; i < image.get_num_mipmaps(); i++)
+// {
+// CSurface mipmap = image.get_mipmap(i);
+//
+// glCompressedTexImage2DARB(GL_TEXTURE_2D, i+1, image.get_format(),
+// mipmap.get_width(), mipmap.get_height(), 0, mipmap.get_size(),
+// mipmap);
+// }
+///////////////////////////////////////////////////////////////////////////////
+//
+// Loading an uncompressed texture:
+//
+// CDDSImage image;
+// GLuint texobj;
+//
+// image.load("uncompressed.dds");
+//
+// glGenTextures(1, &texobj);
+// glEnable(GL_TEXTURE_2D);
+// glBindTexture(GL_TEXTURE_2D, texobj);
+//
+// glTexImage2D(GL_TEXTURE_2D, 0, image.get_components(), image.get_width(),
+// image.get_height(), 0, image.get_format(), GL_UNSIGNED_BYTE, image);
+//
+// for (int i = 0; i < image.get_num_mipmaps(); i++)
+// {
+// glTexImage2D(GL_TEXTURE_2D, i+1, image.get_components(),
+// image.get_mipmap(i).get_width(), image.get_mipmap(i).get_height(),
+// 0, image.get_format(), GL_UNSIGNED_BYTE, image.get_mipmap(i));
+// }
+//
+///////////////////////////////////////////////////////////////////////////////
+//
+// Loading an uncompressed cubemap texture:
+//
+// CDDSImage image;
+// GLuint texobj;
+// GLenum target;
+//
+// image.load("cubemap.dds");
+//
+// glGenTextures(1, &texobj);
+// glEnable(GL_TEXTURE_CUBE_MAP_ARB);
+// glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, texobj);
+//
+// for (int n = 0; n < 6; n++)
+// {
+// target = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+n;
+//
+// glTexImage2D(target, 0, image.get_components(), image[n].get_width(),
+// image[n].get_height(), 0, image.get_format(), GL_UNSIGNED_BYTE,
+// image[n]);
+//
+// for (int i = 0; i < image[n].get_num_mipmaps(); i++)
+// {
+// glTexImage2D(target, i+1, image.get_components(),
+// image[n].get_mipmap(i).get_width(),
+// image[n].get_mipmap(i).get_height(), 0,
+// image.get_format(), GL_UNSIGNED_BYTE, image[n].get_mipmap(i));
+// }
+// }
+//
+///////////////////////////////////////////////////////////////////////////////
+//
+// Loading a volume texture:
+//
+// CDDSImage image;
+// GLuint texobj;
+//
+// image.load("volume.dds");
+//
+// glGenTextures(1, &texobj);
+// glEnable(GL_TEXTURE_3D);
+// glBindTexture(GL_TEXTURE_3D, texobj);
+//
+// PFNGLTEXIMAGE3DPROC glTexImage3D;
+// glTexImage3D(GL_TEXTURE_3D, 0, image.get_components(), image.get_width(),
+// image.get_height(), image.get_depth(), 0, image.get_format(),
+// GL_UNSIGNED_BYTE, image);
+//
+// for (int i = 0; i < image.get_num_mipmaps(); i++)
+// {
+// glTexImage3D(GL_TEXTURE_3D, i+1, image.get_components(),
+// image[0].get_mipmap(i).get_width(),
+// image[0].get_mipmap(i).get_height(),
+// image[0].get_mipmap(i).get_depth(), 0, image.get_format(),
+// GL_UNSIGNED_BYTE, image[0].get_mipmap(i));
+// }
+
+#include <stdio.h>
+#include <assert.h>
+#include "PxTkFile.h"
+#include "nv_dds.h"
+
+using namespace std;
+using namespace nv_dds;
+
+///////////////////////////////////////////////////////////////////////////////
+// CDDSImage public functions
+
+///////////////////////////////////////////////////////////////////////////////
+// default constructor
+CDDSImage::CDDSImage()
+ : m_format(TextureUnknown),
+ m_components(0),
+ m_type(TextureNone),
+ m_valid(false)
+{
+}
+
+CDDSImage::~CDDSImage()
+{
+}
+
+void CDDSImage::create_textureFlat(TextureFormat format, unsigned int components, const CTexture &baseImage)
+{
+ assert(format != 0);
+ assert(components != 0);
+ assert(baseImage.get_depth() == 1);
+
+ // remove any existing images
+ clear();
+
+ m_format = format;
+ m_components = components;
+ m_type = TextureFlat;
+
+ m_images.push_back(baseImage);
+
+ m_valid = true;
+}
+
+void CDDSImage::create_texture3D(TextureFormat format, unsigned int components, const CTexture &baseImage)
+{
+ assert(format != 0);
+ assert(components != 0);
+ assert(baseImage.get_depth() > 1);
+
+ // remove any existing images
+ clear();
+
+ m_format = format;
+ m_components = components;
+ m_type = Texture3D;
+
+ m_images.push_back(baseImage);
+
+ m_valid = true;
+}
+
+inline bool same_size(const CTexture &a, const CTexture &b)
+{
+ if (a.get_width() != b.get_width())
+ return false;
+ if (a.get_height() != b.get_height())
+ return false;
+ if (a.get_depth() != b.get_depth())
+ return false;
+
+ return true;
+}
+
+void CDDSImage::create_textureCubemap(TextureFormat format, unsigned int components,
+ const CTexture &positiveX, const CTexture &negativeX,
+ const CTexture &positiveY, const CTexture &negativeY,
+ const CTexture &positiveZ, const CTexture &negativeZ)
+{
+ assert(format != 0);
+ assert(components != 0);
+ assert(positiveX.get_depth() == 1);
+
+ // verify that all dimensions are the same
+ assert(same_size(positiveX, negativeX));
+ assert(same_size(positiveX, positiveY));
+ assert(same_size(positiveX, negativeY));
+ assert(same_size(positiveX, positiveZ));
+ assert(same_size(positiveX, negativeZ));
+
+ // remove any existing images
+ clear();
+
+ m_format = format;
+ m_components = components;
+ m_type = TextureCubemap;
+
+ m_images.push_back(positiveX);
+ m_images.push_back(negativeX);
+ m_images.push_back(positiveY);
+ m_images.push_back(negativeY);
+ m_images.push_back(positiveZ);
+ m_images.push_back(negativeZ);
+
+ m_valid = true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// loads DDS image
+//
+// filename - fully qualified name of DDS image
+// flipImage - specifies whether image is flipped on load, default is true
+bool CDDSImage::load(string filename, bool flipImage)
+{
+ assert(filename.length() != 0);
+
+ // clear any previously loaded images
+ clear();
+
+ // open file
+ SampleRenderer::File *fp = 0;
+ PxToolkit::fopen_s(&fp, filename.c_str(), "rb");
+ if (fp == NULL)
+ return false;
+
+ bool success = load(fp, flipImage);
+
+ fclose(fp);
+
+ return success;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// loads DDS image from FILE stream
+//
+// filename - fully qualified name of DDS image
+// flipImage - specifies whether image is flipped on load, default is true
+bool CDDSImage::load(SampleRenderer::File* fp, bool flipImage)
+{
+ assert(fp != 0);
+
+ // clear any previously loaded images
+ clear();
+
+ // read in file marker, make sure its a DDS file
+ char filecode[4];
+ size_t numRead = fread(filecode, 1, 4, fp);
+ if(numRead != 4) { return false; }
+
+ if (strncmp(filecode, "DDS ", 4) != 0)
+ {
+ return false;
+ }
+
+ // read in DDS header
+ DDS_HEADER ddsh;
+ numRead = fread(&ddsh, 1, sizeof(DDS_HEADER), fp);
+ if(numRead != sizeof(DDS_HEADER)) { return false; }
+
+ swap_endian(&ddsh.dwSize);
+ swap_endian(&ddsh.dwFlags);
+ swap_endian(&ddsh.dwHeight);
+ swap_endian(&ddsh.dwWidth);
+ swap_endian(&ddsh.dwPitchOrLinearSize);
+ swap_endian(&ddsh.dwMipMapCount);
+ swap_endian(&ddsh.ddspf.dwSize);
+ swap_endian(&ddsh.ddspf.dwFlags);
+ swap_endian(&ddsh.ddspf.dwFourCC);
+ swap_endian(&ddsh.ddspf.dwRGBBitCount);
+ swap_endian(&ddsh.dwCaps1);
+ swap_endian(&ddsh.dwCaps2);
+
+ // default to flat texture type (1D, 2D, or rectangle)
+ m_type = TextureFlat;
+
+ // check if image is a cubemap
+ if (ddsh.dwCaps2 & DDSF_CUBEMAP)
+ m_type = TextureCubemap;
+
+ // check if image is a volume texture
+ if ((ddsh.dwCaps2 & DDSF_VOLUME) && (ddsh.dwDepth > 0))
+ m_type = Texture3D;
+
+ // figure out what the image format is
+ if (ddsh.ddspf.dwFlags & DDSF_FOURCC)
+ {
+ switch(ddsh.ddspf.dwFourCC)
+ {
+ case FOURCC_DXT1:
+ m_format = TextureDXT1;
+ m_components = 3;
+ break;
+ case FOURCC_DXT3:
+ m_format = TextureDXT3;
+ m_components = 4;
+ break;
+ case FOURCC_DXT5:
+ m_format = TextureDXT5;
+ m_components = 4;
+ break;
+ default:
+ return false;
+ }
+ }
+ else if (ddsh.ddspf.dwFlags == DDSF_RGBA && ddsh.ddspf.dwRGBBitCount == 32)
+ {
+ m_format = TextureBGRA;
+ m_components = 4;
+ }
+ else if (ddsh.ddspf.dwFlags == DDSF_RGB && ddsh.ddspf.dwRGBBitCount == 32)
+ {
+ m_format = TextureBGRA;
+ m_components = 4;
+ }
+ else if (ddsh.ddspf.dwFlags == DDSF_RGB && ddsh.ddspf.dwRGBBitCount == 24)
+ {
+ m_format = TextureBGR;
+ m_components = 3;
+ }
+ else if (ddsh.ddspf.dwRGBBitCount == 8)
+ {
+ m_format = TextureLuminance;
+ m_components = 1;
+ }
+ else
+ {
+ return false;
+ }
+
+ // store primary surface width/height/depth
+ unsigned int width, height, depth;
+ width = ddsh.dwWidth;
+ height = ddsh.dwHeight;
+ depth = clamp_size(ddsh.dwDepth); // set to 1 if 0
+
+ // use correct size calculation function depending on whether image is
+ // compressed
+ unsigned int (CDDSImage::*sizefunc)(unsigned int, unsigned int);
+ sizefunc = (is_compressed() ? &CDDSImage::size_dxtc : &CDDSImage::size_rgb);
+
+ // load all surfaces for the image (6 surfaces for cubemaps)
+ for (unsigned int n = 0; n < (unsigned int)(m_type == TextureCubemap ? 6 : 1); n++)
+ {
+ // add empty texture object
+ m_images.push_back(CTexture());
+
+ // get reference to newly added texture object
+ CTexture &img = m_images[n];
+
+ // calculate surface size
+ unsigned int size = (this->*sizefunc)(width, height)*depth;
+
+ // load surface
+ unsigned char *pixels = new unsigned char[size];
+ numRead = fread(pixels, 1, size, fp);
+ if(numRead != size) { delete [] pixels; return false; }
+
+ img.create(width, height, depth, size, pixels);
+
+ delete [] pixels;
+
+ if (flipImage) flip(img);
+
+ unsigned int w = clamp_size(width >> 1);
+ unsigned int h = clamp_size(height >> 1);
+ unsigned int d = clamp_size(depth >> 1);
+
+ // store number of mipmaps
+ unsigned int numMipmaps = ddsh.dwMipMapCount;
+
+ // number of mipmaps in file includes main surface so decrease count
+ // by one
+ if (numMipmaps != 0)
+ numMipmaps--;
+
+ // load all mipmaps for current surface
+ for (unsigned int i = 0; i < numMipmaps && (w || h); i++)
+ {
+ // add empty surface
+ img.add_mipmap(CSurface());
+
+ // get reference to newly added mipmap
+ CSurface &mipmap = img.get_mipmap(i);
+
+ // calculate mipmap size
+ size = (this->*sizefunc)(w, h)*d;
+
+ unsigned char *pixels = new unsigned char[size];
+ numRead = fread(pixels, 1, size, fp);
+ if(numRead != size) { delete [] pixels; return false; }
+
+ mipmap.create(w, h, d, size, pixels);
+
+ delete [] pixels;
+
+ if (flipImage) flip(mipmap);
+
+ // shrink to next power of 2
+ w = clamp_size(w >> 1);
+ h = clamp_size(h >> 1);
+ d = clamp_size(d >> 1);
+ }
+ }
+
+ // swap cubemaps on y axis (since image is flipped in OGL)
+ if (m_type == TextureCubemap && flipImage)
+ {
+ CTexture tmp;
+ tmp = m_images[3];
+ m_images[3] = m_images[2];
+ m_images[2] = tmp;
+ }
+
+ m_valid = true;
+
+ return true;
+}
+
+void CDDSImage::write_texture(const CTexture &texture, SampleRenderer::File *fp)
+{
+ assert(get_num_mipmaps() == texture.get_num_mipmaps());
+
+ fwrite(texture, 1, texture.get_size(), fp);
+
+ for (unsigned int i = 0; i < texture.get_num_mipmaps(); i++)
+ {
+ const CSurface &mipmap = texture.get_mipmap(i);
+ fwrite(mipmap, 1, mipmap.get_size(), fp);
+ }
+}
+
+bool CDDSImage::save(std::string filename, bool flipImage)
+{
+ assert(m_valid);
+ assert(m_type != TextureNone);
+
+ // open file
+ SampleRenderer::File* fp = 0;
+ PxToolkit::fopen_s(&fp, filename.c_str(), "wb");
+ if (fp == NULL)
+ return false;
+
+ bool result = save(fp, flipImage);
+
+ fclose(fp);
+
+ return result;
+}
+
+bool CDDSImage::save(SampleRenderer::File* fp, bool flipImage)
+{
+ assert(m_valid);
+ assert(m_type != TextureNone);
+ assert(fp != 0);
+
+ DDS_HEADER ddsh;
+ unsigned int headerSize = sizeof(DDS_HEADER);
+ memset(&ddsh, 0, headerSize);
+ ddsh.dwSize = headerSize;
+ ddsh.dwFlags = DDSF_CAPS | DDSF_WIDTH | DDSF_HEIGHT | DDSF_PIXELFORMAT;
+ ddsh.dwHeight = get_height();
+ ddsh.dwWidth = get_width();
+
+ if (is_compressed())
+ {
+ ddsh.dwFlags |= DDSF_LINEARSIZE;
+ ddsh.dwPitchOrLinearSize = get_size();
+ }
+ else
+ {
+ ddsh.dwFlags |= DDSF_PITCH;
+ ddsh.dwPitchOrLinearSize = get_dword_aligned_linesize(get_width(), m_components * 8);
+ }
+
+ if (m_type == Texture3D)
+ {
+ ddsh.dwFlags |= DDSF_DEPTH;
+ ddsh.dwDepth = get_depth();
+ }
+
+ if (get_num_mipmaps() > 0)
+ {
+ ddsh.dwFlags |= DDSF_MIPMAPCOUNT;
+ ddsh.dwMipMapCount = get_num_mipmaps() + 1;
+ }
+
+ ddsh.ddspf.dwSize = sizeof(DDS_PIXELFORMAT);
+
+ if (is_compressed())
+ {
+ ddsh.ddspf.dwFlags = DDSF_FOURCC;
+
+ if (m_format == TextureDXT1)
+ ddsh.ddspf.dwFourCC = FOURCC_DXT1;
+ if (m_format == TextureDXT3)
+ ddsh.ddspf.dwFourCC = FOURCC_DXT3;
+ if (m_format == TextureDXT5)
+ ddsh.ddspf.dwFourCC = FOURCC_DXT5;
+ }
+ else
+ {
+ ddsh.ddspf.dwFlags = (m_components == 4) ? DDSF_RGBA : DDSF_RGB;
+ ddsh.ddspf.dwRGBBitCount = m_components * 8;
+ ddsh.ddspf.dwRBitMask = 0x00ff0000;
+ ddsh.ddspf.dwGBitMask = 0x0000ff00;
+ ddsh.ddspf.dwBBitMask = 0x000000ff;
+
+ if (m_components == 4)
+ {
+ ddsh.ddspf.dwFlags |= DDSF_ALPHAPIXELS;
+ ddsh.ddspf.dwABitMask = 0xff000000;
+ }
+ }
+
+ ddsh.dwCaps1 = DDSF_TEXTURE;
+
+ if (m_type == TextureCubemap)
+ {
+ ddsh.dwCaps1 |= DDSF_COMPLEX;
+ ddsh.dwCaps2 = DDSF_CUBEMAP | DDSF_CUBEMAP_ALL_FACES;
+ }
+
+ if (m_type == Texture3D)
+ {
+ ddsh.dwCaps1 |= DDSF_COMPLEX;
+ ddsh.dwCaps2 = DDSF_VOLUME;
+ }
+
+ if (get_num_mipmaps() > 0)
+ ddsh.dwCaps1 |= DDSF_COMPLEX | DDSF_MIPMAP;
+
+ // write file header
+ fwrite("DDS ", 1, 4, fp);
+
+ // write dds header
+ fwrite(&ddsh, 1, sizeof(DDS_HEADER), fp);
+
+ if (m_type != TextureCubemap)
+ {
+ CTexture tex = m_images[0];
+ if (flipImage) flip_texture(tex);
+ write_texture(tex, fp);
+ }
+ else
+ {
+ assert(m_images.size() == 6);
+
+ for (unsigned int i = 0; i < m_images.size(); i++)
+ {
+ CTexture cubeFace;
+
+ if (i == 2)
+ cubeFace = m_images[3];
+ else if (i == 3)
+ cubeFace = m_images[2];
+ else
+ cubeFace = m_images[i];
+
+ if (flipImage) flip_texture(cubeFace);
+ write_texture(cubeFace, fp);
+ }
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// free image memory
+void CDDSImage::clear()
+{
+ m_components = 0;
+ m_format = TextureUnknown;
+ m_type = TextureNone;
+ m_valid = false;
+
+ m_images.clear();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// clamps input size to [1-size]
+inline unsigned int CDDSImage::clamp_size(unsigned int size)
+{
+ if (size <= 0)
+ size = 1;
+
+ return size;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CDDSImage private functions
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// calculates size of DXTC texture in bytes
+inline unsigned int CDDSImage::size_dxtc(unsigned int width, unsigned int height)
+{
+ return ((width+3)/4)*((height+3)/4)*
+ (m_format == TextureDXT1 ? 8 : 16);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// calculates size of uncompressed RGB texture in bytes
+inline unsigned int CDDSImage::size_rgb(unsigned int width, unsigned int height)
+{
+ return width*height*m_components;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Swap the bytes in a 32 bit value
+inline void CDDSImage::swap_endian(void *val)
+{
+#if defined(NV_DDS_BIG_ENDIAN)
+ unsigned int *ival = (unsigned int *)val;
+
+ *ival = ((*ival >> 24) & 0x000000ff) |
+ ((*ival >> 8) & 0x0000ff00) |
+ ((*ival << 8) & 0x00ff0000) |
+ ((*ival << 24) & 0xff000000);
+#else
+ (void)val;
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// flip image around X axis
+void CDDSImage::flip(CSurface &surface)
+{
+ unsigned int linesize;
+ unsigned int offset;
+
+ if (!is_compressed())
+ {
+ assert(surface.get_depth() > 0);
+
+ unsigned int imagesize = surface.get_size()/surface.get_depth();
+ linesize = imagesize / surface.get_height();
+
+ for (unsigned int n = 0; n < surface.get_depth(); n++)
+ {
+ offset = imagesize*n;
+ unsigned char *top = (unsigned char*)surface + offset;
+ unsigned char *bottom = top + (imagesize-linesize);
+
+ for (unsigned int i = 0; i < (surface.get_height() >> 1); i++)
+ {
+ swap(bottom, top, linesize);
+
+ top += linesize;
+ bottom -= linesize;
+ }
+ }
+ }
+ else
+ {
+ void (CDDSImage::*flipblocks)(DXTColBlock*, unsigned int);
+ unsigned int xblocks = surface.get_width() / 4;
+ unsigned int yblocks = surface.get_height() / 4;
+ unsigned int blocksize;
+
+ switch (m_format)
+ {
+ case TextureDXT1:
+ blocksize = 8;
+ flipblocks = &CDDSImage::flip_blocks_dxtc1;
+ break;
+ case TextureDXT3:
+ blocksize = 16;
+ flipblocks = &CDDSImage::flip_blocks_dxtc3;
+ break;
+ case TextureDXT5:
+ blocksize = 16;
+ flipblocks = &CDDSImage::flip_blocks_dxtc5;
+ break;
+ default:
+ return;
+ }
+
+ linesize = xblocks * blocksize;
+
+ DXTColBlock *top;
+ DXTColBlock *bottom;
+
+ for (unsigned int j = 0; j < (yblocks >> 1); j++)
+ {
+ top = (DXTColBlock*)((unsigned char*)surface+ j * linesize);
+ bottom = (DXTColBlock*)((unsigned char*)surface + (((yblocks-j)-1) * linesize));
+
+ (this->*flipblocks)(top, xblocks);
+ (this->*flipblocks)(bottom, xblocks);
+
+ swap(bottom, top, linesize);
+ }
+ }
+}
+
+void CDDSImage::flip_texture(CTexture &texture)
+{
+ flip(texture);
+
+ for (unsigned int i = 0; i < texture.get_num_mipmaps(); i++)
+ {
+ flip(texture.get_mipmap(i));
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// swap to sections of memory
+void CDDSImage::swap(void *byte1, void *byte2, unsigned int size)
+{
+ unsigned char *tmp = new unsigned char[size];
+
+ memcpy(tmp, byte1, size);
+ memcpy(byte1, byte2, size);
+ memcpy(byte2, tmp, size);
+
+ delete [] tmp;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// flip a DXT1 color block
+void CDDSImage::flip_blocks_dxtc1(DXTColBlock *line, unsigned int numBlocks)
+{
+ DXTColBlock *curblock = line;
+
+ for (unsigned int i = 0; i < numBlocks; i++)
+ {
+ swap(&curblock->row[0], &curblock->row[3], sizeof(unsigned char));
+ swap(&curblock->row[1], &curblock->row[2], sizeof(unsigned char));
+
+ curblock++;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// flip a DXT3 color block
+void CDDSImage::flip_blocks_dxtc3(DXTColBlock *line, unsigned int numBlocks)
+{
+ DXTColBlock *curblock = line;
+ DXT3AlphaBlock *alphablock;
+
+ for (unsigned int i = 0; i < numBlocks; i++)
+ {
+ alphablock = (DXT3AlphaBlock*)curblock;
+
+ swap(&alphablock->row[0], &alphablock->row[3], sizeof(unsigned short));
+ swap(&alphablock->row[1], &alphablock->row[2], sizeof(unsigned short));
+
+ curblock++;
+
+ swap(&curblock->row[0], &curblock->row[3], sizeof(unsigned char));
+ swap(&curblock->row[1], &curblock->row[2], sizeof(unsigned char));
+
+ curblock++;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// flip a DXT5 alpha block
+void CDDSImage::flip_dxt5_alpha(DXT5AlphaBlock *block)
+{
+ unsigned char gBits[4][4];
+
+ const unsigned int mask = 0x00000007; // bits = 00 00 01 11
+ unsigned int bits = 0;
+ memcpy(&bits, &block->row[0], sizeof(unsigned char) * 3);
+
+ gBits[0][0] = (unsigned char)(bits & mask);
+ bits >>= 3;
+ gBits[0][1] = (unsigned char)(bits & mask);
+ bits >>= 3;
+ gBits[0][2] = (unsigned char)(bits & mask);
+ bits >>= 3;
+ gBits[0][3] = (unsigned char)(bits & mask);
+ bits >>= 3;
+ gBits[1][0] = (unsigned char)(bits & mask);
+ bits >>= 3;
+ gBits[1][1] = (unsigned char)(bits & mask);
+ bits >>= 3;
+ gBits[1][2] = (unsigned char)(bits & mask);
+ bits >>= 3;
+ gBits[1][3] = (unsigned char)(bits & mask);
+
+ bits = 0;
+ memcpy(&bits, &block->row[3], sizeof(unsigned char) * 3);
+
+ gBits[2][0] = (unsigned char)(bits & mask);
+ bits >>= 3;
+ gBits[2][1] = (unsigned char)(bits & mask);
+ bits >>= 3;
+ gBits[2][2] = (unsigned char)(bits & mask);
+ bits >>= 3;
+ gBits[2][3] = (unsigned char)(bits & mask);
+ bits >>= 3;
+ gBits[3][0] = (unsigned char)(bits & mask);
+ bits >>= 3;
+ gBits[3][1] = (unsigned char)(bits & mask);
+ bits >>= 3;
+ gBits[3][2] = (unsigned char)(bits & mask);
+ bits >>= 3;
+ gBits[3][3] = (unsigned char)(bits & mask);
+
+ unsigned int *pBits = ((unsigned int*) &(block->row[0]));
+
+ *pBits = *pBits | (gBits[3][0] << 0);
+ *pBits = *pBits | (gBits[3][1] << 3);
+ *pBits = *pBits | (gBits[3][2] << 6);
+ *pBits = *pBits | (gBits[3][3] << 9);
+
+ *pBits = *pBits | (gBits[2][0] << 12);
+ *pBits = *pBits | (gBits[2][1] << 15);
+ *pBits = *pBits | (gBits[2][2] << 18);
+ *pBits = *pBits | (gBits[2][3] << 21);
+
+ pBits = ((unsigned int*) &(block->row[3]));
+
+#if defined(NV_DDS_BIG_ENDIAN)
+ *pBits &= 0x000000ff;
+#else
+ *pBits &= 0xff000000;
+#endif
+
+ *pBits = *pBits | (gBits[1][0] << 0);
+ *pBits = *pBits | (gBits[1][1] << 3);
+ *pBits = *pBits | (gBits[1][2] << 6);
+ *pBits = *pBits | (gBits[1][3] << 9);
+
+ *pBits = *pBits | (gBits[0][0] << 12);
+ *pBits = *pBits | (gBits[0][1] << 15);
+ *pBits = *pBits | (gBits[0][2] << 18);
+ *pBits = *pBits | (gBits[0][3] << 21);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// flip a DXT5 color block
+void CDDSImage::flip_blocks_dxtc5(DXTColBlock *line, unsigned int numBlocks)
+{
+ DXTColBlock *curblock = line;
+ DXT5AlphaBlock *alphablock;
+
+ for (unsigned int i = 0; i < numBlocks; i++)
+ {
+ alphablock = (DXT5AlphaBlock*)curblock;
+
+ flip_dxt5_alpha(alphablock);
+
+ curblock++;
+
+ swap(&curblock->row[0], &curblock->row[3], sizeof(unsigned char));
+ swap(&curblock->row[1], &curblock->row[2], sizeof(unsigned char));
+
+ curblock++;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CTexture implementation
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// default constructor
+CTexture::CTexture()
+ : CSurface() // initialize base class part
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// creates an empty texture
+CTexture::CTexture(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char *pixels)
+ : CSurface(w, h, d, imgsize, pixels) // initialize base class part
+{
+}
+
+CTexture::~CTexture()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// copy constructor
+CTexture::CTexture(const CTexture &copy)
+ : CSurface(copy)
+{
+ for (unsigned int i = 0; i < copy.get_num_mipmaps(); i++)
+ m_mipmaps.push_back(copy.get_mipmap(i));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// assignment operator
+CTexture &CTexture::operator= (const CTexture &rhs)
+{
+ if (this != &rhs)
+ {
+ CSurface::operator = (rhs);
+
+ m_mipmaps.clear();
+ for (unsigned int i = 0; i < rhs.get_num_mipmaps(); i++)
+ m_mipmaps.push_back(rhs.get_mipmap(i));
+ }
+
+ return *this;
+}
+
+void CTexture::create(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char *pixels)
+{
+ CSurface::create(w, h, d, imgsize, pixels);
+
+ m_mipmaps.clear();
+}
+
+void CTexture::clear()
+{
+ CSurface::clear();
+
+ m_mipmaps.clear();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CSurface implementation
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// default constructor
+CSurface::CSurface()
+ : m_width(0),
+ m_height(0),
+ m_depth(0),
+ m_size(0),
+ m_pixels(NULL)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// creates an empty image
+CSurface::CSurface(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char *pixels)
+ : m_width(0),
+ m_height(0),
+ m_depth(0),
+ m_size(0),
+ m_pixels(NULL)
+{
+ create(w, h, d, imgsize, pixels);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// copy constructor
+CSurface::CSurface(const CSurface &copy)
+ : m_width(0),
+ m_height(0),
+ m_depth(0),
+ m_size(0),
+ m_pixels(NULL)
+{
+ if (copy.get_size() != 0)
+ {
+ m_size = copy.get_size();
+ m_width = copy.get_width();
+ m_height = copy.get_height();
+ m_depth = copy.get_depth();
+
+ m_pixels = new unsigned char[m_size];
+ memcpy(m_pixels, copy, m_size);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// assignment operator
+CSurface &CSurface::operator= (const CSurface &rhs)
+{
+ if (this != &rhs)
+ {
+ clear();
+
+ if (rhs.get_size())
+ {
+ m_size = rhs.get_size();
+ m_width = rhs.get_width();
+ m_height = rhs.get_height();
+ m_depth = rhs.get_depth();
+
+ m_pixels = new unsigned char[m_size];
+ memcpy(m_pixels, rhs, m_size);
+ }
+ }
+
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// clean up image memory
+CSurface::~CSurface()
+{
+ clear();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// returns a pointer to image
+CSurface::operator unsigned char*() const
+{
+ return m_pixels;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// creates an empty image
+void CSurface::create(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char *pixels)
+{
+ assert(w != 0);
+ assert(h != 0);
+ assert(d != 0);
+ assert(imgsize != 0);
+ assert(pixels);
+
+ clear();
+
+ m_width = w;
+ m_height = h;
+ m_depth = d;
+ m_size = imgsize;
+ m_pixels = new unsigned char[imgsize];
+ memcpy(m_pixels, pixels, imgsize);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// free surface memory
+void CSurface::clear()
+{
+ if (m_pixels != NULL)
+ {
+ delete [] m_pixels;
+ m_pixels = NULL;
+ }
+}
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/nv_dds.h b/PhysX_3.4/Samples/SampleFramework/framework/src/nv_dds.h
new file mode 100644
index 00000000..cafe65bc
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/nv_dds.h
@@ -0,0 +1,378 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+
+// PHYSX-CHANGES:
+// - Removed dependency on OpenGL. -jdolan
+// - MACOS does not always equate to BIG_ENDIAN... fixed it for all platforms. -jdolan
+// - 64 bit fix for unix based platforms (replaced unsigned long with unsigned int) -sschirm
+
+#ifndef NV_DDS_H
+#define NV_DDS_H
+
+#include <string>
+#include <deque>
+#include <assert.h>
+#include <stdio.h>
+
+#include <RendererConfig.h>
+
+#if defined(__APPLE__)
+ #if BYTE_ORDER == BIG_ENDIAN
+ #define NV_DDS_BIG_ENDIAN
+ #endif
+#elif defined(RENDERER_XBOX360) && _XBOX_VER == 200
+ #define NV_DDS_BIG_ENDIAN
+#elif defined(RENDERER_PS3)
+ #define NV_DDS_BIG_ENDIAN
+#elif defined(RENDERER_WIIU)
+ #define NV_DDS_BIG_ENDIAN
+#endif
+
+namespace nv_dds
+{
+ // surface description flags
+ const unsigned int DDSF_CAPS = 0x00000001l;
+ const unsigned int DDSF_HEIGHT = 0x00000002l;
+ const unsigned int DDSF_WIDTH = 0x00000004l;
+ const unsigned int DDSF_PITCH = 0x00000008l;
+ const unsigned int DDSF_PIXELFORMAT = 0x00001000l;
+ const unsigned int DDSF_MIPMAPCOUNT = 0x00020000l;
+ const unsigned int DDSF_LINEARSIZE = 0x00080000l;
+ const unsigned int DDSF_DEPTH = 0x00800000l;
+
+ // pixel format flags
+ const unsigned int DDSF_ALPHAPIXELS = 0x00000001l;
+ const unsigned int DDSF_FOURCC = 0x00000004l;
+ const unsigned int DDSF_RGB = 0x00000040l;
+ const unsigned int DDSF_RGBA = 0x00000041l;
+
+ // dwCaps1 flags
+ const unsigned int DDSF_COMPLEX = 0x00000008l;
+ const unsigned int DDSF_TEXTURE = 0x00001000l;
+ const unsigned int DDSF_MIPMAP = 0x00400000l;
+
+ // dwCaps2 flags
+ const unsigned int DDSF_CUBEMAP = 0x00000200l;
+ const unsigned int DDSF_CUBEMAP_POSITIVEX = 0x00000400l;
+ const unsigned int DDSF_CUBEMAP_NEGATIVEX = 0x00000800l;
+ const unsigned int DDSF_CUBEMAP_POSITIVEY = 0x00001000l;
+ const unsigned int DDSF_CUBEMAP_NEGATIVEY = 0x00002000l;
+ const unsigned int DDSF_CUBEMAP_POSITIVEZ = 0x00004000l;
+ const unsigned int DDSF_CUBEMAP_NEGATIVEZ = 0x00008000l;
+ const unsigned int DDSF_CUBEMAP_ALL_FACES = 0x0000FC00l;
+ const unsigned int DDSF_VOLUME = 0x00200000l;
+
+ // compressed texture types
+ const unsigned int FOURCC_DXT1 = 0x31545844l; //(MAKEFOURCC('D','X','T','1'))
+ const unsigned int FOURCC_DXT3 = 0x33545844l; //(MAKEFOURCC('D','X','T','3'))
+ const unsigned int FOURCC_DXT5 = 0x35545844l; //(MAKEFOURCC('D','X','T','5'))
+
+ struct DXTColBlock
+ {
+ unsigned short col0;
+ unsigned short col1;
+
+ unsigned char row[4];
+ };
+
+ struct DXT3AlphaBlock
+ {
+ unsigned short row[4];
+ };
+
+ struct DXT5AlphaBlock
+ {
+ unsigned char alpha0;
+ unsigned char alpha1;
+
+ unsigned char row[6];
+ };
+
+ struct DDS_PIXELFORMAT
+ {
+ unsigned int dwSize;
+ unsigned int dwFlags;
+ unsigned int dwFourCC;
+ unsigned int dwRGBBitCount;
+ unsigned int dwRBitMask;
+ unsigned int dwGBitMask;
+ unsigned int dwBBitMask;
+ unsigned int dwABitMask;
+ };
+
+ struct DDS_HEADER
+ {
+ unsigned int dwSize;
+ unsigned int dwFlags;
+ unsigned int dwHeight;
+ unsigned int dwWidth;
+ unsigned int dwPitchOrLinearSize;
+ unsigned int dwDepth;
+ unsigned int dwMipMapCount;
+ unsigned int dwReserved1[11];
+ DDS_PIXELFORMAT ddspf;
+ unsigned int dwCaps1;
+ unsigned int dwCaps2;
+ unsigned int dwReserved2[3];
+ };
+
+ enum TextureType
+ {
+ TextureNone,
+ TextureFlat, // 1D, 2D, and rectangle textures
+ Texture3D,
+ TextureCubemap
+ };
+
+ enum TextureFormat
+ {
+ TextureUnknown=0,
+ TextureBGRA,
+ TextureBGR,
+ TextureLuminance,
+ TextureDXT1,
+ TextureDXT3,
+ TextureDXT5,
+ };
+
+ class CSurface
+ {
+ public:
+ CSurface();
+ CSurface(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char *pixels);
+ CSurface(const CSurface &copy);
+ CSurface &operator= (const CSurface &rhs);
+ virtual ~CSurface();
+
+ operator unsigned char*() const;
+
+ virtual void create(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char *pixels);
+ virtual void clear();
+
+ inline unsigned int get_width() const { return m_width; }
+ inline unsigned int get_height() const { return m_height; }
+ inline unsigned int get_depth() const { return m_depth; }
+ inline unsigned int get_size() const { return m_size; }
+
+ private:
+ unsigned int m_width;
+ unsigned int m_height;
+ unsigned int m_depth;
+ unsigned int m_size;
+
+ unsigned char *m_pixels;
+ };
+
+ class CTexture : public CSurface
+ {
+ friend class CDDSImage;
+
+ public:
+ CTexture();
+ CTexture(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char *pixels);
+ CTexture(const CTexture &copy);
+ CTexture &operator= (const CTexture &rhs);
+ ~CTexture();
+
+ void create(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char *pixels);
+ void clear();
+
+ inline const CSurface &get_mipmap(unsigned int index) const
+ {
+ assert(!m_mipmaps.empty());
+ assert(index < m_mipmaps.size());
+
+ return m_mipmaps[index];
+ }
+
+ inline void add_mipmap(const CSurface &mipmap)
+ {
+ m_mipmaps.push_back(mipmap);
+ }
+
+ inline unsigned int get_num_mipmaps() const { return (unsigned int)m_mipmaps.size(); }
+
+ protected:
+ inline CSurface &get_mipmap(unsigned int index)
+ {
+ assert(!m_mipmaps.empty());
+ assert(index < m_mipmaps.size());
+
+ return m_mipmaps[index];
+ }
+
+ private:
+ std::deque<CSurface> m_mipmaps;
+ };
+
+ class CDDSImage
+ {
+ public:
+ CDDSImage();
+ ~CDDSImage();
+
+ void create_textureFlat(TextureFormat format, unsigned int components, const CTexture &baseImage);
+ void create_texture3D(TextureFormat format, unsigned int components, const CTexture &baseImage);
+ void create_textureCubemap(TextureFormat format, unsigned int components,
+ const CTexture &positiveX, const CTexture &negativeX,
+ const CTexture &positiveY, const CTexture &negativeY,
+ const CTexture &positiveZ, const CTexture &negativeZ);
+
+ void clear();
+ bool load(std::string filename, bool flipImage = true);
+ bool load(SampleRenderer::File* fp, bool flipImage = true);
+ bool save(std::string filename, bool flipImage = true);
+ bool save(SampleRenderer::File* fp, bool flipImage = true);
+
+ inline operator unsigned char*()
+ {
+ assert(m_valid);
+ assert(!m_images.empty());
+
+ return m_images[0];
+ }
+
+ inline unsigned int get_width()
+ {
+ assert(m_valid);
+ assert(!m_images.empty());
+
+ return m_images[0].get_width();
+ }
+
+ inline unsigned int get_height()
+ {
+ assert(m_valid);
+ assert(!m_images.empty());
+
+ return m_images[0].get_height();
+ }
+
+ inline unsigned int get_depth()
+ {
+ assert(m_valid);
+ assert(!m_images.empty());
+
+ return m_images[0].get_depth();
+ }
+
+ inline unsigned int get_size()
+ {
+ assert(m_valid);
+ assert(!m_images.empty());
+
+ return m_images[0].get_size();
+ }
+
+ inline unsigned int get_num_mipmaps()
+ {
+ assert(m_valid);
+ assert(!m_images.empty());
+
+ return m_images[0].get_num_mipmaps();
+ }
+
+ inline const CSurface &get_mipmap(unsigned int index) const
+ {
+ assert(m_valid);
+ assert(!m_images.empty());
+ assert(index < m_images[0].get_num_mipmaps());
+
+ return m_images[0].get_mipmap(index);
+ }
+
+ inline const CTexture &get_cubemap_face(unsigned int face) const
+ {
+ assert(m_valid);
+ assert(!m_images.empty());
+ assert(m_images.size() == 6);
+ assert(m_type == TextureCubemap);
+ assert(face < 6);
+
+ return m_images[face];
+ }
+
+ inline unsigned int get_components() { return m_components; }
+ inline TextureFormat get_format() { return m_format; }
+ inline TextureType get_type() { return m_type; }
+
+ inline bool is_compressed()
+ {
+ if ((m_format == TextureDXT1) ||
+ (m_format == TextureDXT3) ||
+ (m_format == TextureDXT5))
+ return true;
+ else
+ return false;
+ }
+
+ inline bool is_cubemap() { return (m_type == TextureCubemap); }
+ inline bool is_volume() { return (m_type == Texture3D); }
+ inline bool is_valid() { return m_valid; }
+
+ inline bool is_dword_aligned()
+ {
+ assert(m_valid);
+
+ int dwordLineSize = get_dword_aligned_linesize(get_width(), m_components*8);
+ int curLineSize = get_width() * m_components;
+
+ return (dwordLineSize == curLineSize);
+ }
+
+ private:
+ unsigned int clamp_size(unsigned int size);
+ unsigned int size_dxtc(unsigned int width, unsigned int height);
+ unsigned int size_rgb(unsigned int width, unsigned int height);
+ inline void swap_endian(void *val);
+
+ // calculates 4-byte aligned width of image
+ inline unsigned int get_dword_aligned_linesize(unsigned int width, unsigned int bpp)
+ {
+ return ((width * bpp + 31) & (unsigned int)(-32)) >> 3;
+ }
+
+ void flip(CSurface &surface);
+ void flip_texture(CTexture &texture);
+
+ void swap(void *byte1, void *byte2, unsigned int size);
+ void flip_blocks_dxtc1(DXTColBlock *line, unsigned int numBlocks);
+ void flip_blocks_dxtc3(DXTColBlock *line, unsigned int numBlocks);
+ void flip_blocks_dxtc5(DXTColBlock *line, unsigned int numBlocks);
+ void flip_dxt5_alpha(DXT5AlphaBlock *block);
+
+ void write_texture(const CTexture &texture, SampleRenderer::File *fp);
+
+ TextureFormat m_format;
+ unsigned int m_components;
+ TextureType m_type;
+ bool m_valid;
+
+ std::deque<CTexture> m_images;
+ };
+}
+#endif
diff --git a/PhysX_3.4/Samples/SampleFramework/framework/src/windows/WindowsSampleAssetManager.cpp b/PhysX_3.4/Samples/SampleFramework/framework/src/windows/WindowsSampleAssetManager.cpp
new file mode 100644
index 00000000..a2bfaa82
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/framework/src/windows/WindowsSampleAssetManager.cpp
@@ -0,0 +1,48 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+#include <SampleAssetManager.h>
+
+#define NOMINMAX
+#include <windows.h>
+
+
+bool SampleFramework::searchForPath(const char* path, char* buffer, int bufferSize, bool isReadOnly, int maxRecursion)
+{
+ char* tmpBuffer = (char*)alloca(bufferSize);
+ strcpy_s(buffer, bufferSize, path);
+ for(int i = 0; i < maxRecursion; i++)
+ {
+ if(GetFileAttributes(buffer) == INVALID_FILE_ATTRIBUTES)
+ {
+ sprintf_s(tmpBuffer, bufferSize, "../%s", buffer);
+ strcpy_s(buffer, bufferSize, tmpBuffer);
+ }
+ else
+ return true;
+ }
+ return false;
+}