aboutsummaryrefslogtreecommitdiff
path: root/APEX_1.4/module/clothing/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 /APEX_1.4/module/clothing/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 'APEX_1.4/module/clothing/src')
-rw-r--r--APEX_1.4/module/clothing/src/ClothingActorData.cpp1161
-rw-r--r--APEX_1.4/module/clothing/src/ClothingActorImpl.cpp4852
-rw-r--r--APEX_1.4/module/clothing/src/ClothingActorTasks.cpp99
-rw-r--r--APEX_1.4/module/clothing/src/ClothingAssetAuthoringImpl.cpp3931
-rw-r--r--APEX_1.4/module/clothing/src/ClothingAssetData.cpp874
-rw-r--r--APEX_1.4/module/clothing/src/ClothingAssetImpl.cpp3849
-rw-r--r--APEX_1.4/module/clothing/src/ClothingCollisionImpl.cpp324
-rw-r--r--APEX_1.4/module/clothing/src/ClothingCooking.cpp163
-rw-r--r--APEX_1.4/module/clothing/src/ClothingPhysicalMeshImpl.cpp1576
-rw-r--r--APEX_1.4/module/clothing/src/ClothingRenderProxyImpl.cpp270
-rw-r--r--APEX_1.4/module/clothing/src/ClothingScene.cpp889
-rw-r--r--APEX_1.4/module/clothing/src/CookingAbstract.cpp76
-rw-r--r--APEX_1.4/module/clothing/src/ModuleClothingHelpers.cpp90
-rw-r--r--APEX_1.4/module/clothing/src/ModuleClothingImpl.cpp1210
-rw-r--r--APEX_1.4/module/clothing/src/SimulationAbstract.cpp55
-rw-r--r--APEX_1.4/module/clothing/src/autogen/ClothingActorParam.cpp2394
-rw-r--r--APEX_1.4/module/clothing/src/autogen/ClothingAssetParameters.cpp2046
-rw-r--r--APEX_1.4/module/clothing/src/autogen/ClothingCookedParam.cpp970
-rw-r--r--APEX_1.4/module/clothing/src/autogen/ClothingCookedPhysX3Param.cpp1557
-rw-r--r--APEX_1.4/module/clothing/src/autogen/ClothingDebugRenderParams.cpp1327
-rw-r--r--APEX_1.4/module/clothing/src/autogen/ClothingGraphicalLodParameters.cpp1491
-rw-r--r--APEX_1.4/module/clothing/src/autogen/ClothingMaterialLibraryParameters.cpp1593
-rw-r--r--APEX_1.4/module/clothing/src/autogen/ClothingModuleParameters.cpp583
-rw-r--r--APEX_1.4/module/clothing/src/autogen/ClothingPhysicalMeshParameters.cpp2418
-rw-r--r--APEX_1.4/module/clothing/src/autogen/ClothingPreviewParam.cpp506
25 files changed, 34304 insertions, 0 deletions
diff --git a/APEX_1.4/module/clothing/src/ClothingActorData.cpp b/APEX_1.4/module/clothing/src/ClothingActorData.cpp
new file mode 100644
index 00000000..a3084779
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/ClothingActorData.cpp
@@ -0,0 +1,1161 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+#include "ApexSimdMath.h"
+#include "PxPreprocessor.h"
+#include "RenderDataFormat.h"
+#include "ClothingActorData.h"
+#include "AbstractMeshDescription.h"
+#include "PsIntrinsics.h"
+#include "PxMat44.h"
+#include "ApexSDKIntl.h"
+
+#include "ClothingGlobals.h"
+
+#include "ProfilerCallback.h"
+
+using namespace physx::shdfnd;
+
+#pragma warning(disable : 4101 4127) // unreferenced local variable and conditional is constant
+
+#define NX_PARAMETERIZED_ONLY_LAYOUTS
+#include "ClothingGraphicalLodParameters.h"
+
+#include "PsIntrinsics.h"
+#include "PsVecMath.h"
+
+namespace nvidia
+{
+namespace clothing
+{
+
+
+ClothingActorData::ClothingActorData() :
+ mNewBounds(PxBounds3::empty()),
+
+ mGlobalPose(PxVec4(1.0f)),
+ mInternalGlobalPose(PxVec4(1.0f)),
+
+ mInternalBoneMatricesCur(NULL),
+ mInternalBoneMatricesPrev(NULL),
+ mRenderingDataPosition(NULL),
+ mRenderingDataNormal(NULL),
+ mRenderingDataTangent(NULL),
+ mMorphDisplacementBuffer(NULL),
+ mSdkWritebackNormal(NULL),
+ mSdkWritebackPositions(NULL),
+ mSkinnedPhysicsPositions(NULL),
+ mSkinnedPhysicsNormals(NULL),
+
+ mInternalMatricesCount(0),
+ mMorphDisplacementBufferCount(0),
+ mSdkDeformableVerticesCount(0),
+ mSdkDeformableIndicesCount(0),
+ mCurrentGraphicalLodId(0),
+ mCurrentPhysicsSubmesh(0),
+
+ mActorScale(0.0f),
+
+ bInternalFrozen(false),
+ bShouldComputeRenderData(false),
+ bIsInitialized(false),
+ bIsSimulationMeshDirty(false),
+ bRecomputeNormals(false),
+ bRecomputeTangents(false),
+ bCorrectSimulationNormals(false),
+ bParallelCpuSkinning(false),
+ bIsClothingSimulationNull(false)
+{
+}
+
+
+
+ClothingActorData::~ClothingActorData()
+{
+ PX_ASSERT(mInternalBoneMatricesCur == NULL); // properly deallocated
+}
+
+
+
+void ClothingActorData::renderDataLock()
+{
+ mRenderLock.lock();
+}
+
+
+
+void ClothingActorData::renderDataUnLock()
+{
+ //TODO - release a mutex here
+ mRenderLock.unlock();
+}
+
+
+
+void ClothingActorData::skinPhysicsMaxDist0Normals_NoPhysx()
+{
+ if (mSdkWritebackNormal == NULL /*|| bInternalFrozen == 1*/)
+ {
+ return;
+ }
+
+ //ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+
+ ClothingPhysicalMeshData* physicalMesh = mAsset.GetPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ const PxVec3* PX_RESTRICT _normals = physicalMesh->mSkinningNormals;
+
+ if (_normals == NULL)
+ {
+ return;
+ }
+
+ if (physicalMesh->mMaxDistance0VerticesCount == 0)
+ {
+ return;
+ }
+
+ const uint32_t startVertex = physicalMesh->mSimulatedVertexCount - physicalMesh->mMaxDistance0VerticesCount;
+ const uint32_t numVertices = physicalMesh->mSimulatedVertexCount;
+ const uint32_t numBoneIndicesPerVertex = physicalMesh->mNumBonesPerVertex;
+
+ // offset the normals array as well
+ _normals += startVertex;
+
+ const uint32_t UnrollSize = 160;
+ const uint32_t vertCount = numVertices - startVertex;
+ const uint32_t numIterations = (vertCount + UnrollSize - 1) / UnrollSize;
+
+ PxVec3* PX_RESTRICT targetNormals = mSdkWritebackNormal + startVertex;
+
+ //uint32_t tags[2] = {10, 11};
+ //const uint32_t prefetchRange = (startVertex & 0xfffffff0); //A multiple of 16 before this prefetch, with the assumption that normals is 16-byte aligned!
+ //C_Prefetcher<2, sizeof(PxVec3) * UnrollSize> normPrefetcher(tags, (void*)(normals + prefetchRange), (void*)(normals + numVertices));
+
+ if (mInternalBoneMatricesCur == NULL || numBoneIndicesPerVertex == 0)
+ {
+ if (mActorScale == 1.0f)
+ {
+ for (uint32_t a = 0; a < numIterations; ++a)
+ {
+ const uint32_t numToProcess = PxMin(UnrollSize, (vertCount - (UnrollSize * a)));
+ const PxVec3* PX_RESTRICT localNormals = (const PxVec3 * PX_RESTRICT)(void*)_normals;
+ for (uint32_t i = 0; i < numToProcess; i++)
+ {
+ targetNormals[i] = mInternalGlobalPose.rotate(localNormals[i]);
+ }
+ targetNormals += UnrollSize;
+ _normals += UnrollSize;
+ }
+ }
+ else
+ {
+ const float recipActorScale = 1.f / mActorScale;
+ for (uint32_t a = 0; a < numIterations; ++a)
+ {
+ const uint32_t numToProcess = PxMin(UnrollSize, (vertCount - (UnrollSize * a)));
+ const PxVec3* PX_RESTRICT localNormals = (const PxVec3 * PX_RESTRICT)(void*)_normals;
+ for (uint32_t i = 0; i < numToProcess; i++)
+ {
+ targetNormals[i] = mInternalGlobalPose.rotate(localNormals[i]) * recipActorScale;
+ }
+ targetNormals += UnrollSize;
+ _normals += UnrollSize;
+ }
+ }
+ }
+ else
+ {
+ //OK a slight refactor is required here - we don't want to fetch in everything only to
+ const uint32_t startBoneIndex = startVertex * numBoneIndicesPerVertex;
+ //Another problem - this is an arbitrarily large amount of data that has to be fetched here!!!! Consider revising
+
+ const uint16_t* PX_RESTRICT eaSimBoneIndices = &physicalMesh->mBoneIndices[startBoneIndex];
+ const float* PX_RESTRICT eaSimBoneWeights = &physicalMesh->mBoneWeights[startBoneIndex];
+
+ const PxMat44* const PX_RESTRICT matrices = (const PxMat44*)mInternalBoneMatricesCur;
+
+ for (uint32_t a = 0; a < numIterations; ++a)
+ {
+ const uint32_t numToProcess = PxMin(UnrollSize, (vertCount - (UnrollSize * a)));
+ const PxVec3* PX_RESTRICT localNormals = (const PxVec3 * PX_RESTRICT)(void*)_normals;
+
+ const uint16_t* const PX_RESTRICT simBoneIndices = (const uint16_t * const PX_RESTRICT)(void*)eaSimBoneIndices;
+ const float* const PX_RESTRICT simBoneWeights = (const float * const PX_RESTRICT)(void*)eaSimBoneWeights;
+
+ eaSimBoneIndices += numBoneIndicesPerVertex * numToProcess;
+ eaSimBoneWeights += numBoneIndicesPerVertex * numToProcess;
+
+ for (uint32_t i = 0; i < numToProcess; i++)
+ {
+ PxVec3 normal(0.0f, 0.0f, 0.0f);
+ for (uint32_t j = 0; j < numBoneIndicesPerVertex; j++)
+ {
+ const float weight = simBoneWeights[i * numBoneIndicesPerVertex + j];
+
+ if (weight > 0.f)
+ {
+ PX_ASSERT(weight <= 1.0f);
+ const uint32_t index = simBoneIndices[i * numBoneIndicesPerVertex + j];
+
+ const PxMat44& bone = matrices[index];
+
+ normal += bone.rotate(localNormals[i]) * weight; // 12% here
+ }
+ else
+ {
+ // PH: Assuming sorted weights is faster
+ break;
+ }
+ }
+
+ normal.normalize();
+ targetNormals[i] = normal;
+ }
+ targetNormals += UnrollSize;
+ _normals += UnrollSize;
+ }
+
+ }
+
+}
+
+
+void ClothingActorData::skinToAnimation_NoPhysX(bool fromFetchResults)
+{
+ // This optimization only works if the render data from last frame is still there.
+ // So this can only be used if we're using the same ClothingRenderProxy again.
+ //if (!bIsSimulationMeshDirty)
+ //{
+ // return;
+ //}
+
+ PX_PROFILE_ZONE("ClothingActorImpl::skinToAnimation", GetInternalApexSDK()->getContextId());
+
+ //const bool recomputeNormals = bRecomputeNormals;
+
+ // PH: If fromFetchResults is true, renderLock does not need to be aquired as it is already aquired by ApexScene::fetchResults()
+ if (!fromFetchResults)
+ {
+ renderDataLock();
+ }
+
+ for (uint32_t graphicalLod = 0; graphicalLod < mAsset.mGraphicalLodsCount; graphicalLod++)
+ {
+ ClothingMeshAssetData& meshAsset = *mAsset.GetLod(graphicalLod);
+ if (!meshAsset.bActive)
+ {
+ continue;
+ }
+
+ uint32_t submeshVertexOffset = 0;
+
+ for (uint32_t submeshIndex = 0; submeshIndex < meshAsset.mSubMeshCount; submeshIndex++)
+ {
+ AbstractMeshDescription renderData;
+ ClothingAssetSubMesh* pSubMesh = mAsset.GetSubmesh(&meshAsset, submeshIndex);
+ renderData.numVertices = pSubMesh->mVertexCount;
+
+ renderData.pPosition = mRenderingDataPosition + submeshVertexOffset;
+
+ renderData.pNormal = mRenderingDataNormal + submeshVertexOffset;
+
+ if (mRenderingDataTangent != NULL)
+ {
+ renderData.pTangent4 = mRenderingDataTangent + submeshVertexOffset;
+ }
+
+ PxMat44* matrices = NULL;
+ PX_ALIGN(16, PxMat44 alignedGlobalPose); // matrices must be 16 byte aligned!
+ if (mInternalBoneMatricesCur == NULL)
+ {
+ matrices = &alignedGlobalPose;
+ alignedGlobalPose = mInternalGlobalPose;
+ }
+ else
+ {
+ matrices = (PxMat44*)mInternalBoneMatricesCur;
+ PX_ASSERT(matrices != NULL);
+ }
+
+ mAsset.skinToBones(renderData, submeshIndex, graphicalLod, pSubMesh->mCurrentMaxVertexSimulation, matrices, mMorphDisplacementBuffer);
+
+ submeshVertexOffset += pSubMesh->mVertexCount;
+ }
+ }
+
+ if (!fromFetchResults)
+ {
+ renderDataUnLock();
+ }
+}
+
+template<bool computeNormals>
+uint32_t ClothingAssetData::skinClothMap(PxVec3* dstPositions, PxVec3* dstNormals, PxVec4* dstTangents, uint32_t numVertices,
+ const AbstractMeshDescription& srcPM, ClothingGraphicalLodParametersNS::SkinClothMapD_Type* map,
+ uint32_t numVerticesInMap, float offsetAlongNormal, float actorScale) const
+{
+ PX_ASSERT(srcPM.numIndices % 3 == 0);
+
+ const ClothingGraphicalLodParametersNS::SkinClothMapD_Type* PX_RESTRICT pTCM = map;
+ nvidia::prefetchLine(pTCM);
+
+ const float invOffsetAlongNormal = 1.0f / offsetAlongNormal;
+
+ uint32_t numVerticesWritten = 0;
+ uint32_t numTangentsWritten = 0;
+ const uint32_t numVerticesTotal = numVertices;
+
+ uint32_t firstMiss = numVerticesInMap;
+
+ const uint32_t unrollCount = 256;
+
+ const uint32_t numIterations = (numVerticesInMap + unrollCount - 1) / unrollCount;
+
+ //uint32_t vertexIndex = 0;
+ for (uint32_t a = 0; a < numIterations; ++a)
+ {
+ const uint32_t numToProcess = PxMin(numVerticesInMap - (a * unrollCount), unrollCount);
+ const ClothingGraphicalLodParametersNS::SkinClothMapD_Type* PX_RESTRICT pTCMLocal =
+ (const ClothingGraphicalLodParametersNS::SkinClothMapD_Type * PX_RESTRICT)(void*)pTCM;
+
+ for (uint32_t j = 0; j < numToProcess; ++j)
+ {
+ nvidia::prefetchLine(pTCMLocal + 1);
+
+ //PX_ASSERT(vertexIndex == pTCMLocal->vertexIndexPlusOffset);
+ uint32_t vertexIndex = pTCMLocal->vertexIndexPlusOffset;
+ const uint32_t physVertIndex0 = pTCMLocal->vertexIndex0;
+ const uint32_t physVertIndex1 = pTCMLocal->vertexIndex1;
+ const uint32_t physVertIndex2 = pTCMLocal->vertexIndex2;
+
+ if (vertexIndex >= numVerticesTotal)
+ {
+ pTCM++;
+ pTCMLocal++;
+ //vertexIndex++;
+ continue;
+ }
+
+ // TODO do only 1 test, make sure physVertIndex0 is the smallest index
+ if (physVertIndex0 >= srcPM.numVertices || physVertIndex1 >= srcPM.numVertices || physVertIndex2 >= srcPM.numVertices)
+ {
+ firstMiss = PxMin(firstMiss, vertexIndex);
+ pTCM++;
+ pTCMLocal++;
+ //vertexIndex++;
+ continue;
+ }
+
+ numVerticesWritten++;
+
+ //PX_ASSERT(!vertexWriteCache.IsStomped());
+
+ const PxVec3 vtx[3] =
+ {
+ *(PxVec3*)&srcPM.pPosition[physVertIndex0],
+ *(PxVec3*)&srcPM.pPosition[physVertIndex1],
+ *(PxVec3*)&srcPM.pPosition[physVertIndex2],
+ };
+
+ //PX_ASSERT(!vertexWriteCache.IsStomped());
+
+ const PxVec3 nrm[3] =
+ {
+ *(PxVec3*)&srcPM.pNormal[physVertIndex0],
+ *(PxVec3*)&srcPM.pNormal[physVertIndex1],
+ *(PxVec3*)&srcPM.pNormal[physVertIndex2],
+ };
+
+ //PX_ASSERT(!vertexWriteCache.IsStomped());
+
+ PxVec3 bary = pTCMLocal->vertexBary;
+ const float vHeight = bary.z * actorScale;
+ bary.z = 1.0f - bary.x - bary.y;
+
+ const PxVec3 positionVertex = bary.x * vtx[0] + bary.y * vtx[1] + bary.z * vtx[2];
+ const PxVec3 positionNormal = (bary.x * nrm[0] + bary.y * nrm[1] + bary.z * nrm[2]) * vHeight;
+
+ const PxVec3 resultPosition = positionVertex + positionNormal;
+ //Write back - to use a DMA list
+
+ PxVec3* dstPosition = (PxVec3*)&dstPositions[vertexIndex];
+
+ *dstPosition = resultPosition;
+
+ PX_ASSERT(resultPosition.isFinite());
+
+ if (computeNormals)
+ {
+ bary = pTCMLocal->normalBary;
+ const float nHeight = bary.z * actorScale;
+ bary.z = 1.0f - bary.x - bary.y;
+
+ const PxVec3 normalVertex = bary.x * vtx[0] + bary.y * vtx[1] + bary.z * vtx[2];
+ const PxVec3 normalNormal = (bary.x * nrm[0] + bary.y * nrm[1] + bary.z * nrm[2]) * nHeight;
+
+ PxVec3* dstNormal = (PxVec3*)&dstNormals[vertexIndex];
+
+ // we multiply in invOffsetAlongNormal in order to get a newNormal that is closer to size 1,
+ // so the normalize approximation will be better
+ PxVec3 newNormal = ((normalVertex + normalNormal) - (resultPosition)) * invOffsetAlongNormal;
+#if 1
+ // PH: Normally this is accurate enough. For testing we can also use the second
+ const PxVec3 resultNormal = newNormal * nvidia::recipSqrtFast(newNormal.magnitudeSquared());
+ *dstNormal = resultNormal;
+#else
+ newNormal.normalize();
+ *dstNormal = newNormal;
+#endif
+ }
+ if (dstTangents != NULL)
+ {
+ bary = pTCMLocal->tangentBary;
+ const float nHeight = bary.z * actorScale;
+ bary.z = 1.0f - bary.x - bary.y;
+
+ const PxVec3 tangentVertex = bary.x * vtx[0] + bary.y * vtx[1] + bary.z * vtx[2];
+ const PxVec3 tangentTangent = (bary.x * nrm[0] + bary.y * nrm[1] + bary.z * nrm[2]) * nHeight;
+
+ PxVec4* dstTangent = (PxVec4*)&dstTangents[vertexIndex];
+
+ // we multiply in invOffsetAlongNormal in order to get a newNormal that is closer to size 1,
+ // so the normalize approximation will be better
+ PxVec3 newTangent = ((tangentVertex + tangentTangent) - (resultPosition)) * invOffsetAlongNormal;
+#if 1
+ // PH: Normally this is accurate enough. For testing we can also use the second
+ const PxVec3 resultTangent = newTangent * nvidia::recipSqrtFast(newTangent.magnitudeSquared());
+
+ uint32_t arrayIndex = numTangentsWritten / 4;
+ uint32_t offset = numTangentsWritten % 4;
+ float w = ((mCompressedTangentW[arrayIndex] >> offset) & 1) ? 1.f : -1.f;
+
+ *dstTangent = PxVec4(resultTangent, w);
+#else
+ newTangent.normalize();
+ *dstTangent = newTangent;
+#endif
+ }
+
+ pTCM++;
+ pTCMLocal++;
+ //vertexIndex++;
+ }
+ }
+
+ return firstMiss;
+}
+
+
+#if PX_ANDROID || PX_LINUX
+template uint32_t ClothingAssetData::skinClothMap<true>(PxVec3* dstPositions, PxVec3* dstNormals, PxVec4* dstTangents, uint32_t numVertices,
+ const AbstractMeshDescription& srcPM, ClothingGraphicalLodParametersNS::SkinClothMapD_Type* map,
+ uint32_t numVerticesInMap, float offsetAlongNormal, float actorScale) const;
+
+template uint32_t ClothingAssetData::skinClothMap<false>(PxVec3* dstPositions, PxVec3* dstNormals, PxVec4* dstTangents, uint32_t numVertices,
+ const AbstractMeshDescription& srcPM, ClothingGraphicalLodParametersNS::SkinClothMapD_Type* map,
+ uint32_t numVerticesInMap, float offsetAlongNormal, float actorScale) const;
+#endif
+
+void ClothingActorData::skinToImmediateMap(const uint32_t* immediateClothMap_, uint32_t numGraphicalVertices_, uint32_t numSrcVertices_,
+ const PxVec3* srcPositions_)
+{
+ const uint32_t* PX_RESTRICT immediateClothMap = immediateClothMap_;
+
+ const PxVec3* PX_RESTRICT srcPositions = srcPositions_;
+ PxVec3* PX_RESTRICT destPositions = mRenderingDataPosition;
+
+ const uint32_t numGraphicalVertices = numGraphicalVertices_;
+ const uint32_t numSrcVertices = numSrcVertices_;
+
+ const uint32_t WorkSize = 512;
+
+ const uint32_t numIterations = (numGraphicalVertices + WorkSize - 1) / WorkSize;
+
+ for (uint32_t a = 0; a < numIterations; ++a)
+ {
+ const uint32_t numToProcess = PxMin(numGraphicalVertices - (a * WorkSize), WorkSize);
+
+ const uint32_t* PX_RESTRICT immediateClothMapLocal = (const uint32_t * PX_RESTRICT)(void*)&immediateClothMap[a * WorkSize];
+ PxVec3* PX_RESTRICT destPositionsLocal = (PxVec3 * PX_RESTRICT)(void*)&destPositions[a * WorkSize];
+
+ for (uint32_t j = 0; j < numToProcess; ++j)
+ {
+ const uint32_t mapEntry = immediateClothMapLocal[j];
+ const uint32_t index = mapEntry & ClothingConstants::ImmediateClothingReadMask;
+ const uint32_t flags = mapEntry & ~ClothingConstants::ImmediateClothingReadMask;
+
+ if (index < numSrcVertices && ((flags & ClothingConstants::ImmediateClothingInSkinFlag)) == 0)
+ {
+ destPositionsLocal[j] = *((PxVec3*)(void*)&srcPositions[index]);
+ PX_ASSERT(destPositionsLocal[j].isFinite());
+ }
+ }
+ }
+}
+
+
+
+void ClothingActorData::skinToImmediateMap(const uint32_t* immediateClothMap_, uint32_t numGraphicalVertices_, uint32_t numSrcVertices_,
+ const PxVec3* srcPositions_, const PxVec3* srcNormals_)
+{
+ const uint32_t* PX_RESTRICT immediateClothMap = immediateClothMap_;
+
+ const PxVec3* PX_RESTRICT srcPositions = srcPositions_;
+ const PxVec3* PX_RESTRICT srcNormals = srcNormals_;
+
+ PxVec3* PX_RESTRICT destPositions = mRenderingDataPosition;
+ PxVec3* PX_RESTRICT destNormals = mRenderingDataNormal;
+
+ const uint32_t numGraphicalVertices = numGraphicalVertices_;
+ const uint32_t numSrcVertices = numSrcVertices_;
+
+ const uint32_t WorkSize = 160;
+
+ //__builtin_snpause();
+
+ const uint32_t numIterations = (numGraphicalVertices + WorkSize - 1) / WorkSize;
+
+ for (uint32_t a = 0; a < numIterations; ++a)
+ {
+ const uint32_t numToProcess = PxMin(numGraphicalVertices - (a * WorkSize), WorkSize);
+
+ const uint32_t* PX_RESTRICT immediateClothMapLocal = (const uint32_t * PX_RESTRICT)(void*)&immediateClothMap[a * WorkSize];
+ PxVec3* PX_RESTRICT destPositionsLocal = (PxVec3 * PX_RESTRICT)(void*)&destPositions[a * WorkSize];
+ PxVec3* PX_RESTRICT destNormalsLocal = (PxVec3 * PX_RESTRICT)(void*)&destNormals[a * WorkSize];
+
+ for (uint32_t j = 0; j < numToProcess; ++j)
+ {
+ const uint32_t mapEntry = immediateClothMapLocal[j];
+ const uint32_t index = mapEntry & ClothingConstants::ImmediateClothingReadMask;
+ const uint32_t flags = mapEntry & ~ClothingConstants::ImmediateClothingReadMask;
+
+ if (index < numSrcVertices && ((flags & ClothingConstants::ImmediateClothingInSkinFlag)) == 0)
+ {
+ destPositionsLocal[j] = *((PxVec3*)(void*)&srcPositions[index]);
+ PX_ASSERT(destPositionsLocal[j].isFinite());
+
+ const PxVec3 destNormal = *((PxVec3*)(void*)&srcNormals[index]);
+ destNormalsLocal[j] = (flags & ClothingConstants::ImmediateClothingInvertNormal) ? -destNormal : destNormal;
+ PX_ASSERT(destNormalsLocal[j].isFinite());
+ }
+ }
+ }
+}
+
+
+
+void ClothingActorData::skinToPhysicalMesh_NoPhysX(bool fromFetchResults)
+{
+ // This optimization only works if the render data from last frame is still there.
+ // So this can only be used if we're using the same ClothingRenderProxy again.
+ //if (!bIsSimulationMeshDirty)
+ //{
+ // return;
+ //}
+
+ PX_PROFILE_ZONE("ClothingActorImpl::meshMesh-Skinning", GetInternalApexSDK()->getContextId());
+
+ const ClothingMeshAssetData& graphicalLod = *mAsset.GetLod(mCurrentGraphicalLodId);
+
+ const ClothingPhysicalMeshData* physicalMesh = mAsset.GetPhysicalMeshFromLod(mCurrentGraphicalLodId);
+
+ AbstractMeshDescription pcm;
+ pcm.numVertices = mSdkDeformableVerticesCount;
+ pcm.numIndices = mSdkDeformableIndicesCount;
+ pcm.pPosition = mSdkWritebackPositions;
+ pcm.pNormal = mSdkWritebackNormal;
+ pcm.pIndices = physicalMesh->mIndices;
+ pcm.avgEdgeLength = graphicalLod.mSkinClothMapThickness;
+
+ const bool skinNormals = !bRecomputeNormals;
+
+ if (!fromFetchResults)
+ {
+ renderDataLock();
+ }
+
+ uint32_t activeCount = 0;
+
+ for (uint32_t i = 0; i < mAsset.mGraphicalLodsCount; i++)
+ {
+ const ClothingMeshAssetData& lod = *mAsset.GetLod(i);
+ if (!lod.bActive)
+ {
+ continue;
+ }
+ activeCount++;
+
+ bool skinTangents = !bRecomputeTangents;
+
+ uint32_t graphicalVerticesCount = 0;
+ for (uint32_t j = 0; j < lod.mSubMeshCount; j++)
+ {
+ ClothingAssetSubMesh* subMesh = mAsset.GetSubmesh(&lod, j);
+ graphicalVerticesCount += subMesh->mVertexCount; // only 1 part is supported
+
+ if (subMesh->mTangents == NULL)
+ {
+ skinTangents = false;
+ }
+ }
+
+ //__builtin_snpause();
+ //RenderMeshAssetIntl* renderMeshAsset = mAsset->getGraphicalMesh(i);
+ //PX_ASSERT(renderMeshAsset != NULL);
+
+ // Do mesh-to-mesh skinning here
+ if (graphicalLod.mSkinClothMapB != NULL)
+ {
+ mAsset.skinClothMapB(mRenderingDataPosition, mRenderingDataNormal, graphicalVerticesCount, pcm,
+ graphicalLod.mSkinClothMapB, graphicalLod.mSkinClothMapBCount, skinNormals);
+ }
+ else if (graphicalLod.mSkinClothMap != NULL)
+ {
+ PxVec4* tangents = skinTangents ? mRenderingDataTangent : NULL;
+ if (skinNormals)
+ mAsset.skinClothMap<true>(mRenderingDataPosition, mRenderingDataNormal, tangents, graphicalVerticesCount, pcm,
+ graphicalLod.mSkinClothMap, graphicalLod.mSkinClothMapCount, graphicalLod.mSkinClothMapOffset, mActorScale);
+ else
+ mAsset.skinClothMap<false>(mRenderingDataPosition, mRenderingDataNormal, tangents, graphicalVerticesCount, pcm,
+ graphicalLod.mSkinClothMap, graphicalLod.mSkinClothMapCount, graphicalLod.mSkinClothMapOffset, mActorScale);
+
+ }
+ else if (graphicalLod.mTetraMap != NULL)
+ {
+ AbstractMeshDescription destMesh;
+ destMesh.pPosition = mRenderingDataPosition;
+ if (skinNormals)
+ {
+ destMesh.pNormal = mRenderingDataNormal;
+ }
+ destMesh.numVertices = graphicalVerticesCount;
+ mAsset.skinToTetraMesh(destMesh, pcm, graphicalLod);
+ }
+
+ if (graphicalLod.mImmediateClothMap != NULL)
+ {
+ if (skinNormals)
+ {
+ skinToImmediateMap(graphicalLod.mImmediateClothMap, graphicalVerticesCount, pcm.numVertices, pcm.pPosition, pcm.pNormal);
+ }
+ else
+ {
+ skinToImmediateMap(graphicalLod.mImmediateClothMap, graphicalVerticesCount, pcm.numVertices, pcm.pPosition);
+ }
+ }
+ }
+
+ PX_ASSERT(activeCount < 2);
+
+ if (!fromFetchResults)
+ {
+ renderDataUnLock();
+ }
+}
+
+
+
+
+
+
+void ClothingActorData::finalizeSkinning_NoPhysX(bool fromFetchResults)
+{
+ // PH: If fromFetchResults is true, renderLock does not need to be aquired as it is already aquired by ApexScene::fetchResults()
+ if (!fromFetchResults)
+ {
+ renderDataLock();
+ }
+
+ mNewBounds.setEmpty();
+
+ for (uint32_t graphicalLod = 0; graphicalLod < mAsset.mGraphicalLodsCount; graphicalLod++)
+ {
+ ClothingMeshAssetData& renderMeshAsset = *mAsset.GetLod(graphicalLod);
+ if (!renderMeshAsset.bActive)
+ {
+ continue;
+ }
+
+ const uint32_t submeshCount = renderMeshAsset.mSubMeshCount;
+
+ uint32_t submeshVertexOffset = 0;
+ for (uint32_t submeshIndex = 0; submeshIndex < submeshCount; submeshIndex++)
+ {
+ AbstractMeshDescription renderData;
+
+ ClothingAssetSubMesh* pSubmesh = mAsset.GetSubmesh(&renderMeshAsset, submeshIndex);
+
+ renderData.numVertices = pSubmesh->mVertexCount;
+
+ renderData.pPosition = mRenderingDataPosition + submeshVertexOffset;
+
+ bool recomputeTangents = bRecomputeTangents && renderMeshAsset.bNeedsTangents;
+ if (bRecomputeNormals || recomputeTangents)
+ {
+ renderData.pNormal = mRenderingDataNormal + submeshVertexOffset;
+
+ const uint32_t* compressedTangentW = NULL;
+
+ if (recomputeTangents)
+ {
+ renderData.pTangent4 = mRenderingDataTangent + submeshVertexOffset;
+ uint32_t mapSize = 0;
+ compressedTangentW = mAsset.getCompressedTangentW(graphicalLod, submeshIndex, mapSize);
+ }
+ if (bRecomputeNormals && recomputeTangents)
+ {
+ PX_PROFILE_ZONE("ClothingActorImpl::recomupteNormalAndTangent", GetInternalApexSDK()->getContextId());
+ computeTangentSpaceUpdate<true, true>(renderData, renderMeshAsset, submeshIndex, compressedTangentW);
+ }
+ else if (bRecomputeNormals)
+ {
+ PX_PROFILE_ZONE("ClothingActorImpl::recomupteNormal", GetInternalApexSDK()->getContextId());
+ computeTangentSpaceUpdate<true, false>(renderData, renderMeshAsset, submeshIndex, compressedTangentW);
+ }
+ else
+ {
+ PX_PROFILE_ZONE("ClothingActorImpl::recomupteTangent", GetInternalApexSDK()->getContextId());
+ computeTangentSpaceUpdate<false, true>(renderData, renderMeshAsset, submeshIndex, compressedTangentW);
+ }
+ }
+
+ const uint32_t unrollCount = 1024;
+ const uint32_t numIterations = (renderData.numVertices + unrollCount - 1) / unrollCount;
+
+ for (uint32_t a = 0; a < numIterations; ++a)
+ {
+ const uint32_t numToProcess = PxMin(unrollCount, renderData.numVertices - (a * unrollCount));
+ const PxVec3* PX_RESTRICT positions = (const PxVec3 * PX_RESTRICT)(renderData.pPosition + (a * unrollCount));
+ for (uint32_t b = 0; b < numToProcess; ++b)
+ {
+ mNewBounds.include(positions[b]);
+ }
+ }
+
+ submeshVertexOffset += renderData.numVertices;
+ }
+ }
+
+ if (!fromFetchResults)
+ {
+ renderDataUnLock();
+ }
+}
+
+#define FLOAT_TANGENT_UPDATE 0
+
+
+template <bool withNormals, bool withTangents>
+void ClothingActorData::computeTangentSpaceUpdate(AbstractMeshDescription& destMesh,
+ const ClothingMeshAssetData& rendermesh, uint32_t submeshIndex, const uint32_t* compressedTangentW)
+{
+ //__builtin_snpause();
+ ClothingAssetSubMesh* pSubMesh = mAsset.GetSubmesh(&rendermesh, submeshIndex);
+
+ if (withNormals && withTangents)
+ {
+ computeTangentSpaceUpdate<true, false>(destMesh, rendermesh, submeshIndex, compressedTangentW);
+ computeTangentSpaceUpdate<false, true>(destMesh, rendermesh, submeshIndex, compressedTangentW);
+ }
+ else
+ {
+ const RenderDataFormat::Enum uvFormat = pSubMesh->mUvFormat;
+
+ if (uvFormat != RenderDataFormat::FLOAT2)
+ {
+ if (withNormals)
+ {
+ computeTangentSpaceUpdate<true, false>(destMesh, rendermesh, submeshIndex, compressedTangentW);
+ }
+
+ return;
+ }
+
+ PX_ASSERT(pSubMesh->mCurrentMaxIndexSimulation <= pSubMesh->mIndicesCount);
+ const uint32_t numGraphicalVertexIndices = pSubMesh->mCurrentMaxIndexSimulation;
+ const uint32_t* indices = pSubMesh->mIndices;
+
+ const VertexUVLocal* PX_RESTRICT uvs = pSubMesh->mUvs;
+ PX_ASSERT(uvs != NULL);
+
+ const uint32_t numVertices = pSubMesh->mCurrentMaxVertexAdditionalSimulation;
+ const uint32_t numZeroVertices = pSubMesh->mCurrentMaxVertexSimulation;
+ PX_ASSERT(numVertices <= destMesh.numVertices);
+
+ PX_ASSERT(pSubMesh->mVertexCount == destMesh.numVertices);
+ PX_ASSERT(destMesh.pPosition != NULL);
+ PX_ASSERT(destMesh.pNormal != NULL);
+ PX_ASSERT(destMesh.pTangent4 != NULL || !withTangents);
+ PX_ASSERT(destMesh.pTangent == NULL);
+ PX_ASSERT(destMesh.pBitangent == NULL);
+
+ const Simd4f vZero = gSimd4fZero;
+
+ //All indices read in in blocks of 3...hence need to fetch in an exact multiple of 3...
+
+ const uint32_t UnrollSize = 192; //exactly divisible by 16 AND 3 :-)
+
+ const uint32_t numIterations = (numGraphicalVertexIndices + UnrollSize - 1) / UnrollSize;
+
+ const PxVec3* PX_RESTRICT destPositions = (const PxVec3 * PX_RESTRICT)(destMesh.pPosition);
+
+ if (withNormals)
+ {
+ //__builtin_snpause();
+ PxVec3* PX_RESTRICT destNormals = destMesh.pNormal;
+ for (uint32_t a = 0; a < numZeroVertices; ++a)
+ {
+ destNormals[a] = PxVec3(0.0f);
+ }
+
+ for (uint32_t a = 0; a < numIterations; ++a)
+ {
+ //__builtin_snpause();
+ const uint32_t numToProcess = PxMin(numGraphicalVertexIndices - (a * UnrollSize), UnrollSize);
+ const uint32_t* localIndices = (const uint32_t*)((void*)(indices + (a * UnrollSize)));
+
+ for (uint32_t i = 0; i < numToProcess; i += 3)
+ {
+ const uint32_t i0 = localIndices[i + 0];
+ const uint32_t i1 = localIndices[i + 1];
+ const uint32_t i2 = localIndices[i + 2];
+
+ const Simd4f P0 = createSimd3f(destPositions[i0]);
+ const Simd4f P1 = createSimd3f(destPositions[i1]);
+ const Simd4f P2 = createSimd3f(destPositions[i2]);
+
+ const Simd4f X1 = P1 - P0;
+ const Simd4f X2 = P2 - P0;
+
+ Simd4f FACENORMAL = cross3(X1, X2);
+
+ PxVec3* PX_RESTRICT nor1 = &destNormals[i0];
+ Simd4f n1 = createSimd3f(*nor1);
+ n1 = n1 + FACENORMAL;
+ store3(&nor1->x, n1);
+
+ PxVec3* PX_RESTRICT nor2 = &destNormals[i1];
+ Simd4f n2 = createSimd3f(*nor2);
+ n2 = n2 + FACENORMAL;
+ store3(&nor2->x, n2);
+
+ PxVec3* PX_RESTRICT nor3 = &destNormals[i2];
+ Simd4f n3 = createSimd3f(*nor3);
+ n3 = n3 + FACENORMAL;
+ store3(&nor3->x, n3);
+
+ }
+ }
+ }
+ if (withTangents)
+ {
+ const VertexUVLocal* PX_RESTRICT uvLocal = (const VertexUVLocal * PX_RESTRICT)(void*)uvs;
+
+ PxVec4* PX_RESTRICT tangents = destMesh.pTangent4;
+ for (uint32_t a = 0; a < numZeroVertices; ++a)
+ {
+ tangents[a] = PxVec4(0.f);
+ }
+
+
+ for (uint32_t a = 0; a < numIterations; ++a)
+ {
+ //__builtin_snpause();
+ const uint32_t numToProcess = PxMin(numGraphicalVertexIndices - (a * UnrollSize), UnrollSize);
+ const uint32_t* localIndices = (const uint32_t*)(void*)(indices + (a * UnrollSize));
+
+ for (uint32_t i = 0; i < numToProcess; i += 3)
+ {
+ const uint32_t i0 = localIndices[i + 0];
+ const uint32_t i1 = localIndices[i + 1];
+ const uint32_t i2 = localIndices[i + 2];
+
+ const Simd4f P0 = createSimd3f(destPositions[i0]);
+ const Simd4f P1 = createSimd3f(destPositions[i1]);
+ const Simd4f P2 = createSimd3f(destPositions[i2]);
+
+ const Simd4f X1 = P1 - P0;
+ const Simd4f X2 = P2 - P0;
+
+ const VertexUVLocal& w0 = uvLocal[i0];
+ const VertexUVLocal& w1 = uvLocal[i1];
+ const VertexUVLocal& w2 = uvLocal[i2];
+
+ const Simd4f W0U = Simd4fScalarFactory(w0.u);
+ const Simd4f W1U = Simd4fScalarFactory(w1.u);
+ const Simd4f W2U = Simd4fScalarFactory(w2.u);
+ const Simd4f W0V = Simd4fScalarFactory(w0.v);
+ const Simd4f W1V = Simd4fScalarFactory(w1.v);
+ const Simd4f W2V = Simd4fScalarFactory(w2.v);
+
+ //This could be just 1 sub...
+
+ const Simd4f S1 = W1U - W0U;
+ const Simd4f S2 = W2U - W0U;
+ const Simd4f T1 = W1V - W0V;
+ const Simd4f T2 = W2V - W0V;
+
+ // invH = (s1 * t2 - s2 * t1);
+ const Simd4f S1T2 = S1 * T2;
+ const Simd4f invHR = S1T2 - S2 * T1;
+ const Simd4f HR = recip(invHR);
+ const Simd4f T2X1 = X1 * T2;
+ //const Vec3V S1X2 = V3Scale(X2, S1);
+ const Simd4f invHREqZero = (invHR == vZero);
+
+ const Simd4f T1X2MT2X1 = T2X1 - X2 * T1;
+ //const Simd4f S2X1MS1X2 = S1X2 - X1 * X2;
+
+ const Simd4f scale = select(invHREqZero, vZero, HR);
+
+ const Simd4f SDIR = T1X2MT2X1 * scale; // .w gets overwritten later on
+ //const Simd4f TDIR = S2X1MS1X2 * scale;
+
+ PxVec4* PX_RESTRICT tangent0 = tangents + i0;
+ PxVec4* PX_RESTRICT tangent1 = tangents + i1;
+ PxVec4* PX_RESTRICT tangent2 = tangents + i2;
+ Simd4f t0 = Simd4fAlignedLoadFactory((float*)tangent0);
+ Simd4f t1 = Simd4fAlignedLoadFactory((float*)tangent1);
+ Simd4f t2 = Simd4fAlignedLoadFactory((float*)tangent2);
+
+ t0 = t0 + SDIR;
+ t1 = t1 + SDIR;
+ t2 = t2 + SDIR;
+
+ storeAligned((float*)tangent0, t0);
+ storeAligned((float*)tangent1, t1);
+ storeAligned((float*)tangent2, t2);
+ }
+ }
+
+ uint32_t tangentW = 0;
+
+ int32_t j = 0;
+#if 1
+ // This makes it quite a bit faster, but it also works without it.
+ for (; j < (int32_t)numVertices - 4; j += 4)
+ {
+ if ((j & 0x1f) == 0)
+ {
+ tangentW = compressedTangentW[j >> 5];
+ }
+
+ tangents[j].w = (tangentW & 0x1) ? 1.0f : -1.0f;
+ tangents[j + 1].w = (tangentW & 0x2) ? 1.0f : -1.0f;
+ tangents[j + 2].w = (tangentW & 0x4) ? 1.0f : -1.0f;
+ tangents[j + 3].w = (tangentW & 0x8) ? 1.0f : -1.0f;
+ tangentW >>= 4;
+ }
+#endif
+
+ // We need this loop to handle last vertices in tangents[], it shares the same j as previous loop
+ for (; j < (int32_t)numVertices; j++)
+ {
+ if ((j & 0x1f) == 0)
+ {
+ tangentW = compressedTangentW[j >> 5];
+ }
+
+ tangents[j].w = (tangentW & 0x1) ? 1.0f : -1.0f;
+ tangentW >>= 1;
+ }
+ }
+ }
+}
+
+
+PxBounds3 ClothingActorData::getRenderMeshAssetBoundsTransformed()
+{
+ PxBounds3 newBounds = mAsset.GetLod(mCurrentGraphicalLodId)->mBounds;
+
+ PxMat44 transformation;
+ if (mInternalBoneMatricesCur != NULL)
+ {
+ transformation = mInternalBoneMatricesCur[mAsset.mRootBoneIndex];
+ }
+ else
+ {
+ //transformation = mActorDesc->globalPose;
+ transformation = mGlobalPose;
+ }
+
+ if (!newBounds.isEmpty())
+ {
+ PxVec3 center = transformation.transform(newBounds.getCenter());
+ PxVec3 extent = newBounds.getExtents();
+
+ // extended basis vectors
+ PxVec3 c0 = transformation.column0.getXYZ() * extent.x;
+ PxVec3 c1 = transformation.column1.getXYZ() * extent.y;
+ PxVec3 c2 = transformation.column2.getXYZ() * extent.z;
+
+ // find combination of base vectors that produces max. distance for each component = sum of PxAbs()
+ extent.x = PxAbs(c0.x) + PxAbs(c1.x) + PxAbs(c2.x);
+ extent.y = PxAbs(c0.y) + PxAbs(c1.y) + PxAbs(c2.y);
+ extent.z = PxAbs(c0.z) + PxAbs(c1.z) + PxAbs(c2.z);
+
+ return PxBounds3::centerExtents(center, extent);
+ }
+ else
+ {
+ return newBounds;
+ }
+}
+
+
+void ClothingActorData::tickSynchAfterFetchResults_LocksPhysX()
+{
+ if (bIsInitialized && !bIsClothingSimulationNull && bShouldComputeRenderData /*&& !bInternalFrozen*/)
+ {
+ // overwrite a few writeback normals!
+
+ if (bCorrectSimulationNormals)
+ {
+ skinPhysicsMaxDist0Normals_NoPhysx();
+ }
+
+ //// perform mesh-to-mesh skinning if using skin cloth
+
+ if (!bParallelCpuSkinning)
+ {
+ skinToAnimation_NoPhysX(true);
+ }
+
+ skinToPhysicalMesh_NoPhysX(true);
+
+ finalizeSkinning_NoPhysX(true);
+
+ PX_ASSERT(!mNewBounds.isEmpty());
+ PX_ASSERT(mNewBounds.isFinite());
+ }
+}
+
+
+bool ClothingActorData::calcIfSimplePhysicsMesh() const
+{
+ // this number is the blocksize in SPU_ClothSkinPhysicsSimple.spu.cpp
+ return skinPhysicsSimpleMem() < BLOCK_SIZE_SKIN_PHYSICS;
+
+ // with
+ // BLOCK_SIZE_SKIN_PHYSICS (32768*6)
+ // 100 bones
+ // 4 bone indices per vertex
+ // => simple mesh is vertexCount < 3336
+}
+
+
+uint32_t ClothingActorData::skinPhysicsSimpleMem() const
+{
+ PX_ASSERT(bIsInitialized);
+
+ const ClothingPhysicalMeshData* physicalMesh = mAsset.GetPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ PX_ASSERT(physicalMesh != NULL);
+
+ const uint32_t numVertices = physicalMesh->mSimulatedVertexCount;
+ const uint32_t numBoneIndicesPerVertex = physicalMesh->mNumBonesPerVertex;
+
+ uint32_t srcPositionMem = numVertices * sizeof(PxVec3);
+ uint32_t srcNormalMem = numVertices * sizeof(PxVec3);
+
+ uint32_t simBoneIndicesMem = numBoneIndicesPerVertex * numVertices * sizeof(uint16_t);
+ uint32_t simBoneWeightsMem = numBoneIndicesPerVertex * numVertices * sizeof(float);
+
+ uint32_t matricesMem = mInternalMatricesCount * sizeof(PxMat44);
+
+ uint32_t optimizationDataMem = physicalMesh->mOptimizationDataCount * sizeof(uint8_t); // mOptimizationDataCount ~ numVertices
+
+ uint32_t mem = srcPositionMem + srcNormalMem + simBoneIndicesMem + simBoneWeightsMem + matricesMem + optimizationDataMem;
+ // numVertices * (33 + (6*numBonesPerVert)) + 64*numBones
+
+ return mem;
+}
+
+
+void ClothingActorData::skinPhysicsMeshSimple()
+{
+ if (!bIsInitialized)
+ {
+ return;
+ }
+
+ // with bones, no interpolated matrices, no backstop?
+
+ // data
+ const ClothingPhysicalMeshData* physicalMesh = mAsset.GetPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ PX_ASSERT(physicalMesh != NULL);
+
+ const uint32_t numVertices = physicalMesh->mSimulatedVertexCount;
+ const uint32_t numBoneIndicesPerVertex = physicalMesh->mNumBonesPerVertex;
+
+ PxVec3* const PX_RESTRICT eaPositions = physicalMesh->mVertices;
+ PxVec3* const PX_RESTRICT positions = (PxVec3*)eaPositions;
+
+ PxVec3* const PX_RESTRICT eaNormals = physicalMesh->mNormals;
+ PxVec3* const PX_RESTRICT normals = (PxVec3*)eaNormals;
+
+ PxVec3* const PX_RESTRICT targetPositions = mSkinnedPhysicsPositions;
+ PxVec3* const PX_RESTRICT targetNormals = mSkinnedPhysicsNormals;
+
+ uint16_t* const PX_RESTRICT eaSimBoneIndices = physicalMesh->mBoneIndices;
+ const uint16_t* const PX_RESTRICT simBoneIndices = (uint16_t*)eaSimBoneIndices;
+
+ float* const PX_RESTRICT eaSimBoneWeights = physicalMesh->mBoneWeights;
+ const float* const PX_RESTRICT simBoneWeights = (float*)eaSimBoneWeights;
+
+ PxMat44* eaMatrices = mInternalBoneMatricesCur; // TODO interpolated matrices?
+ const PxMat44* matrices = (PxMat44*)eaMatrices;
+
+ uint8_t* const PX_RESTRICT eaOptimizationData = physicalMesh->mOptimizationData;
+ const uint8_t* const PX_RESTRICT optimizationData = (uint8_t*)eaOptimizationData;
+
+ PX_ASSERT(optimizationData != NULL);
+
+ for (uint32_t vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
+ {
+ Simd4f positionV = gSimd4fZero;
+ Simd4f normalV = gSimd4fZero;
+
+ const uint8_t shift = 4 * (vertexIndex % 2);
+ const uint8_t numBones = uint8_t((optimizationData[vertexIndex / 2] >> shift) & 0x7);
+ for (uint32_t k = 0; k < numBones; k++)
+ {
+ const float weight = simBoneWeights[vertexIndex * numBoneIndicesPerVertex + k];
+
+ PX_ASSERT(weight <= 1.0f);
+
+ //sumWeights += weight;
+ Simd4f weightV = Simd4fScalarFactory(weight);
+
+ const uint32_t index = simBoneIndices[vertexIndex * numBoneIndicesPerVertex + k];
+ PX_ASSERT(index < mInternalMatricesCount);
+
+ /// PH: This might be faster without the reference, but on PC I can't tell
+ /// HL: Now with SIMD it's significantly faster as reference
+ const PxMat44& bone = (PxMat44&)matrices[index];
+
+ Simd4f pV = applyAffineTransform(bone, createSimd3f(positions[vertexIndex]));
+ pV = pV * weightV;
+ positionV = positionV + pV;
+
+ ///todo There are probably cases where we don't need the normal on the physics mesh
+ Simd4f nV = applyLinearTransform(bone, createSimd3f(normals[vertexIndex]));
+ nV = nV * weightV;
+ normalV = normalV + nV;
+ }
+
+ normalV = normalizeSimd3f(normalV);
+ store3(&targetNormals[vertexIndex].x, normalV);
+ store3(&targetPositions[vertexIndex].x, positionV);
+ }
+}
+
+
+}
+} // namespace nvidia
diff --git a/APEX_1.4/module/clothing/src/ClothingActorImpl.cpp b/APEX_1.4/module/clothing/src/ClothingActorImpl.cpp
new file mode 100644
index 00000000..06956ddd
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/ClothingActorImpl.cpp
@@ -0,0 +1,4852 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+#include "ApexSimdMath.h"
+#include "ApexDefs.h"
+
+#include "PsIntrinsics.h"
+
+#include "ClothingActorImpl.h"
+#include "ClothingActorProxy.h"
+#include "ClothingCooking.h"
+#include "ClothingPhysicalMesh.h"
+#include "ClothingPreviewProxy.h"
+#include "ClothingScene.h"
+#include "CookingPhysX.h"
+#include "ModuleClothing.h"
+#include "ModulePerfScope.h"
+#include "ClothingVelocityCallback.h"
+#include "RenderMeshActorDesc.h"
+#include "SimulationAbstract.h"
+
+#include "ClothingGraphicalLodParameters.h"
+#include "DebugRenderParams.h"
+
+#include "SceneIntl.h"
+#include "ApexSDKIntl.h"
+#include "ApexUsingNamespace.h"
+#include "PsAtomic.h"
+
+#include "ApexMath.h"
+
+#if PX_PHYSICS_VERSION_MAJOR == 3
+#include "PxScene.h"
+//#include "ApexReadWriteLock.h"
+#endif
+
+#include "PsVecMath.h"
+
+#include "PxStrideIterator.h"
+
+#include "Simulation.h"
+
+#include "ApexPvdClient.h"
+
+namespace nvidia
+{
+namespace clothing
+{
+
+ClothingActorImpl::ClothingActorImpl(const NvParameterized::Interface& descriptor, ClothingActorProxy* actorProxy,
+ ClothingPreviewProxy* previewProxy, ClothingAssetImpl* asset, ClothingScene* scene) :
+ mActorProxy(actorProxy),
+ mPreviewProxy(previewProxy),
+ mAsset(asset),
+ mClothingScene(scene),
+#if PX_PHYSICS_VERSION_MAJOR == 3
+ mPhysXScene(NULL),
+#endif
+ mActorDesc(NULL),
+ mBackendName(NULL),
+ mInternalGlobalPose(PxVec4(1.0f)),
+ mOldInternalGlobalPose(PxVec4(0.0f)),
+ mInternalInterpolatedGlobalPose(PxVec4(1.0f)),
+ mInternalInterpolatedBoneMatrices(NULL),
+ mCurrentSolverIterations(0),
+ mInternalScaledGravity(0.0f, 0.0f, 0.0f),
+ mInternalMaxDistanceBlendTime(0.0f),
+ mMaxDistReduction(0.0f),
+ mBufferedGraphicalLod(0),
+ mCurrentGraphicalLodId(0),
+ mRenderProxyReady(NULL),
+ mRenderProxyURR(NULL),
+ mClothingSimulation(NULL),
+ mCurrentMaxDistanceBias(0.0f),
+ bIsSimulationOn(false),
+ mForceSimulation(-1),
+ mLodCentroid(0.0f, 0.0f, 0.0f),
+ mLodRadiusSquared(0.0f),
+ mVelocityCallback(NULL),
+ mInterCollisionChannels(0),
+ mIsAllowedHalfPrecisionSolver(false),
+ mBeforeTickTask(this),
+ mDuringTickTask(this),
+ mFetchResultsTask(this),
+ mActiveCookingTask(NULL),
+ mFetchResultsRunning(false),
+ bGlobalPoseChanged(1),
+ bBoneMatricesChanged(1),
+ bBoneBufferDirty(0),
+ bMaxDistanceScaleChanged(0),
+ bBlendingAllowed(1),
+ bDirtyActorTemplate(0),
+ bDirtyShapeTemplate(0),
+ bDirtyClothingTemplate(0),
+ bBufferedVisible(1),
+ bInternalVisible(1),
+ bUpdateFrozenFlag(0),
+ bBufferedFrozen(0),
+ bInternalFrozen(0),
+ bPressureWarning(0),
+ bUnsucessfullCreation(0),
+ bInternalTeleportDue(ClothingTeleportMode::Continuous),
+ bInternalScaledGravityChanged(1),
+ bReinitActorData(0),
+ bInternalLocalSpaceSim(0),
+ bActorCollisionChanged(0)
+{
+ //mBufferedBoneMatrices = NULL;
+
+ if ((((size_t)this) & 0xf) != 0)
+ {
+ APEX_INTERNAL_ERROR("ClothingActorImpl is not 16 byte aligned");
+ }
+ // make sure the alignment is ok
+ if ((((size_t)&mInternalGlobalPose) & 0xf) != 0)
+ {
+ APEX_INTERNAL_ERROR("Matrix ClothingActorImpl::mInternalGlobalPose is not 16 byte aligned");
+ }
+ if ((((size_t)&mOldInternalGlobalPose) & 0xf) != 0)
+ {
+ APEX_INTERNAL_ERROR("Matrix ClothingActorImpl::mOldInternalGlobalPose is not 16 byte aligned");
+ }
+ if ((((size_t)&mInternalInterpolatedGlobalPose) & 0xf) != 0)
+ {
+ APEX_INTERNAL_ERROR("Matrix ClothingActorImpl::mInternalInterpolatedGlobalPose is not 16 byte aligned");
+ }
+
+ if (::strcmp(descriptor.className(), ClothingActorParam::staticClassName()) == 0)
+ {
+ PX_ASSERT(mActorProxy != NULL);
+
+ mActorDesc = static_cast<ClothingActorParam*>(GetInternalApexSDK()->getParameterizedTraits()->createNvParameterized(ClothingActorParam::staticClassName()));
+ PX_ASSERT(mActorDesc != NULL);
+ mActorDesc->copy(descriptor);
+ PX_ASSERT(mActorDesc->equals(descriptor, NULL, 0));
+
+ const ClothingActorParamNS::ParametersStruct& actorDesc = static_cast<const ClothingActorParamNS::ParametersStruct&>(*mActorDesc);
+
+ // initialize these too
+ mInternalWindParams = mActorDesc->windParams;
+ mInternalMaxDistanceScale = mActorDesc->maxDistanceScale;
+ mInternalFlags = mActorDesc->flags;
+ bInternalLocalSpaceSim = mActorDesc->localSpaceSim ? 1u : 0u;
+
+ mInterCollisionChannels = mAsset->getInterCollisionChannels();
+
+ // Physics is turned off initially
+ mCurrentSolverIterations = 0;
+
+ if (actorDesc.slowStart)
+ {
+ mMaxDistReduction = mAsset->getBiggestMaxDistance();
+ }
+
+
+ mNewBounds.setEmpty();
+
+ // prepare some runtime data for each graphical mesh
+ mGraphicalMeshes.reserve(mAsset->getNumGraphicalMeshes());
+ uint32_t vertexOffset = 0;
+ for (uint32_t i = 0; i < mAsset->getNumGraphicalMeshes(); i++)
+ {
+ ClothingGraphicalMeshActor actor;
+
+ RenderMeshAssetIntl* renderMeshAsset = mAsset->getGraphicalMesh(i);
+ // it can be NULL if ClothingAsset::releaseGraphicalData has beend called to do skinning externally
+ if (renderMeshAsset != NULL)
+ {
+ const uint32_t numSubmeshes = renderMeshAsset->getSubmeshCount();
+
+ for (uint32_t si = 0; si < numSubmeshes; ++si)
+ {
+ actor.morphTargetVertexOffsets.pushBack(vertexOffset);
+ vertexOffset += renderMeshAsset->getSubmesh(si).getVertexCount(0);
+ }
+ }
+ else
+ {
+ actor.morphTargetVertexOffsets.pushBack(0);
+ }
+
+ actor.active = i == 0;
+ mGraphicalMeshes.pushBack(actor);
+ }
+
+ // When we add ourselves to the ApexScene, it will call us back with setPhysXScene
+ addSelfToContext(*mClothingScene->mApexScene->getApexContext());
+
+ // Add ourself to our ClothingScene
+ addSelfToContext(*static_cast<ApexContext*>(mClothingScene));
+
+ // make sure the clothing material gets initialized when
+ // applyClothingMaterial is called the first time
+ mClothingMaterial.solverIterations = uint32_t(-1);
+
+ if (::strcmp(mActorDesc->simulationBackend, "Default") == 0)
+ {
+ mBackendName = "Embedded";
+ }
+ else if (::strcmp(mActorDesc->simulationBackend, "ForceEmbedded") == 0)
+ {
+ mBackendName = "Embedded";
+ }
+ else
+ {
+ mBackendName = "Native";
+ }
+
+ if (mActorDesc->morphDisplacements.arraySizes[0] > 0)
+ {
+ PX_PROFILE_ZONE("ClothingActorImpl::morphTarget", GetInternalApexSDK()->getContextId());
+
+ if (mActorDesc->morphPhysicalMeshNewPositions.buf == NULL)
+ {
+ ParamArray<PxVec3> morphPhysicalNewPos(mActorDesc, "morphPhysicalMeshNewPositions", reinterpret_cast<ParamDynamicArrayStruct*>(&mActorDesc->morphPhysicalMeshNewPositions));
+ mAsset->getDisplacedPhysicalMeshPositions(mActorDesc->morphDisplacements.buf, morphPhysicalNewPos);
+
+ CookingAbstract* cookingJob = mAsset->getModuleClothing()->getBackendFactory(mBackendName)->createCookingJob();
+ PX_ASSERT(cookingJob != NULL);
+
+ if (cookingJob != NULL)
+ {
+ PxVec3 gravity = scene->mApexScene->getGravity();
+ gravity = mActorDesc->globalPose.inverseRT().rotate(gravity);
+ mAsset->prepareCookingJob(*cookingJob, mActorDesc->actorScale, &gravity, morphPhysicalNewPos.begin());
+
+ if (cookingJob->isValid())
+ {
+ if (mAsset->getModuleClothing()->allowAsyncCooking())
+ {
+ mActiveCookingTask = PX_NEW(ClothingCookingTask)(mClothingScene, *cookingJob);
+ mActiveCookingTask->lockObject(mAsset);
+ mClothingScene->submitCookingTask(mActiveCookingTask);
+ }
+ else
+ {
+ mActorDesc->runtimeCooked = cookingJob->execute();
+ PX_DELETE_AND_RESET(cookingJob);
+ }
+ }
+ else
+ {
+ PX_DELETE_AND_RESET(cookingJob);
+ }
+ }
+ }
+
+ if (mActorDesc->morphGraphicalMeshNewPositions.buf == NULL)
+ {
+ ParamArray<PxVec3> morphGraphicalNewPos(mActorDesc, "morphGraphicalMeshNewPositions", reinterpret_cast<ParamDynamicArrayStruct*>(&mActorDesc->morphGraphicalMeshNewPositions));
+
+ uint32_t graphicalVertexCount = 0;
+ for (uint32_t gi = 0; gi < mGraphicalMeshes.size(); ++gi)
+ {
+ RenderMeshAssetIntl* renderMeshAsset = mAsset->getGraphicalMesh(gi);
+
+ const ClothingGraphicalMeshAssetWrapper meshAsset(renderMeshAsset);
+ graphicalVertexCount += meshAsset.getNumTotalVertices();
+ }
+
+ morphGraphicalNewPos.resize(graphicalVertexCount);
+
+ uint32_t vertexOffset = 0;
+ for (uint32_t gi = 0; gi < mGraphicalMeshes.size(); ++gi)
+ {
+ RenderMeshAssetIntl* renderMeshAsset = mAsset->getGraphicalMesh(gi);
+ if (renderMeshAsset == NULL)
+ continue;
+
+ const uint32_t numSubmeshes = renderMeshAsset->getSubmeshCount();
+ for (uint32_t si = 0; si < numSubmeshes; ++si)
+ {
+ const RenderSubmesh& submesh = renderMeshAsset->getSubmesh(si);
+ const VertexFormat& format = submesh.getVertexBuffer().getFormat();
+
+ uint32_t* morphMapping = mAsset->getMorphMapping(gi, si);
+
+ const int32_t positionIndex = format.getBufferIndexFromID(format.getSemanticID(RenderVertexSemantic::POSITION));
+ if (positionIndex != -1)
+ {
+ RenderDataFormat::Enum bufferFormat = RenderDataFormat::UNSPECIFIED;
+ const PxVec3* positions = reinterpret_cast<const PxVec3*>(submesh.getVertexBuffer().getBufferAndFormat(bufferFormat, (uint32_t)positionIndex));
+ PX_ASSERT(bufferFormat == RenderDataFormat::FLOAT3);
+ if (bufferFormat == RenderDataFormat::FLOAT3)
+ {
+ const uint32_t vertexCount = submesh.getVertexCount(0);
+ for (uint32_t i = 0; i < vertexCount; i++)
+ {
+ const PxVec3 disp = morphMapping != NULL ? mActorDesc->morphDisplacements.buf[morphMapping[i]] : PxVec3(0.0f);
+ morphGraphicalNewPos[i + vertexOffset] = positions[i] + disp;
+ }
+ }
+ }
+
+ vertexOffset += submesh.getVertexCount(0);
+ }
+ }
+ }
+ }
+
+ // default render proxy to handle pre simulate case
+ mRenderProxyReady = mClothingScene->getRenderProxy(mAsset->getGraphicalMesh(0), mActorDesc->fallbackSkinning, false, mOverrideMaterials, mActorDesc->morphPhysicalMeshNewPositions.buf, &mGraphicalMeshes[0].morphTargetVertexOffsets[0]);
+
+ if (getRuntimeCookedDataPhysX() != NULL && mActorDesc->actorScale != getRuntimeCookedDataPhysX()->actorScale)
+ {
+ mActorDesc->runtimeCooked->destroy();
+ mActorDesc->runtimeCooked = NULL;
+ }
+
+ // PH: So if backend name is 'embedded', i won't get an asset cooked data ever, so it also won't complain about the cooked version, good
+ // if backend is native, it might, but that's only when you force native with the 2.8.x sdk on a 3.2 asset
+ // const char* cookingDataType = mAsset->getModuleClothing()->getBackendFactory(mBackendName)->getCookingJobType();
+ NvParameterized::Interface* assetCookedData = mAsset->getCookedData(mActorDesc->actorScale);
+ NvParameterized::Interface* actorCookedData = mActorDesc->runtimeCooked;
+
+ BackendFactory* factory = mAsset->getModuleClothing()->getBackendFactory(mBackendName);
+
+ uint32_t assetCookedDataVersion = factory->getCookedDataVersion(assetCookedData);
+ uint32_t actorCookedDataVersion = factory->getCookedDataVersion(actorCookedData);
+
+ if (assetCookedData != NULL && !factory->isMatch(assetCookedData->className()))
+ {
+ APEX_DEBUG_WARNING("Asset (%s) cooked data type (%s) does not match the current backend (%s). Recooking.",
+ mAsset->getName(), assetCookedData->className(), mBackendName);
+ assetCookedData = NULL;
+ }
+ // If the PhysX3 cooking format changes from 3.0 to 3.x, then APEX needs to store something other than the
+ // _SDK_VERSION_NUMBER. Perhaps _PHYSICS_SDK_VERSION (which is something like 0x03010000 or 0x02080400).
+ // Currently, _SDK_VERSION_NUMBER does not change for P3, it is fixed at 300. The PhysX2 path will continue to use
+ // _SDK_VERSION_NUMBER so existing assets cooked with PhysX2 data aren't recooked by default.
+
+ else if (assetCookedData && assetCookedDataVersion != factory->getCookingVersion())
+ {
+ APEX_DEBUG_WARNING("Asset (%s) cooked data version (%d/0x%08x) does not match the current sdk version. Recooking.",
+ mAsset->getName(),
+ assetCookedDataVersion,
+ assetCookedDataVersion);
+ assetCookedData = NULL;
+ }
+
+ if (actorCookedData != NULL && !factory->isMatch(actorCookedData->className()))
+ {
+ APEX_DEBUG_WARNING("Asset (%s) cooked data type (%s) does not match the current backend (%s). Recooking.",
+ mAsset->getName(), assetCookedData->className(), mBackendName);
+ actorCookedData = NULL;
+ }
+
+ if (actorCookedData && actorCookedDataVersion != factory->getCookingVersion())
+ {
+ APEX_DEBUG_WARNING("Actor (%s) cooked data version (%d/0x%08x) does not match the current sdk version. Recooking.",
+ mAsset->getName(),
+ actorCookedDataVersion,
+ actorCookedDataVersion);
+ actorCookedData = NULL;
+ }
+
+ if (assetCookedData == NULL && actorCookedData == NULL && mActiveCookingTask == NULL)
+ {
+ CookingAbstract* cookingJob = mAsset->getModuleClothing()->getBackendFactory(mBackendName)->createCookingJob();
+ PX_ASSERT(cookingJob != NULL);
+
+ if (cookingJob != NULL)
+ {
+ PxVec3 gravity = scene->mApexScene->getGravity();
+ gravity = mActorDesc->globalPose.inverseRT().rotate(gravity);
+ mAsset->prepareCookingJob(*cookingJob, mActorDesc->actorScale, &gravity, NULL);
+
+ if (cookingJob->isValid())
+ {
+ if (mAsset->getModuleClothing()->allowAsyncCooking())
+ {
+ mActiveCookingTask = PX_NEW(ClothingCookingTask)(mClothingScene, *cookingJob);
+ mActiveCookingTask->lockObject(mAsset);
+ mClothingScene->submitCookingTask(mActiveCookingTask);
+ }
+ else
+ {
+ mActorDesc->runtimeCooked = cookingJob->execute();
+ PX_DELETE_AND_RESET(cookingJob);
+ }
+ }
+ else
+ {
+ PX_DELETE_AND_RESET(cookingJob);
+ }
+ }
+
+ }
+
+ mActorProxy->userData = reinterpret_cast<void*>(mActorDesc->userData);
+ }
+ else if (::strcmp(descriptor.className(), ClothingPreviewParam::staticClassName()) == 0)
+ {
+ PX_ASSERT(mPreviewProxy != NULL);
+
+ const ClothingPreviewParam& previewDesc = static_cast<const ClothingPreviewParam&>(descriptor);
+ mActorDesc = static_cast<ClothingActorParam*>(GetInternalApexSDK()->getParameterizedTraits()->createNvParameterized(ClothingActorParam::staticClassName()));
+ PX_ASSERT(mActorDesc != NULL);
+ mActorDesc->globalPose = previewDesc.globalPose;
+ {
+ NvParameterized::Handle handle(mActorDesc);
+ handle.getParameter("boneMatrices");
+ handle.resizeArray(previewDesc.boneMatrices.arraySizes[0]);
+ for (int32_t i = 0; i < previewDesc.boneMatrices.arraySizes[0]; i++)
+ {
+ mActorDesc->boneMatrices.buf[i] = previewDesc.boneMatrices.buf[i];
+ }
+ }
+ mActorDesc->useInternalBoneOrder = previewDesc.useInternalBoneOrder;
+ mActorDesc->updateStateWithGlobalMatrices = previewDesc.updateStateWithGlobalMatrices;
+ mActorDesc->fallbackSkinning = previewDesc.fallbackSkinning;
+
+ //mActorDesc->copy(descriptor);
+ //PX_ASSERT(mActorDesc->equals(descriptor, NULL, 0));
+
+ // prepare some runtime data for each graphical mesh
+ mGraphicalMeshes.reserve(mAsset->getNumGraphicalMeshes());
+ for (uint32_t i = 0; i < mAsset->getNumGraphicalMeshes(); i++)
+ {
+ ClothingGraphicalMeshActor actor;
+ RenderMeshAssetIntl* renderMeshAsset = mAsset->getGraphicalMesh(i);
+ if (renderMeshAsset == NULL)
+ continue;
+
+ actor.active = i == 0;
+ actor.morphTargetVertexOffsets.pushBack(0);
+ mGraphicalMeshes.pushBack(actor);
+ }
+ // default render proxy to handle pre simulate case
+ mRenderProxyReady = PX_NEW(ClothingRenderProxyImpl)(mAsset->getGraphicalMesh(0), mActorDesc->fallbackSkinning, false, mOverrideMaterials, mActorDesc->morphPhysicalMeshNewPositions.buf, &mGraphicalMeshes[0].morphTargetVertexOffsets[0], NULL);
+
+ mPreviewProxy->userData = reinterpret_cast<void*>(mActorDesc->userData);
+ }
+ else
+ {
+ APEX_INVALID_PARAMETER("%s is not a valid descriptor class", descriptor.className());
+
+ PX_ASSERT(mActorProxy == NULL);
+ PX_ASSERT(mPreviewProxy == NULL);
+ }
+
+ if (mActorDesc != NULL)
+ {
+ // initialize overrideMaterialMap with data from actor desc
+ for (uint32_t i = 0; i < (uint32_t)mActorDesc->overrideMaterialNames.arraySizes[0]; ++i)
+ {
+ mOverrideMaterials[i] = mActorDesc->overrideMaterialNames.buf[i];
+ }
+
+ if (mActorDesc->updateStateWithGlobalMatrices)
+ {
+ mAsset->setupInvBindMatrices();
+ }
+
+ uint32_t numMeshesWithTangents = 0;
+ uint32_t maxVertexCount = 0;
+
+ for (uint32_t i = 0; i < mGraphicalMeshes.size(); i++)
+ {
+ RenderMeshAssetIntl* renderMeshAsset = mAsset->getGraphicalMesh(i);
+
+ const ClothingGraphicalMeshAssetWrapper meshAsset(renderMeshAsset);
+
+ if (meshAsset.hasChannel(NULL, RenderVertexSemantic::TANGENT) && meshAsset.hasChannel(NULL, RenderVertexSemantic::BINORMAL))
+ {
+ PX_ALWAYS_ASSERT();
+ // need to compress them into one semantic
+ //APEX_INVALID_PARAMETER("RenderMeshAsset must have either TANGENT and BINORMAL semantics, or none. But not only one!");
+ }
+
+ if (meshAsset.hasChannel(NULL, RenderVertexSemantic::TANGENT) && meshAsset.hasChannel(NULL, RenderVertexSemantic::TEXCOORD0))
+ {
+ numMeshesWithTangents++;
+ mGraphicalMeshes[i].needsTangents = true;
+ }
+ maxVertexCount = PxMax(maxVertexCount, meshAsset.getNumTotalVertices());
+ }
+
+ const uint32_t numBones = mActorDesc->useInternalBoneOrder ? mAsset->getNumUsedBones() : mActorDesc->boneMatrices.arraySizes[0];
+ updateState(mActorDesc->globalPose, mActorDesc->boneMatrices.buf, sizeof(PxMat44), numBones, ClothingTeleportMode::Continuous);
+ updateStateInternal_NoPhysX(false);
+ updateBoneBuffer(mRenderProxyReady);
+ }
+
+ mRenderBounds = getRenderMeshAssetBoundsTransformed();
+ bool bHasBones = mActorDesc->boneMatrices.arraySizes[0] > 0 || mAsset->getNumBones() > 0;
+ if (bHasBones && bInternalLocalSpaceSim == 1)
+ {
+ PX_ASSERT(!mRenderBounds.isEmpty());
+ mRenderBounds = PxBounds3::transformFast(PxTransform(mInternalGlobalPose), mRenderBounds);
+ }
+
+ PX_ASSERT(mRenderBounds.isFinite());
+ PX_ASSERT(!mRenderBounds.isEmpty());
+}
+
+
+
+void ClothingActorImpl::release()
+{
+ if (mInRelease)
+ {
+ return;
+ }
+
+ if (isSimulationRunning())
+ {
+ APEX_INVALID_OPERATION("Cannot release ClothingActorImpl while simulation is still running");
+ return;
+ }
+
+ waitForFetchResults();
+
+ mInRelease = true;
+
+ if (mActorProxy != NULL)
+ {
+ mAsset->releaseClothingActor(*mActorProxy);
+ }
+ else
+ {
+ PX_ASSERT(mPreviewProxy != NULL);
+ mAsset->releaseClothingPreview(*mPreviewProxy);
+ }
+}
+
+
+
+Renderable* ClothingActorImpl::getRenderable()
+{
+ // make sure the result is ready
+ // this is mainly for legacy kind of rendering
+ // with the renderable iterator. note that the
+ // user does not acquire the render proxy here
+ waitForFetchResults();
+
+ return mRenderProxyReady;
+}
+
+
+
+void ClothingActorImpl::dispatchRenderResources(UserRenderer& api)
+{
+ mRenderProxyMutex.lock();
+ if (mRenderProxyURR != NULL)
+ {
+ mRenderProxyURR->dispatchRenderResources(api);
+ }
+ mRenderProxyMutex.unlock();
+}
+
+
+
+void ClothingActorImpl::updateRenderResources(bool rewriteBuffers, void* userRenderData)
+{
+ waitForFetchResults();
+
+ ClothingRenderProxyImpl* newRenderProxy = static_cast<ClothingRenderProxyImpl*>(acquireRenderProxy());
+ if (newRenderProxy != NULL)
+ {
+ if (mRenderProxyURR != NULL)
+ {
+ mRenderProxyURR->release();
+ mRenderProxyURR = NULL;
+ }
+ mRenderProxyURR = newRenderProxy;
+ }
+ if (mRenderProxyURR != NULL)
+ {
+ mRenderProxyURR->updateRenderResources(rewriteBuffers, userRenderData);
+ }
+}
+
+
+
+NvParameterized::Interface* ClothingActorImpl::getActorDesc()
+{
+ if (mActorDesc != NULL && isValidDesc(*mActorDesc))
+ {
+ return mActorDesc;
+ }
+
+ return NULL;
+}
+
+
+
+void ClothingActorImpl::updateState(const PxMat44& globalPose, const PxMat44* newBoneMatrices, uint32_t boneMatricesByteStride, uint32_t numBoneMatrices, ClothingTeleportMode::Enum teleportMode)
+{
+ PX_PROFILE_ZONE("ClothingActorImpl::updateState", GetInternalApexSDK()->getContextId());
+
+ PX_ASSERT(mActorDesc);
+ const bool useInternalBoneOrder = mActorDesc->useInternalBoneOrder;
+
+ uint32_t numElements = useInternalBoneOrder ? mAsset->getNumUsedBones() : mAsset->getNumBones();
+ if (useInternalBoneOrder && (numBoneMatrices > numElements))
+ {
+ APEX_DEBUG_WARNING("numMatrices too big.");
+ return;
+ }
+
+ mActorDesc->globalPose = globalPose;
+ if (!PxEquals(globalPose.column0.magnitude(), mActorDesc->actorScale, 1e-5))
+ {
+ APEX_DEBUG_WARNING("Actor Scale wasn't set properly, it doesn't equal to the Global Pose scale: %f != %f",
+ mActorDesc->actorScale,
+ globalPose.column0.magnitude());
+ }
+
+ PX_ASSERT(newBoneMatrices == NULL || boneMatricesByteStride >= sizeof(PxMat44));
+ if (boneMatricesByteStride >= sizeof(PxMat44) && newBoneMatrices != NULL)
+ {
+ if (mActorDesc->boneMatrices.arraySizes[0] != (int32_t)numBoneMatrices)
+ {
+ // PH: aligned alloc?
+ NvParameterized::Handle handle(mActorDesc);
+ handle.getParameter("boneMatrices");
+ handle.resizeArray((int32_t)numBoneMatrices);
+ }
+
+ for (uint32_t i = 0; i < numBoneMatrices; i++)
+ {
+ const PxMat44* source = (const PxMat44*)(((const uint8_t*)newBoneMatrices) + boneMatricesByteStride * i);
+ mActorDesc->boneMatrices.buf[i] = *source;
+ }
+ }
+ else
+ {
+ NvParameterized::Handle handle(mActorDesc);
+ handle.getParameter("boneMatrices");
+ handle.resizeArray(0);
+ }
+
+ mActorDesc->teleportMode = teleportMode;
+
+ if (mClothingScene == NULL)
+ {
+ // In Preview mode!
+ updateStateInternal_NoPhysX(false);
+ updateBoneBuffer(mRenderProxyReady);
+ }
+}
+
+
+
+void ClothingActorImpl::updateMaxDistanceScale(float scale, bool multipliable)
+{
+ PX_ASSERT(mActorDesc != NULL);
+ mActorDesc->maxDistanceScale.Scale = PxClamp(scale, 0.0f, 1.0f);
+ mActorDesc->maxDistanceScale.Multipliable = multipliable;
+}
+
+
+
+const PxMat44& ClothingActorImpl::getGlobalPose() const
+{
+ PX_ASSERT(mActorDesc != NULL);
+ return mActorDesc->globalPose;
+}
+
+
+
+void ClothingActorImpl::setWind(float windAdaption, const PxVec3& windVelocity)
+{
+ if (windAdaption < 0.0f)
+ {
+ APEX_INVALID_PARAMETER("windAdaption must be bigger or equal than 0.0 (is %f)", windAdaption);
+ windAdaption = 0.0f;
+ }
+
+ PX_ASSERT(mActorDesc);
+ mActorDesc->windParams.Adaption = windAdaption;
+ mActorDesc->windParams.Velocity = windVelocity;
+}
+
+
+
+void ClothingActorImpl::setMaxDistanceBlendTime(float blendTime)
+{
+ PX_ASSERT(mActorDesc);
+ mActorDesc->maxDistanceBlendTime = blendTime;
+}
+
+
+
+
+float ClothingActorImpl::getMaxDistanceBlendTime() const
+{
+ PX_ASSERT(mActorDesc);
+ return mActorDesc->maxDistanceBlendTime;
+}
+
+
+
+void ClothingActorImpl::setVisible(bool enable)
+{
+ // buffer enable
+ bBufferedVisible = enable ? 1u : 0u;
+
+ // disable immediately
+ if (!enable)
+ {
+ bInternalVisible = 0;
+ }
+}
+
+
+
+bool ClothingActorImpl::isVisibleBuffered() const
+{
+ return bBufferedVisible == 1;
+}
+
+
+
+bool ClothingActorImpl::isVisible() const
+{
+ return bInternalVisible == 1;
+}
+
+
+
+bool ClothingActorImpl::shouldComputeRenderData() const
+{
+ return mInternalFlags.ComputeRenderData && bInternalVisible == 1 && mGraphicalMeshes[mCurrentGraphicalLodId].renderProxy != NULL;
+}
+
+
+
+void ClothingActorImpl::setFrozen(bool enable)
+{
+ bUpdateFrozenFlag = 1;
+ bBufferedFrozen = enable ? 1u : 0u;
+}
+
+
+
+bool ClothingActorImpl::isFrozenBuffered() const
+{
+ return bBufferedFrozen == 1;
+}
+
+
+
+ClothSolverMode::Enum ClothingActorImpl::getClothSolverMode() const
+{
+ return ClothSolverMode::v3;
+}
+
+
+
+void ClothingActorImpl::freeze_LocksPhysX(bool on)
+{
+ if (mClothingSimulation != NULL)
+ {
+ mClothingSimulation->setStatic(on);
+ }
+}
+
+
+
+void ClothingActorImpl::setGraphicalLOD(uint32_t lod)
+{
+ mBufferedGraphicalLod = PxMin(lod, mAsset->getNumGraphicalLodLevels()-1);
+}
+
+
+
+uint32_t ClothingActorImpl::getGraphicalLod()
+{
+ return mBufferedGraphicalLod;
+}
+
+
+
+bool ClothingActorImpl::rayCast(const PxVec3& worldOrigin, const PxVec3& worldDirection, float& time, PxVec3& normal, uint32_t& vertexIndex)
+{
+ if (mClothingSimulation != NULL)
+ {
+ PxVec3 origin(worldOrigin);
+ PxVec3 dir(worldDirection);
+ if (bInternalLocalSpaceSim == 1)
+ {
+#if _DEBUG
+ bool ok = true;
+ ok &= mInternalGlobalPose.column0.isNormalized();
+ ok &= mInternalGlobalPose.column1.isNormalized();
+ ok &= mInternalGlobalPose.column2.isNormalized();
+ if (!ok)
+ {
+ APEX_DEBUG_WARNING("Internal Global Pose is not normalized (Scale: %f %f %f). Raycast could be wrong.", mInternalGlobalPose.column0.magnitude(), mInternalGlobalPose.column1.magnitude(), mInternalGlobalPose.column2.magnitude());
+ }
+#endif
+ PxMat44 invGlobalPose = mInternalGlobalPose.inverseRT();
+ origin = invGlobalPose.transform(worldOrigin);
+ dir = invGlobalPose.rotate(worldDirection);
+ }
+
+ bool hit = mClothingSimulation->raycast(origin, dir, time, normal, vertexIndex);
+
+ if (hit && bInternalLocalSpaceSim == 1)
+ {
+ mInternalGlobalPose.rotate(normal);
+ }
+ return hit;
+
+ }
+
+ return false;
+}
+
+
+
+void ClothingActorImpl::attachVertexToGlobalPosition(uint32_t vertexIndex, const PxVec3& worldPosition)
+{
+ if (mClothingSimulation != NULL)
+ {
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ const ClothingPhysicalMeshParametersNS::ConstrainCoefficient_Type* const PX_RESTRICT coeffs = physicalMesh->constrainCoefficients.buf;
+ PX_ASSERT((int32_t)vertexIndex < physicalMesh->constrainCoefficients.arraySizes[0]);
+
+ const float linearScale = (mInternalMaxDistanceScale.Multipliable ? mInternalMaxDistanceScale.Scale : 1.0f) * mActorDesc->actorScale;
+ const float absoluteScale = mInternalMaxDistanceScale.Multipliable ? 0.0f : (physicalMesh->maximumMaxDistance * (1.0f - mInternalMaxDistanceScale.Scale));
+ const float reduceMaxDistance = mMaxDistReduction + absoluteScale;
+
+ const float maxDistance = PxMax(0.0f, coeffs[vertexIndex].maxDistance - reduceMaxDistance) * linearScale;
+ const PxVec3 skinnedPosition = mClothingSimulation->skinnedPhysicsPositions[vertexIndex];
+
+ PxVec3 restrictedWorldPosition = worldPosition;
+ if (bInternalLocalSpaceSim == 1)
+ {
+#if _DEBUG
+ bool ok = true;
+ ok &= mInternalGlobalPose.column0.isNormalized();
+ ok &= mInternalGlobalPose.column1.isNormalized();
+ ok &= mInternalGlobalPose.column2.isNormalized();
+ if (!ok)
+ {
+ APEX_DEBUG_WARNING("Internal Global Pose is not normalized (Scale: %f %f %f). attachVertexToGlobalPosition could be wrong.", mInternalGlobalPose.column0.magnitude(), mInternalGlobalPose.column1.magnitude(), mInternalGlobalPose.column2.magnitude());
+ }
+#endif
+ restrictedWorldPosition = mInternalGlobalPose.inverseRT().transform(restrictedWorldPosition);
+ }
+
+ PxVec3 dir = restrictedWorldPosition - skinnedPosition;
+ if (dir.magnitude() > maxDistance)
+ {
+ dir.normalize();
+ restrictedWorldPosition = skinnedPosition + dir * maxDistance;
+ }
+
+ mClothingSimulation->attachVertexToGlobalPosition(vertexIndex, restrictedWorldPosition);
+ }
+}
+
+
+
+void ClothingActorImpl::freeVertex(uint32_t vertexIndex)
+{
+ if (mClothingSimulation != NULL)
+ {
+ mClothingSimulation->freeVertex(vertexIndex);
+ }
+}
+
+
+
+uint32_t ClothingActorImpl::getClothingMaterial() const
+{
+ const ClothingAssetParameters* clothingAsset = static_cast<const ClothingAssetParameters*>(mAsset->getAssetNvParameterized());
+ ClothingMaterialLibraryParameters* materialLib = static_cast<ClothingMaterialLibraryParameters*>(clothingAsset->materialLibrary);
+
+ PX_ASSERT(materialLib != NULL);
+ if (materialLib == NULL)
+ {
+ return 0;
+ }
+
+ PX_ASSERT(materialLib->materials.buf != NULL);
+ PX_ASSERT(materialLib->materials.arraySizes[0] > 0);
+
+ PX_ASSERT(mActorDesc->clothingMaterialIndex < (uint32_t)materialLib->materials.arraySizes[0]);
+
+ return mActorDesc->clothingMaterialIndex;
+}
+
+
+
+void ClothingActorImpl::setClothingMaterial(uint32_t index)
+{
+ mActorDesc->clothingMaterialIndex = index;
+}
+
+
+
+void ClothingActorImpl::setOverrideMaterial(uint32_t submeshIndex, const char* overrideMaterialName)
+{
+ mOverrideMaterials[submeshIndex] = ApexSimpleString(overrideMaterialName);
+
+ for (uint32_t i = 0; i < mGraphicalMeshes.size(); ++i)
+ {
+ ClothingRenderProxyImpl* renderProxy = mGraphicalMeshes[i].renderProxy;
+ if (renderProxy != NULL)
+ {
+ renderProxy->setOverrideMaterial(i, overrideMaterialName);
+ }
+ }
+}
+
+
+
+void ClothingActorImpl::getLodRange(float& min, float& max, bool& intOnly) const
+{
+ min = 0.f;
+ max = 1.f;
+ intOnly = true;
+}
+
+
+
+float ClothingActorImpl::getActiveLod() const
+{
+ return bIsSimulationOn ? 0.f : 1.f;
+}
+
+
+
+void ClothingActorImpl::forceLod(float lod)
+{
+ if (lod < 0.0f)
+ {
+ mForceSimulation = -1;
+ }
+ else if (lod >= 1.f)
+ {
+ mForceSimulation = 1;
+ }
+ else
+ {
+ mForceSimulation = (int32_t)(lod + 0.5f);
+ }
+
+ if (mClothingSimulation == NULL && mForceSimulation > 0)
+ {
+ mMaxDistReduction = mAsset->getBiggestMaxDistance();
+ }
+}
+
+
+
+void ClothingActorImpl::getPhysicalMeshPositions(void* buffer, uint32_t byteStride)
+{
+ if (isSimulationRunning())
+ {
+ APEX_INTERNAL_ERROR("Cannot be called while the scene is running");
+ return;
+ }
+
+ PX_ASSERT(buffer != NULL);
+ if (byteStride == 0)
+ {
+ byteStride = sizeof(PxVec3);
+ }
+
+ if (byteStride < sizeof(PxVec3))
+ {
+ APEX_INTERNAL_ERROR("Bytestride is too small (%d, but must be >= %d)", byteStride, sizeof(PxVec3));
+ return;
+ }
+
+ uint32_t numSimulatedVertices = (mClothingSimulation == NULL) ? 0 : mClothingSimulation->sdkNumDeformableVertices;
+ PxStrideIterator<PxVec3> it((PxVec3*)buffer, byteStride);
+ for (uint32_t i = 0; i < numSimulatedVertices; i++, ++it)
+ {
+ *it = mClothingSimulation->sdkWritebackPosition[i];
+ }
+
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* pmesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ const PxVec3* skinPosePosition = pmesh->vertices.buf;
+ const PxMat44* matrices = mData.mInternalBoneMatricesCur;
+
+ const uint8_t* const PX_RESTRICT optimizationData = pmesh->optimizationData.buf;
+ PX_ASSERT(optimizationData != NULL);
+
+ if (matrices != NULL)
+ {
+ const uint16_t* boneIndices = pmesh->boneIndices.buf;
+ const float* boneWeights = pmesh->boneWeights.buf;
+ const uint32_t numBonesPerVertex = pmesh->numBonesPerVertex;
+ const uint32_t numVertices = pmesh->numVertices;
+ for (uint32_t vertexIndex = numSimulatedVertices; vertexIndex < numVertices; ++vertexIndex, ++it)
+ {
+ const uint8_t shift = 4 * (vertexIndex % 2);
+ const uint8_t numBones = uint8_t((optimizationData[vertexIndex / 2] >> shift) & 0x7);
+
+ Simd4f temp = gSimd4fZero;
+ for (uint32_t j = 0; j < numBones; j++)
+ {
+ const Simd4f boneWeightV = Simd4fScalarFactory(boneWeights[vertexIndex * numBonesPerVertex + j]);
+ const uint32_t boneIndex = boneIndices[vertexIndex * numBonesPerVertex + j];
+ const PxMat44& mat = (PxMat44&)(matrices[boneIndex]);
+
+ Simd4f transformedPosV = applyAffineTransform(mat, createSimd3f(skinPosePosition[vertexIndex]));
+ transformedPosV = transformedPosV * boneWeightV;
+ temp = temp + transformedPosV;
+ }
+ store3(&(*it).x, temp);
+ }
+ }
+ else
+ {
+ const uint32_t numVertices = pmesh->numVertices;
+ const PxMat44& mat = (PxMat44&)(mInternalGlobalPose);
+ for (uint32_t vertexIndex = numSimulatedVertices; vertexIndex < numVertices; ++vertexIndex, ++it)
+ {
+ Simd4f transformedPosV = applyAffineTransform(mat, createSimd3f(skinPosePosition[vertexIndex]));
+ store3(&(*it).x, transformedPosV);
+ }
+ }
+}
+
+
+
+void ClothingActorImpl::getPhysicalMeshNormals(void* buffer, uint32_t byteStride)
+{
+ if (isSimulationRunning())
+ {
+ APEX_INTERNAL_ERROR("Cannot be called while the scene is running");
+ return;
+ }
+
+ PX_ASSERT(buffer != NULL);
+ if (byteStride == 0)
+ {
+ byteStride = sizeof(PxVec3);
+ }
+
+ if (byteStride < sizeof(PxVec3))
+ {
+ APEX_INTERNAL_ERROR("Bytestride is too small (%d, but must be >= %d)", byteStride, sizeof(PxVec3));
+ return;
+ }
+
+ if (mClothingSimulation == NULL)
+ {
+ APEX_INTERNAL_ERROR("No simulation data available");
+ return;
+ }
+
+ if (mClothingSimulation->sdkWritebackNormal == NULL)
+ {
+ APEX_INTERNAL_ERROR("No simulation normals for softbodies");
+ return;
+ }
+
+ PxStrideIterator<PxVec3> it((PxVec3*)buffer, byteStride);
+ for (uint32_t i = 0; i < mClothingSimulation->sdkNumDeformableVertices; i++, ++it)
+ {
+ *it = mClothingSimulation->sdkWritebackNormal[i];
+ }
+
+
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* pmesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ const PxVec3* skinPoseNormal = pmesh->normals.buf;
+ const PxMat44* matrices = mData.mInternalBoneMatricesCur;
+ const uint32_t numVertices = pmesh->numVertices;
+
+ const uint8_t* const PX_RESTRICT optimizationData = pmesh->optimizationData.buf;
+ PX_ASSERT(optimizationData != NULL);
+
+ if (matrices != NULL)
+ {
+ const uint16_t* boneIndices = pmesh->boneIndices.buf;
+ const float* boneWeights = pmesh->boneWeights.buf;
+ const uint32_t numBonesPerVertex = pmesh->numBonesPerVertex;
+ for (uint32_t vertexIndex = mClothingSimulation->sdkNumDeformableVertices; vertexIndex < numVertices; ++vertexIndex, ++it)
+ {
+ const uint8_t shift = 4 * (vertexIndex % 2);
+ const uint8_t numBones = uint8_t((optimizationData[vertexIndex / 2] >> shift) & 0x7);
+
+ Simd4f temp = gSimd4fZero;
+ for (uint32_t j = 0; j < numBones; j++)
+ {
+ const Simd4f boneWeightV = Simd4fScalarFactory(boneWeights[vertexIndex * numBonesPerVertex + j]);
+ const uint32_t boneIndex = boneIndices[vertexIndex * numBonesPerVertex + j];
+ const PxMat44& mat = (PxMat44&)(matrices[boneIndex]);
+
+ Simd4f transformedNormalV = applyAffineTransform(mat, createSimd3f(skinPoseNormal[vertexIndex]));
+ transformedNormalV = transformedNormalV * boneWeightV;
+ temp = temp + transformedNormalV;
+ }
+ store3(&(*it).x, temp);
+ }
+ }
+ else
+ {
+ const PxMat44& mat = (PxMat44&)(mInternalGlobalPose);
+ for (uint32_t vertexIndex = mClothingSimulation->sdkNumDeformableVertices; vertexIndex < numVertices; ++vertexIndex, ++it)
+ {
+ Simd4f transformedNormalV = applyLinearTransform(mat, createSimd3f(skinPoseNormal[vertexIndex]));
+ store3(&(*it).x, transformedNormalV);
+ }
+ }
+}
+
+
+
+float ClothingActorImpl::getMaximumSimulationBudget() const
+{
+ uint32_t solverIterations = 5;
+
+ ClothingMaterialLibraryParametersNS::ClothingMaterial_Type* clothingMaterial = getCurrentClothingMaterial();
+ if (clothingMaterial != NULL)
+ {
+ solverIterations = clothingMaterial->solverIterations;
+ }
+
+ return mAsset->getMaximumSimulationBudget(solverIterations);
+}
+
+
+
+uint32_t ClothingActorImpl::getNumSimulationVertices() const
+{
+ uint32_t numVerts = 0;
+ if (mClothingSimulation != NULL)
+ {
+ numVerts = mClothingSimulation->sdkNumDeformableVertices;
+ }
+ return numVerts;
+}
+
+
+
+const PxVec3* ClothingActorImpl::getSimulationPositions()
+{
+ if (mClothingSimulation == NULL)
+ return NULL;
+
+ waitForFetchResults();
+
+ return mClothingSimulation->sdkWritebackPosition;
+}
+
+
+
+const PxVec3* ClothingActorImpl::getSimulationNormals()
+{
+ if (mClothingSimulation == NULL)
+ return NULL;
+
+ waitForFetchResults();
+
+ return mClothingSimulation->sdkWritebackNormal;
+}
+
+
+
+bool ClothingActorImpl::getSimulationVelocities(PxVec3* velocities)
+{
+ if (mClothingSimulation == NULL)
+ return false;
+
+ waitForFetchResults();
+
+ mClothingSimulation->getVelocities(velocities);
+ return true;
+}
+
+
+
+uint32_t ClothingActorImpl::getNumGraphicalVerticesActive(uint32_t submeshIndex) const
+{
+ if (mClothingSimulation == NULL)
+ return 0;
+
+ uint32_t numVertices = 0;
+
+ const ClothingGraphicalLodParameters* graphicalLod = mAsset->getGraphicalLod(mCurrentGraphicalLodId);
+
+ const uint32_t numParts = (uint32_t)graphicalLod->physicsMeshPartitioning.arraySizes[0];
+ ClothingGraphicalLodParametersNS::PhysicsMeshPartitioning_Type* parts = graphicalLod->physicsMeshPartitioning.buf;
+
+#if PX_DEBUG || PX_CHECKED
+ bool found = false;
+#endif
+ for (uint32_t c = 0; c < numParts; c++)
+ {
+ if (parts[c].graphicalSubmesh == submeshIndex)
+ {
+ numVertices = parts[c].numSimulatedVertices;
+#if defined _DEBUG || PX_CHECKED
+ found = true;
+#endif
+ break;
+ }
+ }
+#if PX_DEBUG || PX_CHECKED
+ PX_ASSERT(found);
+#endif
+
+ return numVertices;
+}
+
+
+
+PxMat44 ClothingActorImpl::getRenderGlobalPose() const
+{
+ return (bInternalLocalSpaceSim == 1) ? mInternalGlobalPose : PxMat44(PxIdentity);
+}
+
+
+
+const PxMat44* ClothingActorImpl::getCurrentBoneSkinningMatrices() const
+{
+ return mData.mInternalBoneMatricesCur;
+}
+
+
+#if PX_PHYSICS_VERSION_MAJOR == 3
+void ClothingActorImpl::setPhysXScene(PxScene* physXscene)
+{
+ if (isSimulationRunning())
+ {
+ APEX_INTERNAL_ERROR("Cannot change the physics scene while the simulation is running");
+ return;
+ }
+
+ if (mPhysXScene != NULL && mPhysXScene != physXscene)
+ {
+ removePhysX_LocksPhysX();
+ }
+
+ mPhysXScene = physXscene;
+
+ if (mPhysXScene != NULL)
+ {
+ if (isCookedDataReady())
+ {
+ createPhysX_LocksPhysX(0.0f);
+ }
+ }
+}
+
+PxScene* ClothingActorImpl::getPhysXScene() const
+{
+ return mPhysXScene;
+}
+#endif
+
+
+// this is 2.8.x only
+void ClothingActorImpl::updateScaledGravity(float substepSize)
+{
+ if (mClothingScene != NULL && mClothingScene->mApexScene != NULL)
+ {
+ PxVec3 oldInternalScaledGravity = mInternalScaledGravity;
+ mInternalScaledGravity = mClothingScene->mApexScene->getGravity();
+
+ if (mActorDesc->allowAdaptiveTargetFrequency)
+ {
+ // disable adaptive frequency if the simulation doesn't require it
+ if (mClothingSimulation && !mClothingSimulation->needsAdaptiveTargetFrequency())
+ {
+ substepSize = 0.0f;
+ }
+
+ const float targetFrequency = mClothingScene->getAverageSimulationFrequency(); // will return 0 if the module is not set to compute it!
+ if (targetFrequency > 0.0f && substepSize > 0.0f)
+ {
+ // PH: This will scale the gravity to result in fixed velocity deltas (in Cloth/SoftBody)
+ const float targetScale = 1.0f / (targetFrequency * substepSize);
+ mInternalScaledGravity *= targetScale * targetScale; // need to square this to achieve constant behavior.
+ }
+ }
+
+ bInternalScaledGravityChanged = (oldInternalScaledGravity != mInternalScaledGravity) ? 1u : 0u;
+ }
+}
+
+
+
+void ClothingActorImpl::tickSynchBeforeSimulate_LocksPhysX(float simulationDelta, float substepSize, uint32_t substepNumber, uint32_t numSubSteps)
+{
+ PX_PROFILE_ZONE("ClothingActorImpl::beforeSimulate", GetInternalApexSDK()->getContextId());
+
+ // PH: simulationDelta can be 0 for subsequent substeps (substepNumber > 0 and numSubSteps > 1
+
+ if (mClothingSimulation != NULL && simulationDelta > 0.0f)
+ {
+ mClothingSimulation->verifyTimeStep(substepSize);
+ }
+
+ if (substepNumber == 0)
+ {
+ PX_PROFILE_ZONE("ClothingActorImpl::updateStateInternal", GetInternalApexSDK()->getContextId());
+
+ updateStateInternal_NoPhysX(numSubSteps > 1);
+ updateScaledGravity(substepSize); // moved after updateStateInternal, cause it reads the localSpace state
+ freeze_LocksPhysX(bInternalFrozen == 1);
+ }
+
+ /// interpolate matrices
+ if (numSubSteps > 1)
+ {
+ PX_PROFILE_ZONE("ClothingActorImpl::interpolateMatrices", GetInternalApexSDK()->getContextId());
+
+ const uint32_t numBones = mActorDesc->useInternalBoneOrder ? mAsset->getNumUsedBones() : mAsset->getNumBones();
+ PX_ASSERT((numBones != 0) == (mInternalInterpolatedBoneMatrices != NULL));
+ PX_ASSERT((numBones != 0) == (mData.mInternalBoneMatricesPrev != NULL));
+ if (substepNumber == (numSubSteps - 1))
+ {
+ bool matrixChanged = false;
+ for (uint32_t i = 0; i < numBones; i++)
+ {
+ mInternalInterpolatedBoneMatrices[i] = mData.mInternalBoneMatricesCur[i];
+ matrixChanged |= mData.mInternalBoneMatricesCur[i] != mData.mInternalBoneMatricesPrev[i];
+ }
+
+ mInternalInterpolatedGlobalPose = mInternalGlobalPose;
+ bGlobalPoseChanged |= mOldInternalGlobalPose != mInternalGlobalPose ? 1 : 0;
+ bBoneMatricesChanged |= matrixChanged ? 1 : 0;
+ }
+ else
+ {
+ const float ratio = bInternalTeleportDue == ClothingTeleportMode::TeleportAndReset ? 0.0f : (1.0f - float(substepNumber + 1) / float(numSubSteps));
+
+ bool matrixChanged = false;
+ for (uint32_t i = 0; i < numBones; i++)
+ {
+ mInternalInterpolatedBoneMatrices[i] = interpolateMatrix(ratio, mData.mInternalBoneMatricesPrev[i], mData.mInternalBoneMatricesCur[i]);
+ matrixChanged |= mData.mInternalBoneMatricesCur[i] != mData.mInternalBoneMatricesPrev[i];
+ }
+ mInternalInterpolatedGlobalPose = interpolateMatrix(ratio, mOldInternalGlobalPose, mInternalGlobalPose);
+ bGlobalPoseChanged |= mOldInternalGlobalPose != mInternalGlobalPose ? 1 : 0;
+ bBoneMatricesChanged |= matrixChanged ? 1 : 0;
+ }
+ }
+
+ if (mClothingSimulation != NULL)
+ {
+ mClothingSimulation->setGlobalPose(substepNumber == 0 ? mInternalGlobalPose : mInternalInterpolatedGlobalPose);
+ }
+
+ // PH: this is done before createPhysX mesh is called to make sure it's not executed on the freshly generated skeleton
+ // see ClothignAsset::createCollisionBulk for more info
+ {
+ PX_PROFILE_ZONE("ClothingActorImpl::updateCollision", GetInternalApexSDK()->getContextId());
+ updateCollision_LocksPhysX(numSubSteps > 1);
+ }
+
+ // PH: Done before skinPhysicsMesh to use the same buffers
+ if (mClothingSimulation != NULL && substepNumber == 0 && (bInternalFrozen == 0))
+ {
+ PX_PROFILE_ZONE("ClothingActorImpl::applyVelocityChanges", GetInternalApexSDK()->getContextId());
+ applyVelocityChanges_LocksPhysX(simulationDelta);
+ }
+
+ if (substepNumber == 0)
+ {
+ lodTick_LocksPhysX(simulationDelta);
+ }
+
+ if (mCurrentSolverIterations > 0)
+ {
+ PX_ASSERT(mClothingSimulation != NULL); // after lodTick there should be a simulation mesh
+
+ applyTeleport(false, substepNumber);
+
+ if (bDirtyClothingTemplate == 1)
+ {
+ bDirtyClothingTemplate = 0;
+ mClothingSimulation->applyClothingDesc(mActorDesc->clothDescTemplate);
+ }
+ }
+
+ initializeActorData();
+ if (mClothingSimulation != NULL)
+ {
+ skinPhysicsMesh(numSubSteps > 1, (float)(substepNumber + 1) / (float)numSubSteps);
+
+ applyLockingTasks();
+
+ mClothingSimulation->setInterCollisionChannels(mInterCollisionChannels);
+
+ mClothingSimulation->setHalfPrecisionOption(mIsAllowedHalfPrecisionSolver);
+ }
+}
+
+
+
+void ClothingActorImpl::applyLockingTasks()
+{
+ if (mClothingSimulation != NULL)
+ {
+ // depends on nothing
+ applyClothingMaterial_LocksPhysX();
+
+ // depends on skinning
+ applyTeleport(true, 0);
+
+ // depends on applyTeleport
+ applyGlobalPose_LocksPhysX();
+
+ // depends on skinning and applyTeleport
+ updateConstrainPositions_LocksPhysX();
+
+ // depends on lod tick (and maybe applyTeleport eventually)
+ applyCollision_LocksPhysX();
+ }
+}
+
+
+
+bool ClothingActorImpl::isSkinningDirty()
+{
+ return bBoneMatricesChanged == 1 || ((!bInternalLocalSpaceSim) == 1 && bGlobalPoseChanged == 1);
+}
+
+
+
+void ClothingActorImpl::skinPhysicsMesh(bool useInterpolatedMatrices, float substepFraction)
+{
+ if (mClothingSimulation == NULL || mClothingSimulation->skinnedPhysicsPositions == NULL)
+ {
+ return;
+ }
+
+ const bool skinningDirty = isSkinningDirty();
+ if (skinningDirty)
+ {
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+
+ if (physicalMesh->hasNegativeBackstop)
+ {
+ skinPhysicsMeshInternal<true>(useInterpolatedMatrices, substepFraction);
+ }
+ else
+ {
+ skinPhysicsMeshInternal<false>(useInterpolatedMatrices, substepFraction);
+ }
+ }
+}
+
+
+
+void ClothingActorImpl::updateConstrainPositions_LocksPhysX()
+{
+ PX_PROFILE_ZONE("ClothingActorImpl::updateConstrainPositions", GetInternalApexSDK()->getContextId());
+
+ if (mClothingSimulation == NULL || mClothingSimulation->skinnedPhysicsPositions == NULL)
+ {
+ return;
+ }
+
+ const bool skinningDirty = isSkinningDirty();
+ mClothingSimulation->updateConstrainPositions(skinningDirty);
+
+ bBoneMatricesChanged = 0;
+ bGlobalPoseChanged = 0;
+}
+
+
+
+void ClothingActorImpl::applyCollision_LocksPhysX()
+{
+ PX_PROFILE_ZONE("ClothingActorImpl::applyCollision", GetInternalApexSDK()->getContextId());
+
+ if (mClothingSimulation != NULL)
+ {
+ mClothingSimulation->applyCollision();
+ }
+}
+
+
+
+ClothingMaterialLibraryParametersNS::ClothingMaterial_Type* ClothingActorImpl::getCurrentClothingMaterial() const
+{
+ const ClothingAssetParameters* clothingAsset = static_cast<const ClothingAssetParameters*>(mAsset->getAssetNvParameterized());
+ const ClothingMaterialLibraryParameters* materialLib = static_cast<const ClothingMaterialLibraryParameters*>(clothingAsset->materialLibrary);
+ if (materialLib == NULL)
+ {
+ APEX_DEBUG_WARNING("No Clothing Material Library present in asset");
+ return NULL;
+ }
+
+ PX_ASSERT(materialLib->materials.buf != NULL);
+ PX_ASSERT(materialLib->materials.arraySizes[0] > 0);
+
+ uint32_t index = mActorDesc->clothingMaterialIndex;
+ if (index >= (uint32_t)materialLib->materials.arraySizes[0])
+ {
+ APEX_INVALID_PARAMETER("Index must be smaller than materials array: %d < %d", index, materialLib->materials.arraySizes[0]);
+
+ PX_ASSERT(nvidia::strcmp(clothingAsset->className(), ClothingAssetParameters::staticClassName()) == 0);
+ index = clothingAsset->materialIndex;
+ mActorDesc->clothingMaterialIndex = index;
+ }
+
+ return &materialLib->materials.buf[index];
+}
+
+
+bool ClothingActorImpl::clothingMaterialsEqual(ClothingMaterialLibraryParametersNS::ClothingMaterial_Type& a, ClothingMaterialLibraryParametersNS::ClothingMaterial_Type& b)
+{
+ // update this compare function in case the struct has changed
+ // PH: Let's hope that we bump the version number when modifying the materials in the .pl
+ PX_COMPILE_TIME_ASSERT(ClothingMaterialLibraryParameters::ClassVersion == 14);
+
+ return
+ a.verticalStretchingStiffness == b.verticalStretchingStiffness &&
+ a.horizontalStretchingStiffness == b.horizontalStretchingStiffness &&
+ a.bendingStiffness == b.bendingStiffness &&
+ a.shearingStiffness == b.shearingStiffness &&
+ a.tetherStiffness == b.tetherStiffness &&
+ a.tetherLimit == b.tetherLimit &&
+ a.orthoBending == b.orthoBending &&
+ a.verticalStiffnessScaling.compressionRange == b.verticalStiffnessScaling.compressionRange &&
+ a.verticalStiffnessScaling.stretchRange == b.verticalStiffnessScaling.stretchRange &&
+ a.verticalStiffnessScaling.scale == b.verticalStiffnessScaling.scale &&
+ a.horizontalStiffnessScaling.compressionRange == b.horizontalStiffnessScaling.compressionRange &&
+ a.horizontalStiffnessScaling.stretchRange == b.horizontalStiffnessScaling.stretchRange &&
+ a.horizontalStiffnessScaling.scale == b.horizontalStiffnessScaling.scale &&
+ a.bendingStiffnessScaling.compressionRange == b.bendingStiffnessScaling.compressionRange &&
+ a.bendingStiffnessScaling.stretchRange == b.bendingStiffnessScaling.stretchRange &&
+ a.bendingStiffnessScaling.scale == b.bendingStiffnessScaling.scale &&
+ a.shearingStiffnessScaling.compressionRange == b.shearingStiffnessScaling.compressionRange &&
+ a.shearingStiffnessScaling.stretchRange == b.shearingStiffnessScaling.stretchRange &&
+ a.shearingStiffnessScaling.scale == b.shearingStiffnessScaling.scale &&
+ a.damping == b.damping &&
+ a.stiffnessFrequency == b.stiffnessFrequency &&
+ a.drag == b.drag &&
+ a.comDamping == b.comDamping &&
+ a.friction == b.friction &&
+ a.massScale == b.massScale &&
+ a.solverIterations == b.solverIterations &&
+ a.solverFrequency == b.solverFrequency &&
+ a.gravityScale == b.gravityScale &&
+ a.inertiaScale == b.inertiaScale &&
+ a.hardStretchLimitation == b.hardStretchLimitation &&
+ a.maxDistanceBias == b.maxDistanceBias &&
+ a.hierarchicalSolverIterations == b.hierarchicalSolverIterations &&
+ a.selfcollisionThickness == b.selfcollisionThickness &&
+ a.selfcollisionSquashScale == b.selfcollisionSquashScale &&
+ a.selfcollisionStiffness == b.selfcollisionStiffness;
+}
+
+
+
+void ClothingActorImpl::applyClothingMaterial_LocksPhysX()
+{
+ PX_PROFILE_ZONE("ClothingActorImpl::applyClothingMaterial", GetInternalApexSDK()->getContextId());
+
+ ClothingMaterialLibraryParametersNS::ClothingMaterial_Type* currentMaterial = getCurrentClothingMaterial();
+ bool clothingMaterialDirty = !clothingMaterialsEqual(*currentMaterial, mClothingMaterial) || (bInternalScaledGravityChanged == 1);
+
+ if (mClothingSimulation != NULL && clothingMaterialDirty)
+ {
+ if (mClothingSimulation->applyClothingMaterial(currentMaterial, mInternalScaledGravity))
+ {
+ mClothingMaterial = *currentMaterial;
+ bInternalScaledGravityChanged = 0;
+ }
+ }
+}
+
+
+
+void ClothingActorImpl::tickAsynch_NoPhysX()
+{
+ if (mClothingSimulation != NULL)
+ {
+ if (shouldComputeRenderData() /*&& bInternalFrozen == 0*/)
+ {
+ // perform mesh-to-mesh skinning if using skin cloth
+ if (mInternalFlags.ParallelCpuSkinning)
+ {
+ mData.skinToAnimation_NoPhysX(false);
+ }
+ }
+ }
+}
+
+
+
+bool ClothingActorImpl::needsManualSubstepping()
+{
+ return mClothingSimulation != NULL && mClothingSimulation->needsManualSubstepping();
+}
+
+
+#ifndef WITHOUT_PVD
+void ClothingActorImpl::initPvdInstances(pvdsdk::PvdDataStream& pvdStream)
+{
+ ApexResourceInterface* pvdInstance = static_cast<ApexResourceInterface*>(mActorProxy);
+
+ // Actor Params
+ pvdStream.createInstance(pvdsdk::NamespacedName(APEX_PVD_NAMESPACE, "ClothingActorParam"), mActorDesc);
+ pvdStream.setPropertyValue(pvdInstance, "ActorParams", pvdsdk::DataRef<const uint8_t>((const uint8_t*)&mActorDesc, sizeof(ClothingActorParam*)), pvdsdk::getPvdNamespacedNameForType<pvdsdk::ObjectRef>());
+
+ pvdsdk::ApexPvdClient* client = GetInternalApexSDK()->getApexPvdClient();
+ PX_ASSERT(client != NULL);
+ client->updatePvd(mActorDesc, *mActorDesc);
+}
+
+
+void ClothingActorImpl::destroyPvdInstances()
+{
+ pvdsdk::ApexPvdClient* client = GetInternalApexSDK()->getApexPvdClient();
+ if (client != NULL)
+ {
+ if (client->isConnected() && client->getPxPvd().getInstrumentationFlags() & PxPvdInstrumentationFlag::eDEBUG)
+ {
+ pvdsdk::PvdDataStream* pvdStream = client->getDataStream();
+ {
+ if (pvdStream != NULL)
+ {
+ client->updatePvd(mActorDesc, *mActorDesc, pvdsdk::PvdAction::DESTROY);
+ pvdStream->destroyInstance(mActorDesc);
+ // the actor instance is destroyed in ResourceList::remove
+ }
+ }
+ }
+ }
+}
+
+
+void ClothingActorImpl::updatePvd()
+{
+ // update pvd
+ pvdsdk::ApexPvdClient* client = GetInternalApexSDK()->getApexPvdClient();
+ if (client != NULL)
+ {
+ if (client->isConnected() && client->getPxPvd().getInstrumentationFlags() & PxPvdInstrumentationFlag::eDEBUG)
+ {
+ pvdsdk::PvdDataStream* pvdStream = client->getDataStream();
+ pvdsdk::PvdUserRenderer* pvdRenderer = client->getUserRender();
+
+ if (pvdStream != NULL && pvdRenderer != NULL)
+ {
+ ApexResourceInterface* pvdInstance = static_cast<ApexResourceInterface*>(mActorProxy);
+
+ client->updatePvd(mActorDesc, *mActorDesc);
+
+ if (mClothingSimulation)
+ {
+ mClothingSimulation->updatePvd(*pvdStream, *pvdRenderer, pvdInstance, bInternalLocalSpaceSim == 1);
+ }
+ }
+ }
+ }
+}
+#endif
+
+
+void ClothingActorImpl::visualize()
+{
+#ifdef WITHOUT_DEBUG_VISUALIZE
+#else
+
+ using RENDER_DEBUG::DebugColors;
+ using RENDER_DEBUG::DebugRenderState;
+
+ if (mClothingScene == NULL || mClothingScene->mRenderDebug == NULL)
+ {
+ return;
+ }
+ if ( !mEnableDebugVisualization ) return;
+
+ RenderDebugInterface& renderDebug = *mClothingScene->mRenderDebug;
+ const physx::PxMat44& savedPose = *RENDER_DEBUG_IFACE(&renderDebug)->getPoseTyped();
+ RENDER_DEBUG_IFACE(&renderDebug)->setIdentityPose();
+
+ const float visualizationScale = mClothingScene->mDebugRenderParams->Scale;
+
+ PX_ASSERT(mActorDesc != NULL);
+
+ if (visualizationScale == 0.0f || !mActorDesc->flags.Visualize)
+ {
+ return;
+ }
+
+ if (mClothingScene->mClothingDebugRenderParams->GlobalPose)
+ {
+#if 1
+ // PH: This uses only lines, not triangles, hence wider engine support
+ const uint32_t colorRed = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Red);
+ const uint32_t colorGreen = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Green);
+ const uint32_t colorBlue = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Blue);
+ PxMat44 absPose(mInternalGlobalPose);
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorRed);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(absPose.getPosition(), absPose.getPosition() + absPose.column0.getXYZ() * visualizationScale);
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorGreen);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(absPose.getPosition(), absPose.getPosition() + absPose.column1.getXYZ() * visualizationScale);
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorBlue);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(absPose.getPosition(), absPose.getPosition() + absPose.column2.getXYZ() * visualizationScale);
+#else
+ // PH: But this one looks a bit nicer
+ RENDER_DEBUG_IFACE(&renderDebug)->debugAxes(mInternalGlobalPose, visualizationScale);
+#endif
+ }
+
+ // transform debug rendering to global space
+ if (bInternalLocalSpaceSim == 1 && !mClothingScene->mClothingDebugRenderParams->ShowInLocalSpace)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->setPose(mInternalGlobalPose);
+ }
+
+ const uint32_t colorRed = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Red);
+ const uint32_t colorBlue = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Blue);
+ const uint32_t colorWhite = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::White);
+
+ renderDataLock();
+
+#if 0
+ static bool turnOn = true;
+ if (turnOn)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->pushRenderState();
+
+ RenderMeshAssetIntl* rma = mAsset->getGraphicalMesh(mCurrentGraphicalLodId);
+ if (false && mActorDesc->morphDisplacements.arraySizes[0] > 0 && rma != NULL)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorBlue);
+
+ uint32_t* morphMap = mAsset->getMorphMapping(mCurrentGraphicalLodId);
+
+ for (uint32_t s = 0; s < rma->getSubmeshCount(); s++)
+ {
+ const uint32_t numVertices = rma->getSubmesh(s).getVertexCount(0);
+ const VertexFormat& format = rma->getSubmesh(s).getVertexBuffer().getFormat();
+ const uint32_t positionIndex = format.getBufferIndexFromID(format.getSemanticID(RenderVertexSemantic::POSITION));
+ if (format.getBufferFormat(positionIndex) == RenderDataFormat::FLOAT3)
+ {
+ PxVec3* positions = (PxVec3*)rma->getSubmesh(s).getVertexBuffer().getBuffer(positionIndex);
+ for (uint32_t v = 0; v < numVertices; v++)
+ {
+ PxVec3 from = positions[v];
+ PX_ASSERT((int)morphMap[v] < mActorDesc->morphDisplacements.arraySizes[0]);
+ PxVec3 to = from + mActorDesc->morphDisplacements.buf[morphMap[v]];
+
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(from, to);
+ }
+ }
+ }
+
+ }
+
+ if (mActorDesc->morphPhysicalMeshNewPositions.buf != NULL)
+ {
+ mClothingScene-> mRENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorRed);
+
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ uint32_t offset = mAsset->getPhysicalMeshOffset(mAsset->getPhysicalMeshID(mCurrentGraphicalLodId));
+ PX_ASSERT((int32_t)(offset + physicalMesh->numVertices) <= mActorDesc->morphPhysicalMeshNewPositions.arraySizes[0]);
+ for (uint32_t p = 0; p < physicalMesh->numVertices; p++)
+ {
+ const PxVec3 renderDisp(0.0f, 0.0f, 0.001f);
+ PxVec3 from = physicalMesh->vertices.buf[p] + renderDisp;
+ PxVec3 to = mActorDesc->morphPhysicalMeshNewPositions.buf[offset + p] + renderDisp;
+
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(from, to);
+ }
+ }
+
+ RENDER_DEBUG_IFACE(&renderDebug)->popRenderState();
+ }
+#endif
+
+ // save the rendering state.
+ RENDER_DEBUG_IFACE(&renderDebug)->pushRenderState();
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorRed);
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentState(DebugRenderState::SolidShaded);
+
+
+ // visualize velocities
+ const float velocityScale = mClothingScene->mClothingDebugRenderParams->Velocities * visualizationScale;
+ if (velocityScale > 0.0f && mClothingSimulation != NULL)
+ {
+ PxVec3* velocities = (PxVec3*)GetInternalApexSDK()->getTempMemory(sizeof(PxVec3) * mClothingSimulation->sdkNumDeformableVertices);
+ if (velocities != NULL)
+ {
+ mClothingSimulation->getVelocities(velocities);
+
+ const bool useVelocityClamp = mActorDesc->useVelocityClamping;
+ PxBounds3 velocityClamp(mActorDesc->vertexVelocityClamp);
+
+ for (uint32_t i = 0; i < mClothingSimulation->sdkNumDeformableVertices; i++)
+ {
+ const PxVec3 pos = mClothingSimulation->sdkWritebackPosition[i];
+ const PxVec3 vel = velocities[i];
+ bool clamped = false;
+ if (useVelocityClamp)
+ {
+ clamped = (vel.x < velocityClamp.minimum.x) || (vel.x > velocityClamp.maximum.x);
+ clamped |= (vel.y < velocityClamp.minimum.y) || (vel.y > velocityClamp.maximum.y);
+ clamped |= (vel.z < velocityClamp.minimum.z) || (vel.z > velocityClamp.maximum.z);
+ }
+ const PxVec3 dest = pos + vel * velocityScale;
+ RENDER_DEBUG_IFACE(&renderDebug)->debugGradientLine(pos, dest, clamped ? colorRed : colorBlue, colorWhite);
+ }
+
+ GetInternalApexSDK()->releaseTempMemory(velocities);
+ }
+ }
+
+ // visualize Skeleton
+ const bool skeleton = mClothingScene->mClothingDebugRenderParams->Skeleton;
+ const float boneFramesScale = mClothingScene->mClothingDebugRenderParams->BoneFrames;
+ const float boneNamesScale = mClothingScene->mClothingDebugRenderParams->BoneNames;
+ if (skeleton || boneFramesScale + boneNamesScale > 0.0f)
+ {
+ const PxMat44* matrices = mData.mInternalBoneMatricesCur;
+
+ if (matrices != NULL)
+ {
+ mAsset->visualizeBones(renderDebug, matrices, skeleton, boneFramesScale, boneNamesScale);
+ }
+ }
+
+ // visualization of the physical mesh
+ if (mClothingScene->mClothingDebugRenderParams->Backstop)
+ {
+ visualizeBackstop(renderDebug);
+ }
+
+ const float backstopPrecise = mClothingScene->mClothingDebugRenderParams->BackstopPrecise;
+ if (backstopPrecise > 0.0f)
+ {
+ visualizeBackstopPrecise(renderDebug, backstopPrecise);
+ }
+
+ const float skinnedPositionsScale = mClothingScene->mClothingDebugRenderParams->SkinnedPositions;
+ const bool drawMaxDistance = mClothingScene->mClothingDebugRenderParams->MaxDistance;
+ const bool drawMaxDistanceIn = mClothingScene->mClothingDebugRenderParams->MaxDistanceInwards;
+ if (skinnedPositionsScale > 0.0f || drawMaxDistance || drawMaxDistanceIn)
+ {
+ visualizeSkinnedPositions(renderDebug, skinnedPositionsScale, drawMaxDistance, drawMaxDistanceIn);
+ }
+
+ // visualize vertex - bone connections for skinning
+ for (uint32_t g = 0; g < mGraphicalMeshes.size(); g++)
+ {
+ if (!mGraphicalMeshes[g].active)
+ {
+ continue;
+ }
+
+ //const ClothingGraphicalLodParameters* graphicalLod = mAsset->getGraphicalLod(g);
+ ClothingGraphicalMeshAssetWrapper meshAsset(mAsset->getRenderMeshAsset(g));
+
+ const float graphicalVertexBonesScale = mClothingScene->mClothingDebugRenderParams->GraphicalVertexBones;
+ if (graphicalVertexBonesScale > 0.0f)
+ {
+ for (uint32_t submeshIndex = 0; submeshIndex < meshAsset.getSubmeshCount(); submeshIndex++)
+ {
+ RenderDataFormat::Enum outFormat;
+ const PxVec3* positions = (const PxVec3*)meshAsset.getVertexBuffer(submeshIndex, RenderVertexSemantic::POSITION, outFormat);
+ PX_ASSERT(outFormat == RenderDataFormat::FLOAT3);
+ const uint16_t* boneIndices = (const uint16_t*)meshAsset.getVertexBuffer(submeshIndex, RenderVertexSemantic::BONE_INDEX, outFormat);
+ const float* boneWeights = (const float*)meshAsset.getVertexBuffer(submeshIndex, RenderVertexSemantic::BONE_WEIGHT, outFormat);
+ visualizeBoneConnections(renderDebug, positions, boneIndices, boneWeights,
+ meshAsset.getNumBonesPerVertex(submeshIndex), meshAsset.getNumVertices(submeshIndex));
+ }
+ }
+
+ const float physicalVertexBonesScale = mClothingScene->mClothingDebugRenderParams->PhysicalVertexBones;
+ if (physicalVertexBonesScale > 0.0f)
+ {
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(g);
+ visualizeBoneConnections(renderDebug, physicalMesh->vertices.buf, physicalMesh->boneIndices.buf,
+ physicalMesh->boneWeights.buf, physicalMesh->numBonesPerVertex, physicalMesh->numVertices);
+ }
+ }
+
+ if (mClothingSimulation != NULL)
+ {
+ // visualization of the physical mesh
+ const float physicsMeshWireScale = mClothingScene->mClothingDebugRenderParams->PhysicsMeshWire;
+ const float physicsMeshSolidScale = mClothingScene->mClothingDebugRenderParams->PhysicsMeshSolid;
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+
+ const float physicsMeshNormalScale = mClothingScene->mClothingDebugRenderParams->PhysicsMeshNormals;
+ if (physicsMeshNormalScale > 0.0f)
+ {
+ const PxVec3* positions = mClothingSimulation->sdkWritebackPosition;
+ const PxVec3* normals = mClothingSimulation->sdkWritebackNormal;
+
+ RENDER_DEBUG_IFACE(&renderDebug)->pushRenderState();
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Blue));
+
+ const uint32_t numVertices = mClothingSimulation->sdkNumDeformableVertices;
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ const PxVec3 dest = positions[i] + normals[i] * physicsMeshNormalScale;
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(positions[i], dest);
+ }
+
+ RENDER_DEBUG_IFACE(&renderDebug)->popRenderState();
+ }
+
+ if (mClothingScene->mClothingDebugRenderParams->PhysicsMeshIndices)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->pushRenderState();
+ const PxVec3 upAxis = -mInternalScaledGravity.getNormalized();
+ const float avgEdgeLength = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId)->averageEdgeLength;
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentTextScale(avgEdgeLength);
+ RENDER_DEBUG_IFACE(&renderDebug)->addToCurrentState(RENDER_DEBUG::DebugRenderState::CameraFacing);
+
+ const uint32_t numVertices = mClothingSimulation->sdkNumDeformableVertices;
+ const PxVec3* const positions = mClothingSimulation->sdkWritebackPosition;
+ const PxVec3* const normals = mClothingSimulation->sdkWritebackNormal;
+ for (uint32_t i = 0; i < numVertices; ++i)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(0xFFFFFFFF);
+ const PxVec3 pos = positions[i];
+ const PxVec3 normal = normals[i].getNormalized();
+ PxVec3 rightAxis = upAxis.cross(normal).getNormalized();
+ PxVec3 realUpAxis = normal.cross(rightAxis).getNormalized();
+
+ RENDER_DEBUG_IFACE(&renderDebug)->debugText(pos + normal * (avgEdgeLength * 0.1f), "%d", i);
+ }
+ RENDER_DEBUG_IFACE(&renderDebug)->popRenderState();
+ }
+
+ if (physicsMeshWireScale > 0.0f || physicsMeshSolidScale > 0.0f)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->pushRenderState();
+ RENDER_DEBUG_IFACE(&renderDebug)->setIdentityPose();
+ const float actorScale = mActorDesc->actorScale;
+
+ const float linearScale = (mInternalMaxDistanceScale.Multipliable ? mInternalMaxDistanceScale.Scale : 1.0f) * actorScale;
+ const float absoluteScale = mInternalMaxDistanceScale.Multipliable ? 0.0f : (physicalMesh->maximumMaxDistance * (1.0f - mInternalMaxDistanceScale.Scale));
+
+ const float reduceMaxDistance = mMaxDistReduction + absoluteScale;
+
+ const uint32_t numIndices = mClothingSimulation->sdkNumDeformableIndices;
+ const uint32_t* const indices = physicalMesh->indices.buf;
+ const PxVec3* const positions = mClothingSimulation->sdkWritebackPosition;
+ const PxVec3* const skinnedPositions = mClothingSimulation->skinnedPhysicsPositions;
+
+ const ClothingPhysicalMeshParametersNS::ConstrainCoefficient_Type* const PX_RESTRICT coeffs = physicalMesh->constrainCoefficients.buf;
+
+ RENDER_DEBUG_IFACE(&renderDebug)->removeFromCurrentState(DebugRenderState::SolidWireShaded);
+
+ union BlendColors
+ {
+ unsigned char chars[4];
+ uint32_t color;
+ } blendColors[3];
+
+ blendColors[0].color = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Yellow);
+ blendColors[1].color = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Gold);
+ blendColors[2].color = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Red);
+ const uint32_t lightBlue = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::LightBlue);
+ const uint32_t darkBlue = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Blue);
+
+ if (bInternalFrozen)
+ {
+ blendColors[0].color = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Purple);
+ blendColors[1].color = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::DarkPurple);
+ }
+ else if (bInternalTeleportDue == ClothingTeleportMode::TeleportAndReset)
+ {
+ blendColors[0].color = darkBlue;
+ blendColors[1].color = darkBlue;
+ blendColors[2].color = darkBlue;
+ }
+ else if (bInternalTeleportDue == ClothingTeleportMode::Teleport)
+ {
+ blendColors[0].color = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Red);
+ blendColors[1].color = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Red);
+ blendColors[2].color = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Red);
+ }
+
+ const uint8_t sides[4][3] = {{2, 1, 0}, {0, 1, 3}, {1, 2, 3}, {2, 0, 3}};
+
+ const uint32_t numIndicesPerPrim = physicalMesh->isTetrahedralMesh ? 4u : 3u;
+ const float numindicesPerPrimF = (float)numIndicesPerPrim;
+
+ for (uint32_t i = 0; i < numIndices; i += numIndicesPerPrim)
+ {
+ PxVec3 vecs[8];
+ PxVec3 center(0.0f, 0.0f, 0.0f);
+ uint32_t colors[8];
+ for (uint32_t j = 0; j < numIndicesPerPrim; j++)
+ {
+ const uint32_t index = indices[i + j];
+ vecs[j] = positions[index];
+ center += vecs[j];
+ const float maxDistance = (coeffs[index].maxDistance - reduceMaxDistance) * linearScale;
+ if (maxDistance <= 0.0f)
+ {
+ colors[j ] = lightBlue;
+ colors[j + numIndicesPerPrim] = darkBlue;
+ }
+ else
+ {
+ const float distance = (positions[index] - skinnedPositions[index]).magnitude() / maxDistance;
+
+ union
+ {
+ unsigned char tempChars[8];
+ uint32_t tempColor[2];
+ };
+
+ if (distance > 1.0f)
+ {
+ colors[j ] = blendColors[2].color;
+ colors[j + numIndicesPerPrim] = blendColors[2].color;
+ }
+ else
+ {
+ for (uint32_t k = 0; k < 4; k++)
+ {
+ tempChars[k ] = (unsigned char)(blendColors[2].chars[k] * distance + blendColors[0].chars[k] * (1.0f - distance));
+ tempChars[k + 4] = (unsigned char)(blendColors[2].chars[k] * distance + blendColors[1].chars[k] * (1.0f - distance));
+ }
+ colors[j ] = tempColor[0];
+ colors[j + numIndicesPerPrim] = tempColor[1];
+ }
+ }
+ }
+
+ center /= numindicesPerPrimF;
+
+ for (uint32_t j = 0; j < numIndicesPerPrim; j++)
+ {
+ vecs[j + numIndicesPerPrim] = vecs[j] * physicsMeshSolidScale + center * (1.0f - physicsMeshSolidScale);
+ vecs[j] = vecs[j] * physicsMeshWireScale + center * (1.0f - physicsMeshWireScale);
+ }
+
+ if (physicsMeshWireScale > 0.0f)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->removeFromCurrentState(DebugRenderState::SolidShaded);
+
+ if (numIndicesPerPrim == 3)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->debugGradientLine(vecs[0], vecs[1], colors[0], colors[1]);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugGradientLine(vecs[1], vecs[2], colors[1], colors[2]);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugGradientLine(vecs[2], vecs[0], colors[2], colors[0]);
+ }
+ else
+ {
+ for (uint32_t j = 0; j < 4; j++)
+ {
+ uint32_t triIndices[3] = { sides[j][0], sides[j][1], sides[j][2] };
+ RENDER_DEBUG_IFACE(&renderDebug)->debugGradientLine(vecs[triIndices[0]], vecs[triIndices[2]], colors[triIndices[0]], colors[triIndices[2]]);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugGradientLine(vecs[triIndices[2]], vecs[triIndices[1]], colors[triIndices[2]], colors[triIndices[1]]);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugGradientLine(vecs[triIndices[1]], vecs[triIndices[0]], colors[triIndices[1]], colors[triIndices[0]]);
+ }
+ }
+ }
+ if (physicsMeshSolidScale > 0.0f)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->addToCurrentState(DebugRenderState::SolidShaded);
+
+ if (numIndicesPerPrim == 3)
+ {
+ // culling is active for these, so we need both of them
+ RENDER_DEBUG_IFACE(&renderDebug)->debugGradientTri(vecs[3], vecs[4], vecs[5], colors[3], colors[4], colors[5]);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugGradientTri(vecs[3], vecs[5], vecs[4], colors[3], colors[5], colors[4]);
+ }
+ else
+ {
+ for (uint32_t j = 0; j < 4; j++)
+ {
+ uint32_t triIndices[3] = { (uint32_t)sides[j][0] + 4, (uint32_t)sides[j][1] + 4, (uint32_t)sides[j][2] + 4 };
+ RENDER_DEBUG_IFACE(&renderDebug)->debugGradientTri(
+ vecs[triIndices[0]], vecs[triIndices[2]], vecs[triIndices[1]],
+ colors[triIndices[0]], colors[triIndices[2]], colors[triIndices[1]]);
+ }
+ }
+ }
+ }
+ RENDER_DEBUG_IFACE(&renderDebug)->popRenderState();
+ }
+
+ // self collision visualization
+ if ( (mClothingScene->mClothingDebugRenderParams->SelfCollision || mClothingScene->mClothingDebugRenderParams->SelfCollisionWire)
+ && (!mAsset->getModuleClothing()->useSparseSelfCollision() || mClothingSimulation->getType() != SimulationType::CLOTH3x))
+ {
+ const PxVec3* const positions = mClothingSimulation->sdkWritebackPosition;
+ ClothingMaterialLibraryParametersNS::ClothingMaterial_Type* material = getCurrentClothingMaterial();
+
+ if (material->selfcollisionThickness > 0.0f && material->selfcollisionStiffness > 0.0f)
+ {
+ visualizeSpheres(renderDebug, positions, mClothingSimulation->sdkNumDeformableVertices, 0.5f*material->selfcollisionThickness*mActorDesc->actorScale, colorRed, mClothingScene->mClothingDebugRenderParams->SelfCollisionWire);
+ }
+ }
+ /*
+ // inter collision visualization
+ if ( (mClothingScene->mClothingDebugRenderParams->InterCollision || mClothingScene->mClothingDebugRenderParams->InterCollisionWire)
+ && mClothingSimulation->getType() == SimulationType::CLOTH3x)
+ {
+ const PxVec3* const positions = mClothingSimulation->sdkWritebackPosition;
+ float distance = mAsset->getModuleClothing()->getInterCollisionDistance();
+ float stiffness = mAsset->getModuleClothing()->getInterCollisionStiffness();
+ if (distance > 0.0f && stiffness > 0.0f)
+ {
+ visualizeSpheres(renderDebug, positions, mClothingSimulation->sdkNumDeformableVertices, 0.5f*distance, colorBlue, mClothingScene->mClothingDebugRenderParams->InterCollisionWire);
+ }
+ }
+ */
+ // visualization of the graphical mesh
+ for (uint32_t g = 0; g < mGraphicalMeshes.size(); g++)
+ {
+ if (!mGraphicalMeshes[g].active)
+ {
+ continue;
+ }
+
+ const ClothingGraphicalLodParameters* graphicalLod = mAsset->getGraphicalLod(g);
+
+ if (graphicalLod != NULL && (graphicalLod->skinClothMapB.buf != NULL || graphicalLod->skinClothMap.buf != NULL))
+ {
+ AbstractMeshDescription pcm;
+ pcm.numVertices = mClothingSimulation->sdkNumDeformableVertices;
+ pcm.numIndices = mClothingSimulation->sdkNumDeformableIndices;
+ pcm.pPosition = mClothingSimulation->sdkWritebackPosition;
+ pcm.pNormal = mClothingSimulation->sdkWritebackNormal;
+ pcm.pIndices = physicalMesh->indices.buf;
+ pcm.avgEdgeLength = graphicalLod->skinClothMapThickness;
+
+ if (mClothingScene->mClothingDebugRenderParams->SkinMapAll)
+ {
+ mAsset->visualizeSkinCloth(renderDebug, pcm, graphicalLod->skinClothMapB.buf != NULL, mActorDesc->actorScale);
+ }
+ if (mClothingScene->mClothingDebugRenderParams->SkinMapBad)
+ {
+ mAsset->visualizeSkinClothMap(renderDebug, pcm,
+ graphicalLod->skinClothMapB.buf, (uint32_t)graphicalLod->skinClothMapB.arraySizes[0],
+ graphicalLod->skinClothMap.buf, (uint32_t)graphicalLod->skinClothMap.arraySizes[0], mActorDesc->actorScale, true, false);
+ }
+ if (mClothingScene->mClothingDebugRenderParams->SkinMapActual)
+ {
+ mAsset->visualizeSkinClothMap(renderDebug, pcm,
+ graphicalLod->skinClothMapB.buf, (uint32_t)graphicalLod->skinClothMapB.arraySizes[0],
+ graphicalLod->skinClothMap.buf, (uint32_t)graphicalLod->skinClothMap.arraySizes[0], mActorDesc->actorScale, false, false);
+ }
+ if (mClothingScene->mClothingDebugRenderParams->SkinMapInvalidBary)
+ {
+ mAsset->visualizeSkinClothMap(renderDebug, pcm,
+ graphicalLod->skinClothMapB.buf, (uint32_t)graphicalLod->skinClothMapB.arraySizes[0],
+ graphicalLod->skinClothMap.buf, (uint32_t)graphicalLod->skinClothMap.arraySizes[0], mActorDesc->actorScale, false, true);
+ }
+
+ }
+
+ RENDER_DEBUG_IFACE(&renderDebug)->pushRenderState();
+
+ RENDER_DEBUG_IFACE(&renderDebug)->addToCurrentState(RENDER_DEBUG::DebugRenderState::CenterText);
+ RENDER_DEBUG_IFACE(&renderDebug)->addToCurrentState(RENDER_DEBUG::DebugRenderState::CameraFacing);
+
+ // Probably should be removed
+ if (graphicalLod != NULL && mClothingScene->mClothingDebugRenderParams->RecomputeSubmeshes)
+ {
+ const RenderMeshAsset* rma = mAsset->getRenderMeshAsset(mCurrentGraphicalLodId);
+
+ RENDER_DEBUG_IFACE(&renderDebug)->addToCurrentState(DebugRenderState::SolidShaded);
+
+ uint32_t submeshVertexOffset = 0;
+ for (uint32_t s = 0; s < rma->getSubmeshCount(); s++)
+ {
+ const RenderSubmesh& submesh = rma->getSubmesh(s);
+ const uint32_t vertexCount = submesh.getVertexCount(0);
+ const uint32_t* indices = submesh.getIndexBuffer(0);
+ const uint32_t numIndices = submesh.getIndexCount(0);
+
+ if(mGraphicalMeshes[mCurrentGraphicalLodId].renderProxy == NULL)
+ continue;
+ const PxVec3* positions = mGraphicalMeshes[mCurrentGraphicalLodId].renderProxy->renderingDataPosition + submeshVertexOffset;
+
+
+ uint32_t maxForColor = (uint32_t)graphicalLod->physicsMeshPartitioning.arraySizes[0] + 2;
+ {
+ const uint8_t colorPart = (uint8_t)((255 / maxForColor) & 0xff);
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(uint32_t(colorPart | colorPart << 8 | colorPart << 16));
+ }
+
+ for (uint32_t i = 0; i < numIndices; i += 3)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(positions[indices[i]], positions[indices[i + 1]], positions[indices[i + 2]]);
+ }
+ const uint8_t colorPart = (uint8_t)((2 * 255 / maxForColor) & 0xff);
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(uint32_t(colorPart | colorPart << 8 | colorPart << 16));
+
+ submeshVertexOffset += vertexCount;
+ }
+ }
+ if (graphicalLod != NULL && mClothingScene->mClothingDebugRenderParams->RecomputeVertices)
+ {
+ uint32_t color1 = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Orange);
+ uint32_t color2 = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Purple);
+
+ const PxVec3 upAxis = -mInternalScaledGravity.getNormalized();
+ PX_UNUSED(upAxis);
+
+ const float avgEdgeLength = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId)->averageEdgeLength;
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentTextScale(0.2f * avgEdgeLength);
+
+ const RenderMeshAsset* rma = mAsset->getRenderMeshAsset(mCurrentGraphicalLodId);
+
+ uint32_t submeshVertexOffset = 0;
+ for (uint32_t s = 0; s < rma->getSubmeshCount(); s++)
+ {
+ const RenderSubmesh& submesh = rma->getSubmesh(s);
+ const uint32_t vertexCount = submesh.getVertexCount(0);
+
+ ClothingRenderProxyImpl* renderProxy = mGraphicalMeshes[mCurrentGraphicalLodId].renderProxy;
+
+ if (renderProxy == NULL)
+ {
+ renderProxy = mRenderProxyReady;
+ }
+
+ if (renderProxy == NULL)
+ {
+ renderProxy = mRenderProxyURR;
+ }
+
+ if(renderProxy == NULL)
+ continue;
+
+ const PxVec3* positions = renderProxy->renderingDataPosition + submeshVertexOffset;
+
+ uint32_t simulatedVertices = graphicalLod->physicsMeshPartitioning.buf[s].numSimulatedVertices;
+ uint32_t simulatedVerticesAdditional = graphicalLod->physicsMeshPartitioning.buf[s].numSimulatedVerticesAdditional;
+
+ for (uint32_t i = 0; i < simulatedVerticesAdditional && i < vertexCount; i++)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(i < simulatedVertices ? color1 : color2);
+ const PxVec3 pos = positions[i];
+
+ RENDER_DEBUG_IFACE(&renderDebug)->debugText(pos, "%d", submeshVertexOffset + i);
+ }
+
+ submeshVertexOffset += vertexCount;
+ }
+ }
+
+ RENDER_DEBUG_IFACE(&renderDebug)->popRenderState();
+ }
+ }
+
+ if (mClothingSimulation != NULL)
+ {
+ mClothingSimulation->visualize(renderDebug, *mClothingScene->mClothingDebugRenderParams);
+ }
+
+ // restore the rendering state.
+ RENDER_DEBUG_IFACE(&renderDebug)->popRenderState();
+
+ const float windScale = mClothingScene->mClothingDebugRenderParams->Wind;
+ if (mClothingSimulation != NULL && windScale != 0.0f)
+ {
+ //PX_ASSERT(mWindDebugRendering.size() == mClothingSimulation->sdkNumDeformableVertices);
+ const uint32_t numVertices = PxMin(mClothingSimulation->sdkNumDeformableVertices, mWindDebugRendering.size());
+ const PxVec3* positions = mClothingSimulation->sdkWritebackPosition;
+ const uint32_t red = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Red);
+ const uint32_t white = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::White);
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->debugGradientLine(positions[i], positions[i] + mWindDebugRendering[i] * windScale, red, white);
+ }
+ }
+
+ // fetchresults must be completed before Normal/Tangent debug rendering
+ waitForFetchResults();
+
+ // render mesh actor debug rendering
+ for (uint32_t i = 0; i < mGraphicalMeshes.size(); i++)
+ {
+ if (mGraphicalMeshes[i].active && mGraphicalMeshes[i].renderProxy != NULL)
+ {
+ mGraphicalMeshes[i].renderProxy->getRenderMeshActor()->visualize(renderDebug, mClothingScene->mDebugRenderParams);
+ }
+ }
+ if (mRenderProxyReady != NULL)
+ {
+ mRenderProxyReady->getRenderMeshActor()->visualize(renderDebug, mClothingScene->mDebugRenderParams);
+ }
+ else if (mRenderProxyURR != NULL)
+ {
+ mRenderProxyURR->getRenderMeshActor()->visualize(renderDebug, mClothingScene->mDebugRenderParams);
+ }
+
+ // transform debug rendering to global space
+ if (bInternalLocalSpaceSim == 1)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->setPose(PxMat44(PxIdentity));
+ }
+
+
+ if (mClothingScene->mClothingDebugRenderParams->Wind != 0.0f && mActorDesc->windParams.Adaption > 0.0f)
+ {
+ const PxVec3 center = mRenderBounds.getCenter();
+ const float radius = mRenderBounds.getExtents().magnitude() * 0.02f;
+ RENDER_DEBUG_IFACE(&renderDebug)->debugThickRay(center, center + mActorDesc->windParams.Velocity * mClothingScene->mClothingDebugRenderParams->Wind, radius);
+ }
+
+ if (mClothingScene->mClothingDebugRenderParams->SolverMode)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->pushRenderState();
+ RENDER_DEBUG_IFACE(&renderDebug)->addToCurrentState(RENDER_DEBUG::DebugRenderState::CenterText);
+ RENDER_DEBUG_IFACE(&renderDebug)->addToCurrentState(RENDER_DEBUG::DebugRenderState::CameraFacing);
+
+ ApexSimpleString solverString;
+
+ if (mClothingSimulation != NULL)
+ {
+ solverString = (mClothingSimulation->getType() == SimulationType::CLOTH3x) ? "3.x" : "2.x";
+#if APEX_CUDA_SUPPORT
+ ApexSimpleString gpu(mClothingSimulation->isGpuSim() ? " GPU" : " CPU");
+
+ if (mClothingSimulation->getGpuSimMemType() == GpuSimMemType::GLOBAL)
+ {
+ gpu += ApexSimpleString(", Global");
+ }
+ else if(mClothingSimulation->getGpuSimMemType() == GpuSimMemType::MIXED)
+ {
+ gpu += ApexSimpleString(", Mixed");
+ }
+ else if (mClothingSimulation->getGpuSimMemType() == GpuSimMemType::SHARED)
+ {
+ gpu += ApexSimpleString(", Shared");
+ }
+
+ solverString += gpu;
+#endif
+ solverString += ApexSimpleString(", ");
+ ApexSimpleString solverCount;
+ ApexSimpleString::itoa(mClothingSimulation->getNumSolverIterations(), solverCount);
+ solverString += solverCount;
+ }
+ else
+ {
+ solverString = "Disabled";
+ }
+
+ PxVec3 up(0.0f, 1.0f, 0.0f);
+ up = mData.mInternalGlobalPose.transform(up) - mClothingScene->getApexScene()->getGravity();
+ up.normalize();
+
+ const uint32_t white = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::White);
+ const uint32_t gray = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::DarkGray);
+ up = mRenderBounds.getDimensions().multiply(up) * 1.1f;
+ const PxVec3 center = mRenderBounds.getCenter();
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentTextScale(mRenderBounds.getDimensions().magnitude());
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(gray);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugText(center + up * 1.1f, solverString.c_str());
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(white);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugText(center + up * 1.12f, solverString.c_str());
+
+ RENDER_DEBUG_IFACE(&renderDebug)->popRenderState();
+ }
+
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setPose(savedPose);
+ renderDataUnLock();
+#endif
+}
+
+
+
+void ClothingActorImpl::destroy()
+{
+ PX_ASSERT(!isSimulationRunning());
+ if (mActiveCookingTask != NULL)
+ {
+ mActiveCookingTask->abort();
+ PX_ASSERT(mActorDesc->runtimeCooked == NULL);
+ mActiveCookingTask = NULL;
+ }
+
+ ApexActor::destroy(); // remove self from contexts, prevent re-release()
+
+ removePhysX_LocksPhysX();
+
+ if (mData.mInternalBoneMatricesCur != NULL)
+ {
+ PX_FREE(mData.mInternalBoneMatricesCur);
+ mData.mInternalBoneMatricesCur = NULL;
+ }
+ if (mData.mInternalBoneMatricesPrev != NULL)
+ {
+ PX_FREE(mData.mInternalBoneMatricesPrev);
+ mData.mInternalBoneMatricesPrev = NULL;
+ }
+
+ if (mInternalInterpolatedBoneMatrices != NULL)
+ {
+ PX_FREE(mInternalInterpolatedBoneMatrices);
+ mInternalInterpolatedBoneMatrices = NULL;
+ }
+
+ PX_ASSERT(mActorDesc != NULL); // This is a requirement!
+
+
+#ifndef WITHOUT_PVD
+ destroyPvdInstances();
+#endif
+ if (mActorDesc != NULL)
+ {
+ if (mActorDesc->runtimeCooked != NULL)
+ {
+ mAsset->getModuleClothing()->getBackendFactory(mActorDesc->runtimeCooked->className())->releaseCookedInstances(mActorDesc->runtimeCooked);
+ }
+ mActorDesc->destroy();
+ mActorDesc = NULL;
+ }
+
+ for (uint32_t i = 0; i < mGraphicalMeshes.size(); i++)
+ {
+ if (mGraphicalMeshes[i].renderProxy != NULL)
+ {
+ mGraphicalMeshes[i].renderProxy->release();
+ mGraphicalMeshes[i].renderProxy = NULL;
+ }
+ }
+ mGraphicalMeshes.clear();
+
+ mRenderProxyMutex.lock();
+ if (mRenderProxyURR != NULL)
+ {
+ mRenderProxyURR->release();
+ mRenderProxyURR = NULL;
+ }
+ if (mRenderProxyReady != NULL)
+ {
+ mRenderProxyReady->release();
+ mRenderProxyReady = NULL;
+ }
+ mRenderProxyMutex.unlock();
+}
+
+
+#if APEX_UE4
+void ClothingActorImpl::initBeforeTickTasks(PxF32 deltaTime, PxF32 substepSize, PxU32 numSubSteps, PxTaskManager* taskManager, PxTaskID before, PxTaskID after)
+#else
+void ClothingActorImpl::initBeforeTickTasks(float deltaTime, float substepSize, uint32_t numSubSteps)
+#endif
+{
+#if APEX_UE4
+ PX_UNUSED(before);
+ PX_UNUSED(after);
+ PX_UNUSED(taskManager);
+#endif
+ mBeforeTickTask.setDeltaTime(deltaTime, substepSize, numSubSteps);
+}
+
+
+
+void ClothingActorImpl::submitTasksDuring(PxTaskManager* taskManager)
+{
+ taskManager->submitUnnamedTask(mDuringTickTask);
+}
+
+
+
+void ClothingActorImpl::setTaskDependenciesBefore(PxBaseTask* after)
+{
+ mBeforeTickTask.setContinuation(after);
+}
+
+
+void ClothingActorImpl::startBeforeTickTask()
+{
+ mBeforeTickTask.removeReference();
+}
+
+
+
+PxTaskID ClothingActorImpl::setTaskDependenciesDuring(PxTaskID before, PxTaskID after)
+{
+ mDuringTickTask.startAfter(before);
+ mDuringTickTask.finishBefore(after);
+
+ return mDuringTickTask.getTaskID();
+}
+
+
+#if !APEX_UE4
+void ClothingActorImpl::setFetchContinuation()
+{
+ PxTaskManager* taskManager = mClothingScene->getApexScene()->getTaskManager();
+ taskManager->submitUnnamedTask(mWaitForFetchTask);
+
+ mFetchResultsTask.setContinuation(&mWaitForFetchTask);
+
+ // reduce refcount to 1
+ mWaitForFetchTask.removeReference();
+}
+#endif
+
+
+void ClothingActorImpl::startFetchTasks()
+{
+ mFetchResultsRunningMutex.lock();
+ mFetchResultsRunning = true;
+#if APEX_UE4
+ mFetchResultsSync.reset();
+#else
+ mWaitForFetchTask.mWaiting.reset();
+#endif
+ mFetchResultsRunningMutex.unlock();
+
+#if APEX_UE4
+ PxTaskManager* taskManager = mClothingScene->getApexScene()->getTaskManager();
+ taskManager->submitUnnamedTask(mFetchResultsTask);
+#else
+ setFetchContinuation();
+#endif
+
+ mFetchResultsTask.removeReference();
+}
+
+
+
+void ClothingActorImpl::waitForFetchResults()
+{
+ mFetchResultsRunningMutex.lock();
+ if (mFetchResultsRunning)
+ {
+ PX_PROFILE_ZONE("ClothingActorImpl::waitForFetchResults", GetInternalApexSDK()->getContextId());
+#if APEX_UE4
+ mFetchResultsSync.wait();
+#else
+ mWaitForFetchTask.mWaiting.wait();
+#endif
+ syncActorData();
+ mFetchResultsRunning = false;
+
+#ifndef WITHOUT_PVD
+ updatePvd();
+#endif
+ }
+ mFetchResultsRunningMutex.unlock();
+}
+
+
+
+#if !APEX_UE4
+void ClothingWaitForFetchTask::run()
+{
+}
+
+
+
+void ClothingWaitForFetchTask::release()
+{
+ PxTask::release();
+
+ mWaiting.set();
+}
+
+
+
+const char* ClothingWaitForFetchTask::getName() const
+{
+ return "ClothingWaitForFetchTask";
+}
+#endif
+
+
+
+void ClothingActorImpl::applyTeleport(bool skinningReady, uint32_t substepNumber)
+{
+ const float teleportWeight = (bInternalTeleportDue != ClothingTeleportMode::Continuous && substepNumber == 0) ? 1.0f : 0.0f;
+ const bool teleportReset = bInternalTeleportDue == ClothingTeleportMode::TeleportAndReset;
+
+ // skinninReady is required when the teleportWeight is > 0.0
+ // != is the same as XOR, it prevents calling setTeleportWeights twice when using a normal or (||)
+ if ((mClothingSimulation != NULL) && ((teleportWeight == 0.0f) != skinningReady))
+ {
+ mClothingSimulation->setTeleportWeight(teleportWeight, teleportReset, bInternalLocalSpaceSim == 1);
+ }
+}
+
+
+
+void ClothingActorImpl::applyGlobalPose_LocksPhysX()
+{
+ if (mClothingSimulation)
+ {
+ mClothingSimulation->applyGlobalPose();
+ }
+}
+
+
+
+bool ClothingActorImpl::isValidDesc(const NvParameterized::Interface& params)
+{
+ // make this verbose!!!!
+ if (::strcmp(params.className(), ClothingActorParam::staticClassName()) == 0)
+ {
+ const ClothingActorParam& actorDescGeneric = static_cast<const ClothingActorParam&>(params);
+ const ClothingActorParamNS::ParametersStruct& actorDesc = static_cast<const ClothingActorParamNS::ParametersStruct&>(actorDescGeneric);
+
+ // commented variables don't need validation.
+ // actorDesc.actorDescTemplate
+ for (int32_t i = 0; i < actorDesc.boneMatrices.arraySizes[0]; i++)
+ {
+ if (!actorDesc.boneMatrices.buf[i].isFinite())
+ {
+ APEX_INVALID_PARAMETER("boneMatrices[%d] is not finite!", i);
+ return false;
+ }
+ }
+ // actorDesc.clothDescTemplate
+ // actorDesc.fallbackSkinning
+ // actorDesc.flags.ParallelCpuSkinning
+ // actorDesc.flags.ParallelMeshMeshSkinning
+ // actorDesc.flags.ParallelPhysxMeshSkinning
+ // actorDesc.flags.RecomputeNormals
+ // actorDesc.flags.Visualize
+ if (!actorDesc.globalPose.isFinite())
+ {
+ APEX_INVALID_PARAMETER("globalPose is not finite!");
+ return false;
+ }
+
+ if (actorDesc.maxDistanceBlendTime < 0.0f)
+ {
+ APEX_INVALID_PARAMETER("maxDistanceBlendTime must be positive");
+ return false;
+ }
+
+ if (actorDesc.maxDistanceScale.Scale < 0.0f || actorDesc.maxDistanceScale.Scale > 1.0f)
+ {
+ APEX_INVALID_PARAMETER("maxDistanceScale.Scale must be in the [0.0, 1.0] interval (is %f)",
+ actorDesc.maxDistanceScale.Scale);
+ return false;
+ }
+
+ // actorDesc.shapeDescTemplate
+ // actorDesc.slowStart
+ // actorDesc.updateStateWithGlobalMatrices
+ // actorDesc.useHardwareCloth
+ // actorDesc.useInternalBoneOrder
+ // actorDesc.userData
+ // actorDesc.uvChannelForTangentUpdate
+ if (actorDesc.windParams.Adaption < 0.0f)
+ {
+ APEX_INVALID_PARAMETER("windParams.Adaption must be positive or zero");
+ return false;
+ }
+ // actorDesc.windParams.Velocity
+
+ if (actorDesc.actorScale <= 0.0f)
+ {
+ APEX_INVALID_PARAMETER("ClothingActorParam::actorScale must be bigger than 0 (is %f)", actorDesc.actorScale);
+ return false;
+ }
+
+ return true;
+ }
+ else if (::strcmp(params.className(), ClothingPreviewParam::staticClassName()) == 0)
+ {
+ const ClothingPreviewParam& previewDescGeneric = static_cast<const ClothingPreviewParam&>(params);
+ const ClothingPreviewParamNS::ParametersStruct& previewDesc = static_cast<const ClothingPreviewParamNS::ParametersStruct&>(previewDescGeneric);
+
+
+ for (int32_t i = 0; i < previewDesc.boneMatrices.arraySizes[0]; i++)
+ {
+ if (!previewDesc.boneMatrices.buf[i].isFinite())
+ {
+ APEX_INVALID_PARAMETER("boneMatrices[%d] is not finite!", i);
+ return false;
+ }
+ }
+
+ if (!previewDesc.globalPose.isFinite())
+ {
+ APEX_INVALID_PARAMETER("globalPose is not finite!");
+ return false;
+ }
+
+ return true;
+ }
+ return false;
+}
+
+
+
+ClothingCookedParam* ClothingActorImpl::getRuntimeCookedDataPhysX()
+{
+ if (mActorDesc->runtimeCooked != NULL && ::strcmp(mActorDesc->runtimeCooked->className(), ClothingCookedParam::staticClassName()) == 0)
+ {
+ return static_cast<ClothingCookedParam*>(mActorDesc->runtimeCooked);
+ }
+
+ return NULL;
+}
+
+
+
+// ------ private methods -------
+
+
+void ClothingActorImpl::updateBoneBuffer(ClothingRenderProxyImpl* renderProxy)
+{
+ if (renderProxy == NULL)
+ return;
+
+ renderProxy->setPose(getRenderGlobalPose());
+
+ RenderMeshActor* meshActor = renderProxy->getRenderMeshActor();
+ if (meshActor == NULL)
+ return;
+
+ if (mData.mInternalBoneMatricesCur == NULL)
+ {
+ // no bones
+ PxMat44 pose = PxMat44(PxIdentity);
+ if (mClothingSimulation == NULL)
+ {
+ // no sim
+ if (bInternalLocalSpaceSim == 1)
+ {
+ pose = PxMat44(PxIdentity) * mActorDesc->actorScale;
+ }
+ else
+ {
+ pose = mInternalGlobalPose;
+ }
+ }
+
+ meshActor->setTM(pose, 0);
+ }
+ else /*if (bBoneBufferDirty)*/ // this dirty flag can only be used if we know that the
+ // render mesh asset stays with the clothing actor
+ // reactivate when APEX-43 is fixed. Note that currently
+ // the flag is set every frame in removePhysX_LocksPhysX
+ // when simulation is disabled, so the flag is
+ // currently not too useful
+ {
+ // bones or simulation have changed
+ PxMat44* buffer = mData.mInternalBoneMatricesCur;
+ PX_ASSERT(buffer != NULL);
+
+ if (mAsset->getNumUsedBonesForMesh() == 1 && mClothingSimulation != NULL)
+ {
+ meshActor->setTM(PxMat44(PxIdentity), 0);
+ }
+ else
+ {
+ const uint32_t numBones = PxMin(mAsset->getNumUsedBonesForMesh(), meshActor->getBoneCount());
+ for (uint32_t i = 0; i < numBones; i++)
+ {
+ meshActor->setTM(buffer[i], i);
+ }
+ }
+ }
+
+ bBoneBufferDirty = 0;
+}
+
+
+
+PxBounds3 ClothingActorImpl::getRenderMeshAssetBoundsTransformed()
+{
+ PxBounds3 newBounds = mAsset->getBoundingBox();
+
+ PxMat44 transformation;
+ if (mData.mInternalBoneMatricesCur != NULL)
+ {
+ transformation = mData.mInternalBoneMatricesCur[mAsset->getRootBoneIndex()];
+ }
+ else
+ {
+ transformation = mActorDesc->globalPose;
+ }
+
+ if (!newBounds.isEmpty())
+ {
+ const PxVec3 center = transformation.transform(newBounds.getCenter());
+ const PxVec3 extent = newBounds.getExtents();
+ const PxMat33 basis(transformation.column0.getXYZ(), transformation.column1.getXYZ(), transformation.column2.getXYZ());
+
+ return PxBounds3::basisExtent(center, basis, extent);
+ }
+ else
+ {
+ return newBounds;
+ }
+}
+
+
+
+bool ClothingActorImpl::allocateEnoughBoneBuffers_NoPhysX(bool prepareForSubstepping)
+{
+ PX_ASSERT(mActorDesc != NULL);
+ const uint32_t numBones = mActorDesc->useInternalBoneOrder ? mAsset->getNumUsedBones() : mAsset->getNumBones();
+
+ if (prepareForSubstepping && mInternalInterpolatedBoneMatrices == NULL)
+ {
+ mInternalInterpolatedBoneMatrices = (PxMat44*)PX_ALLOC(sizeof(PxMat44) * numBones, "mInternalInterpolatedBoneMatrices");
+ }
+
+ if (mData.mInternalBoneMatricesCur == NULL)
+ {
+ mData.mInternalBoneMatricesCur = (PxMat44*)PX_ALLOC(sizeof(PxMat44) * numBones, "mInternalBoneMatrices");
+ mData.mInternalBoneMatricesPrev = (PxMat44*)PX_ALLOC(sizeof(PxMat44) * numBones, "mInternalBoneMatrices2");
+ intrinsics::memSet(mData.mInternalBoneMatricesCur, 0, sizeof(PxMat44) * numBones);
+ intrinsics::memSet(mData.mInternalBoneMatricesPrev, 0, sizeof(PxMat44) * numBones);
+ return true;
+ }
+
+ return false;
+}
+
+
+
+bool ClothingActorImpl::isSimulationRunning() const
+{
+ if (mClothingScene != NULL)
+ {
+ return mClothingScene->isSimulating(); // virtual call
+ }
+
+ return false;
+}
+
+
+
+void ClothingActorImpl::updateStateInternal_NoPhysX(bool prepareForSubstepping)
+{
+ PX_ASSERT(mActorDesc);
+ mInternalFlags = mActorDesc->flags;
+
+ mInternalMaxDistanceBlendTime = (mActorDesc->freezeByLOD) ? 0.0f : mActorDesc->maxDistanceBlendTime;
+
+ mInternalWindParams = mActorDesc->windParams;
+
+ bInternalVisible = bBufferedVisible;
+ if (bUpdateFrozenFlag == 1)
+ {
+ bInternalFrozen = bBufferedFrozen;
+ bUpdateFrozenFlag = 0;
+ }
+
+ // update teleportation from double buffering
+ bInternalTeleportDue = (ClothingTeleportMode::Enum)mActorDesc->teleportMode;
+ mActorDesc->teleportMode = ClothingTeleportMode::Continuous;
+
+ if (mActorDesc->localSpaceSim != (bInternalLocalSpaceSim == 1))
+ {
+ bInternalTeleportDue = ClothingTeleportMode::TeleportAndReset;
+ }
+ bInternalLocalSpaceSim = mActorDesc->localSpaceSim ? 1u : 0u;
+
+ bMaxDistanceScaleChanged =
+ (mInternalMaxDistanceScale.Scale != mActorDesc->maxDistanceScale.Scale ||
+ mInternalMaxDistanceScale.Multipliable != mActorDesc->maxDistanceScale.Multipliable)
+ ? 1u : 0u;
+
+ mInternalMaxDistanceScale = mActorDesc->maxDistanceScale;
+
+ lockRenderResources();
+
+ PxMat44 globalPose = mActorDesc->globalPose;
+
+ PxMat44 rootBoneTransform = PxMat44(PxIdentity);
+ const float invActorScale = 1.0f / mActorDesc->actorScale;
+ bool bHasBones = mActorDesc->boneMatrices.arraySizes[0] > 0 || mAsset->getNumBones() > 0;
+ bool bMultiplyGlobalPoseIntoBones = mActorDesc->multiplyGlobalPoseIntoBones || mActorDesc->boneMatrices.arraySizes[0] == 0;
+ if (bHasBones)
+ {
+ bool newBuffers = allocateEnoughBoneBuffers_NoPhysX(prepareForSubstepping);
+
+ nvidia::swap(mData.mInternalBoneMatricesCur, mData.mInternalBoneMatricesPrev);
+
+ const uint32_t numBones = (mActorDesc->useInternalBoneOrder) ? mAsset->getNumUsedBones() : mAsset-> getNumBones();
+
+ uint32_t rootNodeExternalIndex = mActorDesc->useInternalBoneOrder ? mAsset->getRootBoneIndex() : mAsset->getBoneExternalIndex(mAsset->getRootBoneIndex());
+ if (rootNodeExternalIndex < (uint32_t)mActorDesc->boneMatrices.arraySizes[0])
+ {
+ // new pose of root bone available
+ rootBoneTransform = mActorDesc->boneMatrices.buf[rootNodeExternalIndex];
+ }
+ else if (mActorDesc->updateStateWithGlobalMatrices)
+ {
+ // no pose for root bone available, use bind pose
+ mAsset->getBoneBasePose(mAsset->getRootBoneIndex(), rootBoneTransform);
+ }
+
+ PxMat44 pose = PxMat44(PxIdentity);
+ if (bInternalLocalSpaceSim == 1)
+ {
+ // consider the root bone as local space reference
+ // PH: Note that inverseRT does not invert the scale, but preserve it
+
+ // normalize (dividing by actorscale is not precise enough)
+ if (!bMultiplyGlobalPoseIntoBones)
+ {
+ rootBoneTransform.column0.normalize();
+ rootBoneTransform.column1.normalize();
+ rootBoneTransform.column2.normalize();
+ }
+
+ // this transforms the skeleton into origin, and keeps the scale
+ PxMat44 invRootBoneTransformTimesScale = rootBoneTransform.inverseRT();
+
+ if (bMultiplyGlobalPoseIntoBones)
+ {
+ invRootBoneTransformTimesScale *= mActorDesc->actorScale;
+ }
+
+ // the result will be transformed back to global space in rendering
+ pose = invRootBoneTransformTimesScale;
+ }
+ else if (bMultiplyGlobalPoseIntoBones)
+ {
+ pose = globalPose;
+ }
+
+ if (mActorDesc->boneMatrices.arraySizes[0] >= (int32_t)numBones)
+ {
+ // TODO when no globalPose is set and the bones are given internal, there could be a memcpy
+ if (mAsset->writeBoneMatrices(pose, mActorDesc->boneMatrices.buf, sizeof(PxMat44), (uint32_t)mActorDesc->boneMatrices.arraySizes[0],
+ mData.mInternalBoneMatricesCur, mActorDesc->useInternalBoneOrder, mActorDesc->updateStateWithGlobalMatrices))
+ {
+ bBoneMatricesChanged = 1;
+ }
+ }
+ else
+ {
+ // no matrices provided. mInternalBoneMatrices (skinningMatrices) should just reflect the
+ // the global pose transform
+
+ for (uint32_t i = 0; i < numBones; i++)
+ {
+ mData.mInternalBoneMatricesCur[i] = pose;
+ }
+ }
+
+ if (newBuffers)
+ {
+ memcpy(mData.mInternalBoneMatricesPrev, mData.mInternalBoneMatricesCur, sizeof(PxMat44) * numBones);
+ }
+ }
+ else if (mData.mInternalBoneMatricesCur != NULL)
+ {
+ PX_FREE(mData.mInternalBoneMatricesCur);
+ PX_FREE(mData.mInternalBoneMatricesPrev);
+ mData.mInternalBoneMatricesCur = mData.mInternalBoneMatricesPrev = NULL;
+ }
+
+ unlockRenderResources();
+
+ PxMat44 newInternalGlobalPose;
+ if (bInternalLocalSpaceSim == 1)
+ {
+ // transform back into global space:
+ if (bMultiplyGlobalPoseIntoBones || !bHasBones)
+ {
+ // we need to remove the scale when transforming back, as we keep the scale in local space
+ // hmm, not sure why the adjustments on the translation parts are necessary, but they are..
+ globalPose *= invActorScale;
+ rootBoneTransform.scale(PxVec4(1.0f, 1.0f, 1.0f, mActorDesc->actorScale));
+ newInternalGlobalPose = globalPose * rootBoneTransform;
+ }
+ else
+ {
+ newInternalGlobalPose = rootBoneTransform;
+ }
+ }
+ else
+ {
+ newInternalGlobalPose = globalPose;
+ }
+
+ mOldInternalGlobalPose = mOldInternalGlobalPose.column0.isZero() ? newInternalGlobalPose : mInternalGlobalPose;
+ mInternalGlobalPose = newInternalGlobalPose;
+
+ bGlobalPoseChanged = (mInternalGlobalPose != mOldInternalGlobalPose) ? 1u : 0u;
+
+ // set bBoneBufferDirty to 1 if any matrices have changed
+ bBoneBufferDirty = (bGlobalPoseChanged == 1) || (bBoneMatricesChanged == 1) || (bBoneBufferDirty == 1) ? 1u : 0u;
+}
+
+
+
+#define RENDER_DEBUG_INTERMEDIATE_STEPS 0
+
+template<bool withBackstop>
+void ClothingActorImpl::skinPhysicsMeshInternal(bool useInterpolatedMatrices, float substepFraction)
+{
+#if RENDER_DEBUG_INTERMEDIATE_STEPS
+ const float RenderDebugIntermediateRadius = 0.8f;
+ mClothingScene->mRenderDebug->setCurrentDisplayTime(0.1);
+ const uint8_t yellowColor = 255 - (uint8_t)(255.0f * substepFraction);
+ const uint32_t color = 0xff0000 | yellowColor << 8;
+ mClothingScene->mRenderDebug->setCurrentColor(color);
+#else
+ PX_UNUSED(substepFraction);
+#endif
+
+ uint32_t morphOffset = mAsset->getPhysicalMeshOffset(mAsset->getPhysicalMeshID(mCurrentGraphicalLodId));
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ PxVec3* morphedPositions = mActorDesc->morphPhysicalMeshNewPositions.buf;
+ const PxVec3* const PX_RESTRICT positions = morphedPositions != NULL ? morphedPositions + morphOffset : physicalMesh->vertices.buf;
+ const PxVec3* const PX_RESTRICT normals = physicalMesh->normals.buf;
+ const ClothingPhysicalMeshParametersNS::ConstrainCoefficient_Type* const PX_RESTRICT coeffs = physicalMesh->constrainCoefficients.buf;
+ const float actorScale = mActorDesc->actorScale;
+
+ const uint32_t numVertices = physicalMesh->numSimulatedVertices;
+ const uint32_t numBoneIndicesPerVertex = physicalMesh->numBonesPerVertex;
+
+ PxVec3* const PX_RESTRICT targetPositions = mClothingSimulation->skinnedPhysicsPositions;
+ PxVec3* const PX_RESTRICT targetNormals = mClothingSimulation->skinnedPhysicsNormals;
+
+ const uint32_t numPrefetches = ((numVertices + NUM_VERTICES_PER_CACHE_BLOCK - 1) / NUM_VERTICES_PER_CACHE_BLOCK);
+
+ if (mData.mInternalBoneMatricesCur == NULL || numBoneIndicesPerVertex == 0)
+ {
+ PxMat44 matrix = PxMat44(PxIdentity);
+ if (bInternalLocalSpaceSim == 1)
+ {
+ matrix *= actorScale;
+ }
+ else
+ {
+ // PH: maybe we can skip the matrix multiplication altogether when using local space sim?
+ matrix = useInterpolatedMatrices ? mInternalInterpolatedGlobalPose : mInternalGlobalPose;
+ }
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ //const PxVec3 untransformedPosition = positions[index] + morphReordering == NULL ? PxVec3(0.0f) : morphDisplacements[morphReordering[index]];
+ targetPositions[i] = matrix.transform(positions[i]);
+ targetNormals[i] = matrix.rotate(normals[i]);
+
+ if (withBackstop)
+ {
+ if (coeffs[i].collisionSphereDistance < 0.0f)
+ {
+ targetPositions[i] -= (coeffs[i].collisionSphereDistance * actorScale) * targetNormals[i];
+ }
+ }
+#if RENDER_DEBUG_INTERMEDIATE_STEPS
+ if (RenderDebugIntermediateRadius > 0.0f)
+ {
+ mClothingScene->mRenderDebug->debugPoint(targetPositions[i], RenderDebugIntermediateRadius);
+ }
+#endif
+ }
+ }
+ else
+ {
+ const uint16_t* const PX_RESTRICT simBoneIndices = physicalMesh->boneIndices.buf;
+ const float* const PX_RESTRICT simBoneWeights = physicalMesh->boneWeights.buf;
+ const PxMat44* matrices = useInterpolatedMatrices ? mInternalInterpolatedBoneMatrices : mData.mInternalBoneMatricesCur;
+
+ const uint8_t* const PX_RESTRICT optimizationData = physicalMesh->optimizationData.buf;
+ PX_ASSERT(optimizationData != NULL);
+ PX_ASSERT((int32_t)(numPrefetches * NUM_VERTICES_PER_CACHE_BLOCK) / 2 <= physicalMesh->optimizationData.arraySizes[0]);
+
+ uint32_t vertexIndex = 0;
+ for (uint32_t i = 0; i < numPrefetches; ++i)
+ {
+ // HL: i tried to put positions and normals into a 16 byte aligned struct
+ // but there was no significant perf benefit, and it caused a lot of adaptations
+ // in the code because of the introduction of strides. Had to use
+ // a stride iterators in AbstractMeshDescription, which made
+ // its usage slower on xbox
+
+ uint8_t* cache = (uint8_t*)((((size_t)(positions + vertexIndex + NUM_VERTICES_PER_CACHE_BLOCK)) >> 7) << 7);
+ prefetchLine(cache);
+ //prefetchLine(cache + 128);
+
+ cache = (uint8_t*)((((size_t)(normals + vertexIndex + NUM_VERTICES_PER_CACHE_BLOCK)) >> 7) << 7);
+ prefetchLine(cache);
+ //prefetchLine(cache + 128);
+
+ cache = (uint8_t*)((((size_t)(&simBoneWeights[(vertexIndex + NUM_VERTICES_PER_CACHE_BLOCK) * numBoneIndicesPerVertex])) >> 7) << 7);
+ prefetchLine(cache);
+ prefetchLine(cache + 128);
+
+ cache = (uint8_t*)((((size_t)(&simBoneIndices[(vertexIndex + NUM_VERTICES_PER_CACHE_BLOCK) * numBoneIndicesPerVertex])) >> 7) << 7);
+ prefetchLine(cache);
+ //prefetchLine(cache + 128);
+
+
+ if (withBackstop)
+ {
+ prefetchLine(&coeffs[vertexIndex + NUM_VERTICES_PER_CACHE_BLOCK]);
+ }
+
+ for (uint32_t j = 0; j < NUM_VERTICES_PER_CACHE_BLOCK; ++j)
+ {
+ //float sumWeights = 0.0f; // this is just for sanity
+
+ Simd4f positionV = gSimd4fZero;
+ Simd4f normalV = gSimd4fZero;
+
+ const uint8_t shift = 4 * (vertexIndex % 2);
+ const uint8_t numBones = uint8_t((optimizationData[vertexIndex / 2] >> shift) & 0x7);
+ for (uint32_t k = 0; k < numBones; k++)
+ {
+ const float weight = simBoneWeights[vertexIndex * numBoneIndicesPerVertex + k];
+
+ PX_ASSERT(weight <= 1.0f);
+
+ //sumWeights += weight;
+ Simd4f weightV = Simd4fScalarFactory(weight);
+
+ const uint32_t index = simBoneIndices[vertexIndex * numBoneIndicesPerVertex + k];
+ PX_ASSERT(index < mAsset->getNumUsedBones());
+
+ /// PH: This might be faster without the reference, but on PC I can't tell
+ /// HL: Now with SIMD it's significantly faster as reference
+ const PxMat44& bone = (PxMat44&)matrices[index];
+
+ Simd4f pV = applyAffineTransform(bone, createSimd3f(positions[vertexIndex]));
+ pV = pV * weightV;
+ positionV = positionV + pV;
+
+ ///todo There are probably cases where we don't need the normal on the physics mesh
+ Simd4f nV = applyLinearTransform(bone, createSimd3f(normals[vertexIndex]));
+ nV = nV * weightV;
+ normalV = normalV + nV;
+ }
+
+ // PH: Sanity test. if this is not fulfilled, skinning went awfully wrong anyways
+ // TODO do this check only once somewhere at initialization
+ //PX_ASSERT(sumWeights == 0.0f || (sumWeights > 0.9999f && sumWeights < 1.0001f));
+
+ normalV = normalV * rsqrt(dot3(normalV, normalV));
+ store3(&targetNormals[vertexIndex].x, normalV);
+ PX_ASSERT(numBones == 0 || targetNormals[vertexIndex].isFinite());
+
+ // We disabled this in skinToBones as well, cause it's not really a valid case
+ //if (sumWeights == 0)
+ // positionV = V3LoadU(positions[vertexIndex]);
+
+ // in case of a negative collision sphere distance we move the animated position upwards
+ // along the normal and set the collision sphere distance to zero.
+ if (withBackstop)
+ {
+ if ((optimizationData[vertexIndex / 2] >> shift) & 0x8)
+ {
+ const float collisionSphereDistance = coeffs[vertexIndex].collisionSphereDistance;
+ Simd4f dV = normalV * Simd4fScalarFactory(collisionSphereDistance * actorScale);
+ positionV = positionV - dV;
+ }
+ }
+
+ store3(&targetPositions[vertexIndex].x, positionV);
+ PX_ASSERT(targetPositions[vertexIndex].isFinite());
+
+#if RENDER_DEBUG_INTERMEDIATE_STEPS
+ if (RenderDebugIntermediateRadius > 0.0f)
+ {
+ mClothingScene->mRenderDebug->debugPoint(targetPositions[vertexIndex], RenderDebugIntermediateRadius);
+ }
+#endif
+
+ ++vertexIndex;
+ }
+ }
+ }
+#if RENDER_DEBUG_INTERMEDIATE_STEPS
+ mClothingScene->mRenderDebug->setCurrentDisplayTime();
+#endif
+}
+
+
+
+void ClothingActorImpl::fetchResults()
+{
+ PX_PROFILE_ZONE("ClothingActorImpl::fetchResults", GetInternalApexSDK()->getContextId());
+ if (isVisible() && mClothingSimulation != NULL && bInternalFrozen == 0)
+ {
+ mClothingSimulation->fetchResults(mInternalFlags.ComputePhysicsMeshNormals);
+ }
+}
+
+
+
+ClothingActorData& ClothingActorImpl::getActorData()
+{
+ return mData;
+}
+
+
+
+void ClothingActorImpl::initializeActorData()
+{
+ PX_PROFILE_ZONE("ClothingActorImpl::initializeActorData", GetInternalApexSDK()->getContextId());
+
+ mData.bIsClothingSimulationNull = mClothingSimulation == NULL;
+ const bool bUninit = mData.bIsInitialized && mClothingSimulation == NULL;
+ if (bReinitActorData == 1 || bUninit)
+ {
+ //We need to uninitialize ourselves
+ PX_FREE(mData.mAsset.mData);
+ mData.mAsset.mData = NULL;
+ mData.bIsInitialized = false;
+ bReinitActorData = 0;
+
+ if (bUninit)
+ {
+ return;
+ }
+ }
+
+ if(mGraphicalMeshes[mCurrentGraphicalLodId].renderProxy != NULL)
+ {
+ mData.mRenderingDataPosition = mGraphicalMeshes[mCurrentGraphicalLodId].renderProxy->renderingDataPosition;
+ mData.mRenderingDataNormal = mGraphicalMeshes[mCurrentGraphicalLodId].renderProxy->renderingDataNormal;
+ mData.mRenderingDataTangent = mGraphicalMeshes[mCurrentGraphicalLodId].renderProxy->renderingDataTangent;
+ }
+
+ if (!mData.bIsInitialized && mClothingSimulation != NULL)
+ {
+ mData.bIsInitialized = true;
+ //Initialize
+ mData.mRenderLock = mRenderDataLock;
+
+ mData.mSdkDeformableVerticesCount = mClothingSimulation->sdkNumDeformableVertices;
+ mData.mSdkDeformableIndicesCount = mClothingSimulation->sdkNumDeformableIndices;
+ mData.mSdkWritebackPositions = mClothingSimulation->sdkWritebackPosition;
+ mData.mSdkWritebackNormal = mClothingSimulation->sdkWritebackNormal;
+
+ mData.mSkinnedPhysicsPositions = mClothingSimulation->skinnedPhysicsPositions;
+ mData.mSkinnedPhysicsNormals = mClothingSimulation->skinnedPhysicsNormals;
+
+ //Allocate the clothing asset now...
+
+ mAsset->initializeAssetData(mData.mAsset, mActorDesc->uvChannelForTangentUpdate);
+
+ mData.mMorphDisplacementBuffer = mActorDesc->morphDisplacements.buf;
+ mData.mMorphDisplacementBufferCount = (uint32_t)mActorDesc->morphDisplacements.arraySizes[0];
+ }
+
+ uint32_t largestSubmesh = 0;
+ if (mData.bIsInitialized && mClothingSimulation != NULL)
+ {
+ mData.bRecomputeNormals = mInternalFlags.RecomputeNormals;
+ mData.bRecomputeTangents = mInternalFlags.RecomputeTangents;
+ mData.bIsSimulationMeshDirty = mClothingSimulation->isSimulationMeshDirty();
+
+ // this updates per-frame so I need to sync it every frame
+ mData.mInternalGlobalPose = mInternalGlobalPose;
+ mData.mCurrentGraphicalLodId = mCurrentGraphicalLodId;
+
+ for (uint32_t a = 0; a < mData.mAsset.mGraphicalLodsCount; ++a)
+ {
+ ClothingMeshAssetData* pLod = mData.mAsset.GetLod(a);
+ pLod->bActive = mGraphicalMeshes[a].active;
+ pLod->bNeedsTangents = mGraphicalMeshes[a].needsTangents;
+
+ // check if map contains tangent values, otherwise print out warning
+ if (!mData.bRecomputeTangents && mGraphicalMeshes[a].needsTangents && pLod->mImmediateClothMap != NULL)
+ {
+ // tangentBary has been marked invalid during asset update, or asset has immediate map (without tangent info)
+ mData.bRecomputeTangents = true;
+ mInternalFlags.RecomputeTangents = true;
+ mActorDesc->flags.RecomputeTangents = true;
+
+ // hm, let's not spam the user, as RecomputeTangents is off by default
+ //APEX_DEBUG_INFO("Asset (%s) does not support tangent skinning. Resetting RecomputeTangents to true.", mAsset->getName());
+ }
+
+ //Copy to...
+
+ for (uint32_t b = 0; b < pLod->mSubMeshCount; b++)
+ {
+ ClothingAssetSubMesh* submesh = mData.mAsset.GetSubmesh(a, b);
+
+ const uint32_t numParts = (uint32_t)mAsset->getGraphicalLod(a)->physicsMeshPartitioning.arraySizes[0];
+ ClothingGraphicalLodParametersNS::PhysicsMeshPartitioning_Type* parts = mAsset->getGraphicalLod(a)->physicsMeshPartitioning.buf;
+
+#if defined _DEBUG || PX_CHECKED
+ bool found = false;
+#endif
+ for (uint32_t c = 0; c < numParts; c++)
+ {
+ if (parts[c].graphicalSubmesh == b)
+ {
+ submesh->mCurrentMaxVertexSimulation = parts[c].numSimulatedVertices;
+ submesh->mCurrentMaxVertexAdditionalSimulation = parts[c].numSimulatedVerticesAdditional;
+ submesh->mCurrentMaxIndexSimulation = parts[c].numSimulatedIndices;
+
+ largestSubmesh = PxMax(largestSubmesh, parts[c].numSimulatedVerticesAdditional);
+#if defined _DEBUG || PX_CHECKED
+ found = true;
+#endif
+ break;
+ }
+ }
+#if defined _DEBUG || PX_CHECKED
+ PX_ASSERT(found);
+#endif
+ }
+ }
+ mData.mActorScale = mActorDesc->actorScale;
+
+ mData.bShouldComputeRenderData = shouldComputeRenderData();
+ mData.bInternalFrozen = bInternalFrozen;
+ mData.bCorrectSimulationNormals = mInternalFlags.CorrectSimulationNormals;
+ mData.bParallelCpuSkinning = mInternalFlags.ParallelCpuSkinning;
+ mData.mGlobalPose = mActorDesc->globalPose;
+
+ mData.mInternalMatricesCount = mActorDesc->useInternalBoneOrder ? mAsset->getNumUsedBones() : mAsset->getNumBones();
+ }
+
+}
+
+void ClothingActorImpl::syncActorData()
+{
+ PX_PROFILE_ZONE("ClothingActorImpl::syncActorData", GetInternalApexSDK()->getContextId());
+
+ if (mData.bIsInitialized && mData.bShouldComputeRenderData && mClothingSimulation != NULL /*&& bInternalFrozen == 0*/)
+ {
+ PX_ASSERT(!mData.mNewBounds.isEmpty());
+ PX_ASSERT(mData.mNewBounds.isFinite());
+
+ //Write back all the modified variables so that the simulation is consistent
+ mNewBounds = mData.mNewBounds;
+ }
+ else
+ {
+ mNewBounds = getRenderMeshAssetBoundsTransformed();
+ }
+
+ if (bInternalLocalSpaceSim == 1)
+ {
+#if _DEBUG
+ bool ok = true;
+ ok &= mInternalGlobalPose.column0.isNormalized();
+ ok &= mInternalGlobalPose.column1.isNormalized();
+ ok &= mInternalGlobalPose.column2.isNormalized();
+ if (!ok)
+ {
+ APEX_DEBUG_WARNING("Internal Global Pose is not normalized (Scale: %f %f %f). Bounds could be wrong.", mInternalGlobalPose.column0.magnitude(), mInternalGlobalPose.column1.magnitude(), mInternalGlobalPose.column2.magnitude());
+ }
+#endif
+ PX_ASSERT(!mNewBounds.isEmpty());
+ mRenderBounds = PxBounds3::transformFast(PxTransform(mInternalGlobalPose), mNewBounds);
+ }
+ else
+ {
+ mRenderBounds = mNewBounds;
+ }
+
+ markRenderProxyReady();
+}
+
+
+
+void ClothingActorImpl::markRenderProxyReady()
+{
+ PX_PROFILE_ZONE("ClothingActorImpl::markRenderProxyReady", GetInternalApexSDK()->getContextId());
+ mRenderProxyMutex.lock();
+ if (mRenderProxyReady != NULL)
+ {
+ // user didn't request the renderable after fetchResults,
+ // let's release it, so it can be reused
+ mRenderProxyReady->release();
+ }
+
+ ClothingRenderProxyImpl* renderProxy = mGraphicalMeshes[mCurrentGraphicalLodId].renderProxy;
+ if (renderProxy != NULL)
+ {
+ updateBoneBuffer(renderProxy);
+ mGraphicalMeshes[mCurrentGraphicalLodId].renderProxy = NULL;
+ renderProxy->setBounds(mRenderBounds);
+ }
+
+ mRenderProxyReady = renderProxy;
+ mRenderProxyMutex.unlock();
+}
+
+
+
+void ClothingActorImpl::fillWritebackData_LocksPhysX(const WriteBackInfo& writeBackInfo)
+{
+ PX_ASSERT(mClothingSimulation != NULL);
+ PX_ASSERT(mClothingSimulation->physicalMeshId != 0xffffffff);
+ PX_ASSERT(writeBackInfo.simulationDelta >= 0.0f);
+
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* destPhysicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+
+ // copy the data from the old mesh
+ // use bigger position buffer as temp buffer
+ uint32_t numCopyVertices = 0;
+ PxVec3* velocities = NULL;
+
+ float transitionMapThickness = 0.0f;
+ float transitionMapOffset = 0.0f;
+ const ClothingPhysicalMeshParametersNS::SkinClothMapB_Type* pTCMB = NULL;
+ const ClothingPhysicalMeshParametersNS::SkinClothMapD_Type* pTCM = NULL;
+ if (writeBackInfo.oldSimulation)
+ {
+ PX_ASSERT(writeBackInfo.oldSimulation->physicalMeshId != 0xffffffff);
+ pTCMB = mAsset->getTransitionMapB(mClothingSimulation->physicalMeshId, writeBackInfo.oldSimulation->physicalMeshId, transitionMapThickness, transitionMapOffset);
+ pTCM = mAsset->getTransitionMap(mClothingSimulation->physicalMeshId, writeBackInfo.oldSimulation->physicalMeshId, transitionMapThickness, transitionMapOffset);
+ }
+
+ if (pTCMB != NULL || pTCM != NULL)
+ {
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* srcPhysicalMesh = mAsset->getPhysicalMeshFromLod(writeBackInfo.oldGraphicalLodId);
+ PX_ASSERT(srcPhysicalMesh != NULL);
+
+ AbstractMeshDescription srcPM;
+ srcPM.numIndices = writeBackInfo.oldSimulation->sdkNumDeformableIndices;
+ srcPM.numVertices = writeBackInfo.oldSimulation->sdkNumDeformableVertices;
+ srcPM.pIndices = srcPhysicalMesh->indices.buf;
+ srcPM.pNormal = writeBackInfo.oldSimulation->sdkWritebackNormal;
+ srcPM.pPosition = writeBackInfo.oldSimulation->sdkWritebackPosition;
+ srcPM.avgEdgeLength = transitionMapThickness;
+
+ // new position and normal buffer will be initialized afterwards, buffer can be used here
+ if (mClothingSimulation->sdkNumDeformableVertices > writeBackInfo.oldSimulation->sdkNumDeformableVertices)
+ {
+ transferVelocities_LocksPhysX(*writeBackInfo.oldSimulation, pTCMB, pTCM, destPhysicalMesh->numVertices, srcPM.pIndices, srcPM.numIndices, srcPM.numVertices,
+ mClothingSimulation->sdkWritebackPosition, mClothingSimulation->sdkWritebackNormal, writeBackInfo.simulationDelta);
+ }
+
+ // PH: sdkWritebackPosition will contain qnans for the values that have not been written.
+ intrinsics::memSet(mClothingSimulation->sdkWritebackPosition, 0xff, sizeof(PxVec3) * mClothingSimulation->sdkNumDeformableVertices);
+
+ if (pTCMB != NULL)
+ {
+ numCopyVertices = mData.mAsset.skinClothMapB(mClothingSimulation->sdkWritebackPosition, mClothingSimulation->sdkWritebackNormal,
+ mClothingSimulation->sdkNumDeformableVertices, srcPM, (ClothingGraphicalLodParametersNS::SkinClothMapB_Type*)pTCMB, destPhysicalMesh->numVertices, true);
+ }
+ else
+ {
+ numCopyVertices = mData.mAsset.skinClothMap<true>(mClothingSimulation->sdkWritebackPosition, mClothingSimulation->sdkWritebackNormal, NULL, mClothingSimulation->sdkNumDeformableVertices,
+ srcPM, (ClothingGraphicalLodParametersNS::SkinClothMapD_Type*)pTCM, destPhysicalMesh->numVertices, transitionMapOffset, mActorDesc->actorScale);
+ }
+
+ // don't need old positions and normals anymore
+ if (writeBackInfo.oldSimulation->sdkNumDeformableVertices >= mClothingSimulation->sdkNumDeformableVertices)
+ {
+ transferVelocities_LocksPhysX(*writeBackInfo.oldSimulation, pTCMB, pTCM, destPhysicalMesh->numVertices, srcPM.pIndices, srcPM.numIndices, srcPM.numVertices,
+ writeBackInfo.oldSimulation->sdkWritebackPosition, writeBackInfo.oldSimulation->sdkWritebackNormal, writeBackInfo.simulationDelta);
+ }
+ }
+ else if (writeBackInfo.oldSimulation != NULL && writeBackInfo.oldSimulation->physicalMeshId == mClothingSimulation->physicalMeshId)
+ {
+ if (writeBackInfo.oldSimulation->sdkNumDeformableVertices < mClothingSimulation->sdkNumDeformableVertices)
+ {
+ // old is smaller
+ numCopyVertices = writeBackInfo.oldSimulation->sdkNumDeformableVertices;
+ velocities = mClothingSimulation->sdkWritebackPosition;
+ copyAndComputeVelocities_LocksPhysX(numCopyVertices, writeBackInfo.oldSimulation, velocities, writeBackInfo.simulationDelta);
+
+ // PH: sdkWritebackPosition will contain qnans for the values that have not been written.
+ intrinsics::memSet(mClothingSimulation->sdkWritebackPosition, 0xff, sizeof(PxVec3) * mClothingSimulation->sdkNumDeformableVertices);
+
+ copyPositionAndNormal_NoPhysX(numCopyVertices, writeBackInfo.oldSimulation);
+ }
+ else
+ {
+ // new is smaller
+ numCopyVertices = mClothingSimulation->sdkNumDeformableVertices;
+ velocities = writeBackInfo.oldSimulation->sdkWritebackPosition;
+
+ // PH: sdkWritebackPosition will contain qnans for the values that have not been written.
+ intrinsics::memSet(mClothingSimulation->sdkWritebackPosition, 0xff, sizeof(PxVec3) * mClothingSimulation->sdkNumDeformableVertices);
+
+ copyPositionAndNormal_NoPhysX(numCopyVertices, writeBackInfo.oldSimulation);
+ copyAndComputeVelocities_LocksPhysX(numCopyVertices, writeBackInfo.oldSimulation, velocities, writeBackInfo.simulationDelta);
+ }
+ }
+ else
+ {
+ velocities = mClothingSimulation->sdkWritebackPosition;
+ copyAndComputeVelocities_LocksPhysX(0, writeBackInfo.oldSimulation, velocities, writeBackInfo.simulationDelta);
+
+ // PH: sdkWritebackPosition will contain qnans for the values that have not been written.
+ intrinsics::memSet(mClothingSimulation->sdkWritebackPosition, 0xff, sizeof(PxVec3) * mClothingSimulation->sdkNumDeformableVertices);
+ }
+
+
+ const PxVec3* positions = destPhysicalMesh->vertices.buf;
+ const PxVec3* normals = destPhysicalMesh->normals.buf;
+ const uint32_t numBoneIndicesPerVertex = destPhysicalMesh->numBonesPerVertex;
+ const uint16_t* simBoneIndices = destPhysicalMesh->boneIndices.buf;
+ const float* simBoneWeights = destPhysicalMesh->boneWeights.buf;
+
+ // apply an initial skinning on the physical mesh
+ // ASSUMPTION: when allocated, mSdkWriteback* buffers will always contain meaningful data, so initialize correctly!
+ // All data that is not skinned from the old to the new mesh will have non-finite values (qnan)
+
+ const uint8_t* const PX_RESTRICT optimizationData = destPhysicalMesh->optimizationData.buf;
+ PX_ASSERT(optimizationData != NULL);
+
+ const PxMat44* matrices = mData.mInternalBoneMatricesCur;
+ if (matrices != NULL)
+ {
+ // one pass of cpu skinning on the physical mesh
+ const bool useNormals = mClothingSimulation->sdkWritebackNormal != NULL;
+
+ const uint32_t numVertices = destPhysicalMesh->numVertices;
+ for (uint32_t i = numCopyVertices; i < numVertices; i++)
+ {
+ const uint8_t shift = 4 * (i % 2);
+ const uint8_t numBones = uint8_t((optimizationData[i / 2] >> shift) & 0x7);
+
+ const uint32_t vertexIndex = (pTCMB == NULL) ? i : pTCMB[i].vertexIndexPlusOffset;
+
+ if (vertexIndex >= mClothingSimulation->sdkNumDeformableVertices)
+ {
+ continue;
+ }
+
+ if (PxIsFinite(mClothingSimulation->sdkWritebackPosition[vertexIndex].x))
+ {
+ continue;
+ }
+
+ Simd4f positionV = gSimd4fZero;
+ Simd4f normalV = gSimd4fZero;
+
+ const uint32_t numUsedBones = mAsset->getNumUsedBones();
+ PX_UNUSED(numUsedBones);
+
+ for (uint32_t j = 0; j < numBones; j++)
+ {
+
+ Simd4f weightV = Simd4fScalarFactory(simBoneWeights[vertexIndex * numBoneIndicesPerVertex + j]);
+ uint16_t index = simBoneIndices[vertexIndex * numBoneIndicesPerVertex + j];
+ PX_ASSERT(index < numUsedBones);
+
+ const PxMat44& bone = (PxMat44&)matrices[index];
+
+ Simd4f pV = applyAffineTransform(bone, createSimd3f(positions[vertexIndex]));
+ pV = pV * weightV;
+ positionV = positionV + pV;
+
+ if (useNormals)
+ {
+ Simd4f nV = applyLinearTransform(bone, createSimd3f(normals[vertexIndex]));
+ nV = nV * weightV;
+ normalV = normalV + nV;
+ }
+
+ }
+
+ if (useNormals)
+ {
+ normalV = normalV * rsqrt(dot3(normalV, normalV));
+ store3(&mClothingSimulation->sdkWritebackNormal[vertexIndex].x, normalV);
+ }
+ store3(&mClothingSimulation->sdkWritebackPosition[vertexIndex].x, positionV);
+ }
+ }
+ else
+ {
+ // no bone matrices, just move into world space
+ const uint32_t numVertices = destPhysicalMesh->numVertices;
+ PxMat44 TM = bInternalLocalSpaceSim == 1 ? PxMat44(PxIdentity) * mActorDesc->actorScale : mInternalGlobalPose;
+ for (uint32_t i = numCopyVertices; i < numVertices; i++)
+ {
+ const uint32_t vertexIndex = (pTCMB == NULL) ? i : pTCMB[i].vertexIndexPlusOffset;
+ if (vertexIndex >= mClothingSimulation->sdkNumDeformableVertices)
+ {
+ continue;
+ }
+
+ if (PxIsFinite(mClothingSimulation->sdkWritebackPosition[vertexIndex].x))
+ {
+ continue;
+ }
+
+ mClothingSimulation->sdkWritebackPosition[vertexIndex] = TM.transform(positions[vertexIndex]);
+ if (mClothingSimulation->sdkWritebackNormal != NULL)
+ {
+ mClothingSimulation->sdkWritebackNormal[vertexIndex] = TM.rotate(normals[vertexIndex]);
+ }
+ }
+ }
+}
+
+
+
+/// todo simdify?
+void ClothingActorImpl::applyVelocityChanges_LocksPhysX(float simulationDelta)
+{
+ if (mClothingSimulation == NULL)
+ {
+ return;
+ }
+
+ float pressure = mActorDesc->pressure;
+ if (pressure >= 0.0f)
+ {
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* mesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ if (!mesh->isClosed)
+ {
+ pressure = -1.0f;
+
+ if (bPressureWarning == 0)
+ {
+ bPressureWarning = 1;
+ if (!mesh->isClosed)
+ {
+ APEX_INTERNAL_ERROR("Pressure requires a closed mesh!\n");
+ }
+ else
+ {
+ APEX_INTERNAL_ERROR("Pressure only works on Physics LODs where all vertices are active!\n");
+ }
+ }
+ }
+ }
+
+ // did the simulation handle pressure already?
+ const bool needsPressure = !mClothingSimulation->applyPressure(pressure) && (pressure > 0.0f);
+
+ if (mInternalWindParams.Adaption > 0.0f || mVelocityCallback != NULL || mActorDesc->useVelocityClamping || needsPressure)
+ {
+ PX_ASSERT(mClothingScene);
+ PX_PROFILE_ZONE("ClothingActorImpl::applyVelocityChanges", GetInternalApexSDK()->getContextId());
+
+ const uint32_t numVertices = mClothingSimulation->sdkNumDeformableVertices;
+
+ // copy velocities to temp array
+ PxVec3* velocities = mClothingSimulation->skinnedPhysicsNormals;
+
+ // use the skinnedPhysics* buffers when possible
+ const bool doNotUseWritebackMemory = (bBoneMatricesChanged == 0 && bGlobalPoseChanged == 0);
+
+ if (doNotUseWritebackMemory)
+ {
+ velocities = (PxVec3*)GetInternalApexSDK()->getTempMemory(sizeof(PxVec3) * numVertices);
+ }
+
+ if (velocities == NULL)
+ {
+ return;
+ }
+
+ mClothingSimulation->getVelocities(velocities);
+ // positions never need to be read!
+
+ bool writeVelocities = false;
+
+ // get pointers
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ const PxVec3* assetNormals = physicalMesh->normals.buf;
+ const ClothingPhysicalMeshParametersNS::ConstrainCoefficient_Type* coeffs = physicalMesh->constrainCoefficients.buf;
+ const PxVec3* normals = (mClothingSimulation->sdkWritebackNormal != NULL) ? mClothingSimulation->sdkWritebackNormal : assetNormals;
+
+ PxVec3 windVelocity = mInternalWindParams.Velocity;
+ if (windVelocity.magnitudeSquared() > 0.0f && bInternalLocalSpaceSim == 1)
+ {
+#if _DEBUG
+ bool ok = true;
+ ok &= mInternalGlobalPose.column0.isNormalized();
+ ok &= mInternalGlobalPose.column1.isNormalized();
+ ok &= mInternalGlobalPose.column2.isNormalized();
+ if (!ok)
+ {
+ APEX_DEBUG_WARNING("Internal Global Pose is not normalized (Scale: %f %f %f). Velocities could be wrong.", mInternalGlobalPose.column0.magnitude(), mInternalGlobalPose.column1.magnitude(), mInternalGlobalPose.column2.magnitude());
+ }
+#endif
+ PxMat44 invGlobalPose = mInternalGlobalPose.inverseRT();
+ windVelocity = invGlobalPose.rotate(windVelocity);
+ }
+
+ // modify velocities (2.8.x) or set acceleration (3.x) based on wind
+ writeVelocities |= mClothingSimulation->applyWind(velocities, normals, coeffs, windVelocity, mInternalWindParams.Adaption, simulationDelta);
+
+ // clamp velocities
+ if (mActorDesc->useVelocityClamping)
+ {
+ PxBounds3 velocityClamp(mActorDesc->vertexVelocityClamp);
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ PxVec3 velocity = velocities[i];
+ velocity.x = PxClamp(velocity.x, velocityClamp.minimum.x, velocityClamp.maximum.x);
+ velocity.y = PxClamp(velocity.y, velocityClamp.minimum.y, velocityClamp.maximum.y);
+ velocity.z = PxClamp(velocity.z, velocityClamp.minimum.z, velocityClamp.maximum.z);
+ velocities[i] = velocity;
+ }
+ writeVelocities = true;
+ }
+
+ if (needsPressure)
+ {
+ PX_ALWAYS_ASSERT();
+ //writeVelocities = true;
+ }
+
+ if (mVelocityCallback != NULL)
+ {
+ PX_PROFILE_ZONE("ClothingActorImpl::velocityShader", GetInternalApexSDK()->getContextId());
+ writeVelocities |= mVelocityCallback->velocityShader(velocities, mClothingSimulation->sdkWritebackPosition, mClothingSimulation->sdkNumDeformableVertices);
+ }
+
+ if (writeVelocities)
+ {
+ if (mClothingScene->mClothingDebugRenderParams->Wind != 0.0f)
+ {
+ mWindDebugRendering.clear(); // no memory operation!
+
+ PxVec3* oldVelocities = (PxVec3*)GetInternalApexSDK()->getTempMemory(sizeof(PxVec3) * numVertices);
+ mClothingSimulation->getVelocities(oldVelocities);
+
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ mWindDebugRendering.pushBack(velocities[i] - oldVelocities[i]);
+ }
+
+ GetInternalApexSDK()->releaseTempMemory(oldVelocities);
+ }
+ else if (mWindDebugRendering.capacity() > 0)
+ {
+ mWindDebugRendering.reset();
+ }
+ mClothingSimulation->setVelocities(velocities);
+ }
+
+ if (doNotUseWritebackMemory)
+ {
+ GetInternalApexSDK()->releaseTempMemory(velocities);
+ }
+ }
+}
+
+
+
+// update the renderproxy to which the data of this frame is written
+void ClothingActorImpl::updateRenderProxy()
+{
+ PX_PROFILE_ZONE("ClothingActorImpl::updateRenderProxy", GetInternalApexSDK()->getContextId());
+ PX_ASSERT(mGraphicalMeshes[mCurrentGraphicalLodId].renderProxy == NULL);
+
+ // get a new render proxy from the pool
+ RenderMeshAssetIntl* renderMeshAsset = mAsset->getGraphicalMesh(mCurrentGraphicalLodId);
+ ClothingRenderProxyImpl* renderProxy = mClothingScene->getRenderProxy(renderMeshAsset, mActorDesc->fallbackSkinning, mClothingSimulation != NULL,
+ mOverrideMaterials, mActorDesc->morphGraphicalMeshNewPositions.buf,
+ &mGraphicalMeshes[mCurrentGraphicalLodId].morphTargetVertexOffsets[0]);
+
+ mGraphicalMeshes[mCurrentGraphicalLodId].renderProxy = renderProxy;
+}
+
+
+
+ClothingRenderProxy* ClothingActorImpl::acquireRenderProxy()
+{
+ PX_PROFILE_ZONE("ClothingActorImpl::acquireRenderProxy", GetInternalApexSDK()->getContextId());
+ if (!mClothingScene->isSimulating()) // after fetchResults
+ {
+ // For consistency, only return the new result after fetchResults.
+ // During simulation always return the old result
+ // even if the new result might be ready
+ waitForFetchResults();
+ }
+
+ mRenderProxyMutex.lock();
+ ClothingRenderProxyImpl* renderProxy = mRenderProxyReady;
+ mRenderProxyReady = NULL;
+ mRenderProxyMutex.unlock();
+
+ return renderProxy;
+}
+
+
+
+void ClothingActorImpl::getSimulation(const WriteBackInfo& writeBackInfo)
+{
+ const uint32_t physicalMeshId = mAsset->getGraphicalLod(mCurrentGraphicalLodId)->physicalMeshId;
+
+#if defined _DEBUG || PX_CHECKED
+ BackendFactory* factory = mAsset->getModuleClothing()->getBackendFactory(mBackendName);
+ PX_UNUSED(factory); // Strange warning fix
+#endif
+
+ NvParameterized::Interface* cookingInterface = mActorDesc->runtimeCooked;
+
+ if (cookingInterface != NULL)
+ {
+#if defined _DEBUG || PX_CHECKED
+ PX_ASSERT(factory->isMatch(cookingInterface->className()));
+#endif
+ }
+ else
+ {
+ cookingInterface = mAsset->getCookedData(mActorDesc->actorScale);
+#if defined _DEBUG || PX_CHECKED
+ PX_ASSERT(factory->isMatch(cookingInterface->className()));
+#endif
+ }
+
+ mClothingSimulation = mAsset->getSimulation(physicalMeshId, cookingInterface, mClothingScene);
+ if (mClothingSimulation != NULL)
+ {
+ mClothingSimulation->reenablePhysX(mActorProxy, mInternalGlobalPose);
+
+ mAsset->updateCollision(mClothingSimulation, mData.mInternalBoneMatricesCur, mCollisionPlanes, mCollisionConvexes, mCollisionSpheres, mCollisionCapsules, mCollisionTriangleMeshes, true);
+ mClothingSimulation->updateCollisionDescs(mActorDesc->actorDescTemplate, mActorDesc->shapeDescTemplate);
+
+ fillWritebackData_LocksPhysX(writeBackInfo);
+
+ mClothingSimulation->setPositions(mClothingSimulation->sdkWritebackPosition);
+
+ PX_ASSERT(mClothingSimulation->physicalMeshId != 0xffffffff);
+ PX_ASSERT(mClothingSimulation->submeshId != 0xffffffff);
+ }
+ else if (cookingInterface != NULL)
+ {
+ // will call fillWritebackData_LocksPhysX
+ createSimulation(physicalMeshId, cookingInterface, writeBackInfo);
+ }
+
+ bDirtyClothingTemplate = 1; // updates the clothing desc
+
+ if (mClothingSimulation != NULL)
+ {
+ // make sure skinPhysicalMesh does something
+ bBoneMatricesChanged = 1;
+ }
+}
+
+
+
+bool ClothingActorImpl::isCookedDataReady()
+{
+ // Move getResult of the Cooking Task outside because it would block the other cooking tasks when the actor stopped the simulation.
+ if (mActiveCookingTask == NULL)
+ {
+ return true;
+ }
+
+ PX_ASSERT(mActorDesc->runtimeCooked == NULL);
+ mActorDesc->runtimeCooked = mActiveCookingTask->getResult();
+ if (mActorDesc->runtimeCooked != NULL)
+ {
+ mActiveCookingTask = NULL; // will be deleted by the scene
+ return true;
+ }
+
+ if(mAsset->getModuleClothing()->allowAsyncCooking())
+ {
+ mClothingScene->submitCookingTask(NULL); //trigger tasks to be submitted
+ }
+
+ return false;
+}
+
+
+
+void ClothingActorImpl::createPhysX_LocksPhysX(float simulationDelta)
+{
+#if PX_PHYSICS_VERSION_MAJOR == 3
+ if (mPhysXScene == NULL)
+ {
+ return;
+ }
+#endif
+ if (mCurrentSolverIterations == 0)
+ {
+ return;
+ }
+
+ if (mClothingSimulation != NULL)
+ {
+ APEX_INTERNAL_ERROR("Physics mesh already created!");
+ return;
+ }
+
+ PX_PROFILE_ZONE("ClothingActorImpl::createPhysX", GetInternalApexSDK()->getContextId());
+
+ WriteBackInfo writeBackInfo;
+ writeBackInfo.simulationDelta = simulationDelta;
+
+ getSimulation(writeBackInfo);
+
+ if (mClothingSimulation == NULL)
+ {
+ mCurrentSolverIterations = 0;
+ }
+
+ updateConstraintCoefficients_LocksPhysX();
+
+ bBoneBufferDirty = 1;
+}
+
+
+
+void ClothingActorImpl::removePhysX_LocksPhysX()
+{
+ if (mClothingScene != NULL)
+ {
+ if (mClothingSimulation != NULL)
+ {
+ mAsset->returnSimulation(mClothingSimulation);
+ mClothingSimulation = NULL;
+ }
+ }
+ else
+ {
+ PX_ASSERT(mClothingSimulation == NULL);
+ }
+
+ bBoneBufferDirty = 1;
+}
+
+
+
+void ClothingActorImpl::changePhysicsMesh_LocksPhysX(uint32_t oldGraphicalLodId, float simulationDelta)
+{
+ PX_ASSERT(mClothingSimulation != NULL);
+ PX_ASSERT(mClothingScene != NULL);
+
+ WriteBackInfo writeBackInfo;
+ writeBackInfo.oldSimulation = mClothingSimulation;
+ writeBackInfo.oldGraphicalLodId = oldGraphicalLodId;
+ writeBackInfo.simulationDelta = simulationDelta;
+
+ getSimulation(writeBackInfo); // sets mClothingSimulation & will register the sim buffers
+ writeBackInfo.oldSimulation->swapCollision(mClothingSimulation);
+
+ mAsset->returnSimulation(writeBackInfo.oldSimulation);
+ writeBackInfo.oldSimulation = NULL;
+
+ updateConstraintCoefficients_LocksPhysX();
+
+ // make sure skinPhysicalMesh does something
+ bBoneMatricesChanged = 1;
+
+ // make sure actorData gets updated
+ reinitActorData();
+}
+
+
+
+void ClothingActorImpl::updateCollision_LocksPhysX(bool useInterpolatedMatrices)
+{
+ if (mClothingSimulation == NULL || (bBoneMatricesChanged == 0 && bGlobalPoseChanged == 0 && bActorCollisionChanged == 0))
+ {
+ return;
+ }
+
+ PX_ASSERT(mClothingScene != NULL);
+
+ const PxMat44* matrices = useInterpolatedMatrices ? mInternalInterpolatedBoneMatrices : mData.mInternalBoneMatricesCur;
+ mAsset->updateCollision(mClothingSimulation, matrices, mCollisionPlanes, mCollisionConvexes, mCollisionSpheres, mCollisionCapsules, mCollisionTriangleMeshes, bInternalTeleportDue != ClothingTeleportMode::Continuous);
+ bActorCollisionChanged = 0;
+
+ if (bDirtyActorTemplate == 1 || bDirtyShapeTemplate == 1)
+ {
+ mClothingSimulation->updateCollisionDescs(mActorDesc->actorDescTemplate, mActorDesc->shapeDescTemplate);
+
+ bDirtyActorTemplate = 0;
+ bDirtyShapeTemplate = 0;
+ }
+}
+
+
+
+void ClothingActorImpl::updateConstraintCoefficients_LocksPhysX()
+{
+ if (mClothingSimulation == NULL)
+ {
+ return;
+ }
+
+ const ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ const ClothingPhysicalMeshParametersNS::ConstrainCoefficient_Type* assetCoeffs = physicalMesh->constrainCoefficients.buf;
+
+ const float actorScale = mActorDesc->actorScale;
+
+ const float linearScale = (mInternalMaxDistanceScale.Multipliable ? mInternalMaxDistanceScale.Scale : 1.0f) * actorScale;
+ const float absoluteScale = mInternalMaxDistanceScale.Multipliable ? 0.0f : (physicalMesh->maximumMaxDistance * (1.0f - mInternalMaxDistanceScale.Scale));
+
+ const float reduceMaxDistance = mMaxDistReduction + absoluteScale;
+
+ mCurrentMaxDistanceBias = 0.0f;
+ ClothingMaterialLibraryParametersNS::ClothingMaterial_Type* clothingMaterial = getCurrentClothingMaterial();
+ if (clothingMaterial != NULL)
+ {
+ mCurrentMaxDistanceBias = clothingMaterial->maxDistanceBias;
+ }
+
+ mClothingSimulation->setConstrainCoefficients(assetCoeffs, reduceMaxDistance, linearScale, mCurrentMaxDistanceBias, actorScale);
+
+ // change is applied now
+ bMaxDistanceScaleChanged = 0;
+}
+
+
+
+void ClothingActorImpl::copyPositionAndNormal_NoPhysX(uint32_t numCopyVertices, SimulationAbstract* oldClothingSimulation)
+{
+ if (oldClothingSimulation == NULL)
+ {
+ return;
+ }
+
+ PX_ASSERT(numCopyVertices <= mClothingSimulation->sdkNumDeformableVertices && numCopyVertices <= oldClothingSimulation->sdkNumDeformableVertices);
+
+ memcpy(mClothingSimulation->sdkWritebackPosition, oldClothingSimulation->sdkWritebackPosition, sizeof(PxVec3) * numCopyVertices);
+
+ if (mClothingSimulation->sdkWritebackNormal != NULL)
+ {
+ memcpy(mClothingSimulation->sdkWritebackNormal, oldClothingSimulation->sdkWritebackNormal, sizeof(PxVec3) * numCopyVertices);
+ }
+}
+
+
+
+void ClothingActorImpl::copyAndComputeVelocities_LocksPhysX(uint32_t numCopyVertices, SimulationAbstract* oldClothingSimulation, PxVec3* velocities, float simulationDelta) const
+{
+ PX_ASSERT(mClothingScene != NULL);
+
+ // copy
+ if (oldClothingSimulation != NULL && numCopyVertices > 0)
+ {
+ oldClothingSimulation->getVelocities(velocities);
+ }
+
+ // compute velocity from old and current skinned pos
+ // TODO only skin when bone matrices have changed -> how to use bBoneMatricesChanged in a safe way?
+ const ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ PX_ASSERT(physicalMesh != NULL);
+
+ const uint32_t numVertices = physicalMesh->numSimulatedVertices;
+ PX_ASSERT(numVertices == mClothingSimulation->sdkNumDeformableVertices);
+ if (mData.mInternalBoneMatricesCur != NULL && mData.mInternalBoneMatricesPrev != NULL && simulationDelta > 0 && bBoneMatricesChanged == 1)
+ {
+ // cpu skinning on the physical mesh
+ for (uint32_t i = numCopyVertices; i < numVertices; i++)
+ {
+ velocities[i] = computeVertexVelFromAnim(i, physicalMesh, simulationDelta);
+ }
+ }
+ else
+ {
+ // no bone matrices, just set 0 velocities
+ memset(velocities + numCopyVertices, 0, sizeof(PxVec3) * (numVertices - numCopyVertices));
+ }
+
+ // set the velocities
+ mClothingSimulation->setVelocities(velocities);
+}
+
+
+
+void ClothingActorImpl::transferVelocities_LocksPhysX(const SimulationAbstract& oldClothingSimulation,
+ const ClothingPhysicalMeshParametersNS::SkinClothMapB_Type* pTCMB,
+ const ClothingPhysicalMeshParametersNS::SkinClothMapD_Type* pTCM,
+ uint32_t numVerticesInMap, const uint32_t* srcIndices, uint32_t numSrcIndices, uint32_t numSrcVertices,
+ PxVec3* oldVelocities, PxVec3* newVelocities, float simulationDelta)
+{
+ oldClothingSimulation.getVelocities(oldVelocities);
+
+ // data for skinning
+ const ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+
+ // copy velocities
+ uint32_t vertexIndex = (uint32_t) - 1;
+ uint32_t idx[3] =
+ {
+ (uint32_t) - 1,
+ (uint32_t) - 1,
+ (uint32_t) - 1,
+ };
+ for (uint32_t i = 0; i < numVerticesInMap; ++i)
+ {
+ if (pTCMB)
+ {
+ uint32_t faceIndex = pTCMB[i].faceIndex0;
+ idx[0] = (faceIndex >= numSrcIndices) ? srcIndices[faceIndex + 0] : (uint32_t) - 1;
+ idx[1] = (faceIndex >= numSrcIndices) ? srcIndices[faceIndex + 1] : (uint32_t) - 1;
+ idx[2] = (faceIndex >= numSrcIndices) ? srcIndices[faceIndex + 2] : (uint32_t) - 1;
+
+ vertexIndex = pTCMB[i].vertexIndexPlusOffset;
+ }
+ else if (pTCM)
+ {
+ idx[0] = pTCM[i].vertexIndex0;
+ idx[1] = pTCM[i].vertexIndex1;
+ idx[2] = pTCM[i].vertexIndex2;
+ vertexIndex = pTCM[i].vertexIndexPlusOffset;
+ //PX_ASSERT(i == pTCM[i].vertexIndexPlusOffset);
+ }
+ else
+ {
+ PX_ALWAYS_ASSERT();
+ }
+
+ if (vertexIndex >= mClothingSimulation->sdkNumDeformableVertices)
+ {
+ continue;
+ }
+
+ if (idx[0] >= numSrcVertices || idx[1] >= numSrcVertices || idx[2] >= numSrcVertices)
+ {
+ // compute from anim
+ if (mData.mInternalBoneMatricesPrev == NULL || simulationDelta == 0.0f)
+ {
+ newVelocities[vertexIndex] = PxVec3(0.0f);
+ }
+ else
+ {
+ newVelocities[vertexIndex] = computeVertexVelFromAnim(vertexIndex, physicalMesh, simulationDelta);
+ }
+ }
+ else
+ {
+ // transfer from old mesh
+ newVelocities[vertexIndex] = (oldVelocities[idx[0]] + oldVelocities[idx[1]] + oldVelocities[idx[2]]) / 3.0f;
+ }
+ }
+
+ mClothingSimulation->setVelocities(newVelocities);
+}
+
+
+
+PxVec3 ClothingActorImpl::computeVertexVelFromAnim(uint32_t vertexIndex, const ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh, float simulationDelta) const
+{
+ PX_ASSERT(simulationDelta > 0);
+ PX_ASSERT(mData.mInternalBoneMatricesCur != NULL);
+ PX_ASSERT(mData.mInternalBoneMatricesPrev != NULL);
+
+ const PxVec3* positions = physicalMesh->vertices.buf;
+ Simd4f simulationDeltaV = Simd4fScalarFactory(simulationDelta);
+
+ uint32_t numBoneIndicesPerVertex = physicalMesh->numBonesPerVertex;
+ const uint16_t* simBoneIndices = physicalMesh->boneIndices.buf;
+ const float* simBoneWeights = physicalMesh->boneWeights.buf;
+
+ const uint8_t* const optimizationData = physicalMesh->optimizationData.buf;
+ PX_ASSERT(optimizationData != NULL);
+
+ const uint8_t shift = 4 * (vertexIndex % 2);
+ const uint8_t numBones = uint8_t((optimizationData[vertexIndex / 2] >> shift) & 0x7);
+
+ Simd4f oldPosV = gSimd4fZero;
+ Simd4f newPosV = gSimd4fZero;
+ for (uint32_t j = 0; j < numBones; j++)
+ {
+ const Simd4f weightV = Simd4fScalarFactory(simBoneWeights[vertexIndex * numBoneIndicesPerVertex + j]);
+
+ const uint16_t index = simBoneIndices[vertexIndex * numBoneIndicesPerVertex + j];
+ PX_ASSERT(index < mAsset->getNumUsedBones());
+ const PxMat44& oldBoneV = (PxMat44&)mData.mInternalBoneMatricesPrev[index];
+ const PxMat44& boneV = (PxMat44&)mData.mInternalBoneMatricesCur[index];
+
+
+ //oldPos += oldBone * positions[vertexIndex] * weight;
+ Simd4f pV = applyAffineTransform(oldBoneV, createSimd3f(positions[vertexIndex]));
+ pV = pV * weightV;
+ oldPosV = oldPosV + pV;
+
+ //newPos += bone * positions[vertexIndex] * weight;
+ pV = applyAffineTransform(boneV, createSimd3f(positions[vertexIndex]));
+ pV = pV * weightV;
+ newPosV = newPosV + pV;
+
+ }
+
+ Simd4f velV = newPosV - oldPosV;
+ velV = velV / simulationDeltaV;
+
+ PxVec3 vel;
+ store3(&vel.x, velV);
+ return vel;
+}
+
+
+
+void ClothingActorImpl::createSimulation(uint32_t physicalMeshId, NvParameterized::Interface* cookedData, const WriteBackInfo& writeBackInfo)
+{
+ PX_ASSERT(mClothingSimulation == NULL);
+#if PX_PHYSICS_VERSION_MAJOR == 3
+ if (mPhysXScene == NULL)
+ {
+ return;
+ }
+#endif
+ if (bUnsucessfullCreation == 1)
+ {
+ return;
+ }
+
+ PX_PROFILE_ZONE("ClothingActorImpl::SDKCreateClothSoftbody", GetInternalApexSDK()->getContextId());
+
+ mClothingSimulation = mAsset->getModuleClothing()->getBackendFactory(mBackendName)->createSimulation(mClothingScene, mActorDesc->useHardwareCloth);
+
+ bool success = false;
+
+ if (mClothingSimulation != NULL)
+ {
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ const uint32_t numVertices = physicalMesh->numSimulatedVertices;
+ const uint32_t numIndices = physicalMesh->numSimulatedIndices;
+
+ mClothingSimulation->init(numVertices, numIndices, true);
+
+ PX_ASSERT(nvidia::strcmp(mAsset->getAssetNvParameterized()->className(), ClothingAssetParameters::staticClassName()) == 0);
+ const ClothingAssetParameters* assetParams = static_cast<const ClothingAssetParameters*>(mAsset->getAssetNvParameterized());
+ mClothingSimulation->initSimulation(assetParams->simulation);
+
+ mClothingSimulation->physicalMeshId = physicalMeshId;
+ fillWritebackData_LocksPhysX(writeBackInfo);
+
+ uint32_t* indices = NULL;
+ PxVec3* vertices = NULL;
+ if (physicalMesh != NULL)
+ {
+ indices = physicalMesh->indices.buf;
+ vertices = physicalMesh->vertices.buf;
+ }
+
+ success = mClothingSimulation->setCookedData(cookedData, mActorDesc->actorScale);
+
+ mAsset->initCollision(mClothingSimulation, mData.mInternalBoneMatricesCur, mCollisionPlanes, mCollisionConvexes, mCollisionSpheres, mCollisionCapsules, mCollisionTriangleMeshes, mActorDesc, mInternalGlobalPose, bInternalLocalSpaceSim == 1);
+
+ // sets positions to sdkWritebackPosition
+ ClothingMaterialLibraryParametersNS::ClothingMaterial_Type* clothingMaterial = getCurrentClothingMaterial();
+ success &= mClothingSimulation->initPhysics(physicalMeshId, indices, vertices, clothingMaterial, mInternalGlobalPose, mInternalScaledGravity, bInternalLocalSpaceSim == 1);
+
+ if (success)
+ {
+ mClothingSimulation->registerPhysX(mActorProxy);
+ }
+
+ mClothingScene->registerAsset(mAsset);
+ }
+
+ if (!success)
+ {
+ bUnsucessfullCreation = 1;
+
+ if (mClothingSimulation != NULL)
+ {
+ PX_DELETE_AND_RESET(mClothingSimulation);
+ }
+ }
+}
+
+
+
+float ClothingActorImpl::getCost() const
+{
+ ClothingMaterialLibraryParametersNS::ClothingMaterial_Type* clothingMaterial = getCurrentClothingMaterial();
+ const uint32_t solverIterations = clothingMaterial != NULL ? clothingMaterial->solverIterations : 5;
+
+ float cost = 0.0f;
+ if (mClothingSimulation != NULL)
+ {
+ cost = static_cast<float>(solverIterations * mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId)->numSimulatedVertices);
+ }
+ return cost;
+}
+
+
+
+uint32_t ClothingActorImpl::getGraphicalMeshIndex(uint32_t lod) const
+{
+ for (uint32_t i = 1; i < mAsset->getNumGraphicalMeshes(); i++)
+ {
+ if (mAsset->getGraphicalLod(i)->lod > lod)
+ {
+ return i - 1;
+ }
+ }
+
+ // not found, return last index
+ return mAsset->getNumGraphicalMeshes() - 1;
+}
+
+
+
+void ClothingActorImpl::lodTick_LocksPhysX(float simulationDelta)
+{
+ PX_PROFILE_ZONE("ClothingActorImpl::lodTick", GetInternalApexSDK()->getContextId());
+
+ bool actorCooked = isCookedDataReady();
+
+ // update graphics lod
+ // hlanker: active needs a lock if parallel active checks are allowed (like parallel updateRenderResource)
+ for (uint32_t i = 0; i < mGraphicalMeshes.size(); i++)
+ {
+ mGraphicalMeshes[i].active = false;
+ }
+
+ const uint32_t newGraphicalLodId = getGraphicalMeshIndex(mBufferedGraphicalLod);
+
+ if (newGraphicalLodId >= mGraphicalMeshes.size())
+ {
+ return;
+ }
+
+ mGraphicalMeshes[newGraphicalLodId].active = true;
+
+ uint32_t oldPhysicalMeshId = mAsset->getGraphicalLod(mCurrentGraphicalLodId)->physicalMeshId;
+ const bool physicalMeshChanged = oldPhysicalMeshId != mAsset->getGraphicalLod(newGraphicalLodId)->physicalMeshId;
+ if (physicalMeshChanged)
+ {
+ bInternalScaledGravityChanged = 1;
+ }
+
+ const bool graphicalLodChanged = newGraphicalLodId != mCurrentGraphicalLodId;
+ const uint32_t oldGraphicalLodId = mCurrentGraphicalLodId;
+ mCurrentGraphicalLodId = newGraphicalLodId;
+
+ if (mForceSimulation < 0)
+ {
+ mForceSimulation = 1;
+ }
+ bIsSimulationOn = mForceSimulation > 0? false : true;
+
+ float maxDistReductionTarget = 0.f;
+ if (graphicalLodChanged)
+ {
+ // interrupt blending when switching graphical lod
+ mMaxDistReduction = maxDistReductionTarget;
+ }
+
+ // must not enter here if graphical lod changed. otherwise we'll assert in updateConstraintCoefficients because of a pointer mismatch
+ if (mAsset->getGraphicalLod(mCurrentGraphicalLodId)->physicalMeshId != uint32_t(-1) && !graphicalLodChanged)
+ {
+ const ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+
+ // update maxDistReductionTarget
+ // if there is no simulation bulk, wait with reducing the maxDistReductionTarget
+ if (mMaxDistReduction != maxDistReductionTarget && mClothingSimulation != NULL)
+ {
+ const float maxBlendDistance = physicalMesh->maximumMaxDistance * (mInternalMaxDistanceBlendTime > 0 ? (simulationDelta / mInternalMaxDistanceBlendTime) : 1.0f);
+ if (mMaxDistReduction == -1.0f)
+ {
+ // initialization
+ mMaxDistReduction = maxDistReductionTarget;
+ }
+ else if (PxAbs(maxDistReductionTarget - mMaxDistReduction) < maxBlendDistance)
+ {
+ // distance multiplier target reached
+ mMaxDistReduction = maxDistReductionTarget;
+ }
+ else if (bBlendingAllowed == 0)
+ {
+ // No blending
+ mMaxDistReduction = maxDistReductionTarget;
+ }
+ else
+ {
+ // move towards distance multiplier target
+ mMaxDistReduction += PxSign(maxDistReductionTarget - mMaxDistReduction) * maxBlendDistance;
+ }
+ updateConstraintCoefficients_LocksPhysX();
+ }
+ else if (mCurrentMaxDistanceBias != mClothingMaterial.maxDistanceBias)
+ {
+ // update them if the max distance bias changes
+ updateConstraintCoefficients_LocksPhysX();
+ }
+ else if (bMaxDistanceScaleChanged == 1)
+ {
+ updateConstraintCoefficients_LocksPhysX();
+ }
+ }
+
+
+ // switch immediately when simulation was switched off or when graphical lod has changed, otherwise wait until finished blending
+ if (mMaxDistReduction >= maxDistReductionTarget)
+ {
+ ClothingMaterialLibraryParametersNS::ClothingMaterial_Type* clothingMaterial = getCurrentClothingMaterial();
+ const uint32_t solverIterations = clothingMaterial != NULL ? clothingMaterial->solverIterations : 5;
+
+ uint32_t solverIterationsTarget = solverIterations;
+
+ bool solverIterChanged = (mCurrentSolverIterations != solverIterationsTarget);
+ mCurrentSolverIterations = solverIterationsTarget;
+ if (actorCooked && mCurrentSolverIterations > 0)
+ {
+ if (mClothingSimulation == NULL)
+ {
+ createPhysX_LocksPhysX(simulationDelta);
+ }
+ else if (graphicalLodChanged)
+ {
+ PX_ASSERT(!physicalMeshChanged || mCurrentGraphicalLodId != oldGraphicalLodId);
+ changePhysicsMesh_LocksPhysX(oldGraphicalLodId, simulationDelta);
+ }
+
+ if (solverIterChanged && mClothingSimulation != NULL)
+ {
+ mClothingSimulation->setSolverIterations(mCurrentSolverIterations);
+ }
+
+ bInternalFrozen = bBufferedFrozen;
+ freeze_LocksPhysX(bInternalFrozen == 1);
+ bUpdateFrozenFlag = 0;
+ }
+ else
+ {
+ mCurrentSolverIterations = 0;
+
+ if (!mActorDesc->freezeByLOD)
+ {
+ removePhysX_LocksPhysX();
+ }
+ else
+ {
+ freeze_LocksPhysX(true);
+ bInternalFrozen = 1;
+ bUpdateFrozenFlag = 0;
+ }
+ }
+ }
+
+ // get render proxy for this simulate call
+ updateRenderProxy();
+}
+
+
+
+void ClothingActorImpl::visualizeSkinnedPositions(RenderDebugInterface& renderDebug, float positionRadius, bool maxDistanceOut, bool maxDistanceIn) const
+{
+#ifdef WITHOUT_DEBUG_VISUALIZE
+ PX_UNUSED(renderDebug);
+ PX_UNUSED(positionRadius);
+ PX_UNUSED(maxDistanceOut);
+ PX_UNUSED(maxDistanceIn);
+#else
+ using RENDER_DEBUG::DebugColors;
+ using RENDER_DEBUG::DebugRenderState;
+
+ if (mClothingSimulation != NULL)
+ {
+ const float pointRadius = positionRadius * 0.1f;
+ PX_ASSERT(mClothingSimulation->skinnedPhysicsPositions != NULL);
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ ClothingPhysicalMeshParametersNS::ConstrainCoefficient_Type* coeffs = physicalMesh->constrainCoefficients.buf;
+
+
+ const float actorScale = mActorDesc->actorScale;
+
+ const float linearScale = (mInternalMaxDistanceScale.Multipliable ? mInternalMaxDistanceScale.Scale : 1.0f) * actorScale;
+ const float absoluteScale = mInternalMaxDistanceScale.Multipliable ? 0.0f : (physicalMesh->maximumMaxDistance * (1.0f - mInternalMaxDistanceScale.Scale));
+
+ const float reduceMaxDistance = mMaxDistReduction + absoluteScale;
+
+ const float maxMotionRadius = (physicalMesh->maximumMaxDistance - reduceMaxDistance) * linearScale;
+
+ const uint32_t colorGreen = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Green);
+ const uint32_t colorBlue = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Blue);
+
+ const uint32_t numVertices = physicalMesh->numSimulatedVertices;
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ const float maxDistance = PxMax(0.0f, coeffs[i].maxDistance - reduceMaxDistance) * linearScale;
+ uint32_t color;
+ if (maxDistance < 0.0f)
+ {
+ color = colorGreen;
+ }
+ else if (maxDistance == 0.0f)
+ {
+ color = colorBlue;
+ }
+ else
+ {
+ uint32_t b = (uint32_t)(255 * maxDistance / maxMotionRadius);
+ color = (b << 16) + (b << 8) + b;
+ }
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(color);
+ //RENDER_DEBUG_IFACE(&renderDebug)->setCurrentDisplayTime(0.1f);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugPoint(mClothingSimulation->skinnedPhysicsPositions[i], pointRadius);
+ //RENDER_DEBUG_IFACE(&renderDebug)->setCurrentDisplayTime();
+
+ if (maxDistanceOut)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(
+ mClothingSimulation->skinnedPhysicsPositions[i],
+ mClothingSimulation->skinnedPhysicsPositions[i] + mClothingSimulation->skinnedPhysicsNormals[i] * maxDistance
+ );
+ }
+ if (maxDistanceIn)
+ {
+ float collDist = PxMax(0.0f, coeffs[i].collisionSphereDistance * actorScale);
+ //float scaledMaxDist = PxMax(0.0f, maxDistance - reduceMaxDistance);
+ if (coeffs[i].collisionSphereRadius > 0.0f && collDist < maxDistance)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(
+ mClothingSimulation->skinnedPhysicsPositions[i] - mClothingSimulation->skinnedPhysicsNormals[i] * collDist,
+ mClothingSimulation->skinnedPhysicsPositions[i]
+ );
+ }
+ else
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(
+ mClothingSimulation->skinnedPhysicsPositions[i] - mClothingSimulation->skinnedPhysicsNormals[i] * maxDistance,
+ mClothingSimulation->skinnedPhysicsPositions[i]
+ );
+ }
+ }
+ }
+ }
+#endif
+}
+
+
+
+void ClothingActorImpl::visualizeSpheres(RenderDebugInterface& renderDebug, const PxVec3* positions, uint32_t numPositions, float radius, uint32_t color, bool wire) const
+{
+#ifdef WITHOUT_DEBUG_VISUALIZE
+ PX_UNUSED(renderDebug);
+ PX_UNUSED(positions);
+ PX_UNUSED(numPositions);
+ PX_UNUSED(radius);
+ PX_UNUSED(color);
+ PX_UNUSED(wire);
+#else
+ RENDER_DEBUG_IFACE(&renderDebug)->pushRenderState();
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(color);
+
+ if (wire)
+ {
+ PxMat44 cameraPose = mClothingScene->mApexScene->getViewMatrix(0).inverseRT();
+ cameraPose = mInternalGlobalPose.inverseRT() * cameraPose;
+ PxVec3 cameraPos = cameraPose.getPosition();
+ for (uint32_t i = 0; i < numPositions; ++i)
+ {
+ // face camera
+ PxVec3 y = positions[i] - cameraPos;
+ y.normalize();
+ PxPlane p(y, 0.0f);
+ PxVec3 x = p.project(cameraPose.column0.getXYZ());
+ x.normalize();
+ PxMat44 pose(x, y, x.cross(y), positions[i]);
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setPose(pose);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugCircle(PxVec3(0.0f), radius, 2);
+ }
+ }
+ else
+ {
+ PxMat44 pose(PxIdentity);
+ for (uint32_t i = 0; i < numPositions; ++i)
+ {
+ pose.setPosition(positions[i]);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugSphere(pose.getPosition(), radius, 0);
+ }
+ }
+ RENDER_DEBUG_IFACE(&renderDebug)->popRenderState();
+#endif
+}
+
+
+
+void ClothingActorImpl::visualizeBackstop(RenderDebugInterface& renderDebug) const
+{
+#ifdef WITHOUT_DEBUG_VISUALIZE
+ PX_UNUSED(renderDebug);
+#else
+ using RENDER_DEBUG::DebugColors;
+ using RENDER_DEBUG::DebugRenderState;
+
+ if (mClothingSimulation != NULL)
+ {
+ PX_ASSERT(mClothingSimulation->skinnedPhysicsPositions != NULL);
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ ClothingPhysicalMeshParametersNS::ConstrainCoefficient_Type* coeffs = physicalMesh->constrainCoefficients.buf;
+ uint32_t* indices = physicalMesh->indices.buf;
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Red));
+
+ const float actorScale = mActorDesc->actorScale;
+
+ if (!physicalMesh->isTetrahedralMesh)
+ {
+ // render collision surface as triangle-mesh
+ const uint32_t colorDarkRed = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::DarkRed);
+ const uint32_t colorDarkBlue = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::DarkBlue);
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentState(DebugRenderState::SolidShaded);
+ for (uint32_t i = 0; i < physicalMesh->numSimulatedIndices; i += 3)
+ {
+ PxVec3 p[3];
+
+ bool show = true;
+
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ const uint32_t index = indices[i + j];
+ if (coeffs[index].collisionSphereRadius <= 0.0f)
+ {
+ show = false;
+ break;
+ }
+
+ const float collisionSphereDistance = coeffs[index].collisionSphereDistance * actorScale;
+ if (collisionSphereDistance < 0.0f)
+ {
+ p[j] = mClothingSimulation->skinnedPhysicsPositions[index];
+ }
+ else
+ {
+ p[j] = mClothingSimulation->skinnedPhysicsPositions[index]
+ - (mClothingSimulation->skinnedPhysicsNormals[index] * collisionSphereDistance);
+ }
+ }
+
+ if (show)
+ {
+ // frontface
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorDarkRed);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(p[0], p[2], p[1]);
+
+ // backface
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorDarkBlue);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(p[0], p[1], p[2]);
+ }
+ }
+ }
+ }
+#endif
+}
+
+
+
+void ClothingActorImpl::visualizeBackstopPrecise(RenderDebugInterface& renderDebug, float scale) const
+{
+#ifdef WITHOUT_DEBUG_VISUALIZE
+ PX_UNUSED(renderDebug);
+ PX_UNUSED(scale);
+#else
+ using RENDER_DEBUG::DebugColors;
+ using RENDER_DEBUG::DebugRenderState;
+
+ if (mClothingSimulation != NULL)
+ {
+ PX_ASSERT(mClothingSimulation->skinnedPhysicsPositions != NULL);
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = mAsset->getPhysicalMeshFromLod(mCurrentGraphicalLodId);
+ ClothingPhysicalMeshParametersNS::ConstrainCoefficient_Type* coeffs = physicalMesh->constrainCoefficients.buf;
+
+ const float shortestEdgeLength = physicalMesh->averageEdgeLength * 0.5f * scale;
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentState(DebugRenderState::SolidShaded);
+
+ const uint32_t colorRed = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Red);
+ const uint32_t colorBlue = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Blue);
+
+ const float actorScale = mActorDesc->actorScale;
+
+ for (uint32_t i = 0; i < mClothingSimulation->sdkNumDeformableVertices; i++)
+ {
+ if (coeffs[i].collisionSphereRadius <= 0.0f)
+ {
+ continue;
+ }
+
+ PxVec3 skinnedPosition = mClothingSimulation->skinnedPhysicsPositions[i];
+ if (coeffs[i].collisionSphereDistance > 0.0f)
+ {
+ skinnedPosition -= mClothingSimulation->skinnedPhysicsNormals[i] * (coeffs[i].collisionSphereDistance * actorScale);
+ }
+
+ const float collisionSphereRadius = coeffs[i].collisionSphereRadius * actorScale;
+
+ const PxVec3 sphereCenter = skinnedPosition - mClothingSimulation->skinnedPhysicsNormals[i] * collisionSphereRadius;
+
+ PxVec3 centerToSim = mClothingSimulation->sdkWritebackPosition[i] - sphereCenter;
+ centerToSim.normalize();
+ PxVec3 right = centerToSim.cross(PxVec3(0.0f, 1.0f, 0.0f));
+ PxVec3 up = right.cross(centerToSim);
+ PxVec3 target = sphereCenter + centerToSim * collisionSphereRadius;
+
+ right *= shortestEdgeLength;
+ up *= shortestEdgeLength;
+
+ const float r = collisionSphereRadius;
+ const float back = r - sqrtf(r * r - shortestEdgeLength * shortestEdgeLength);
+
+ // move the verts a bit back such that they are on the sphere
+ centerToSim *= back;
+
+ PxVec3 l1 = target + right - centerToSim;
+ PxVec3 l2 = target + up - centerToSim;
+ PxVec3 l3 = target - right - centerToSim;
+ PxVec3 l4 = target - up - centerToSim;
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorRed);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(target, l1, l2);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(target, l2, l3);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(target, l3, l4);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(target, l4, l1);
+#if 1
+ // PH: also render backfaces, in blue
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorBlue);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(target, l1, l4);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(target, l4, l3);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(target, l3, l2);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(target, l2, l1);
+#endif
+ }
+ }
+#endif
+}
+
+
+
+void ClothingActorImpl::visualizeBoneConnections(RenderDebugInterface& renderDebug, const PxVec3* positions, const uint16_t* boneIndices,
+ const float* boneWeights, uint32_t numBonesPerVertex, uint32_t numVertices) const
+{
+#ifdef WITHOUT_DEBUG_VISUALIZE
+ PX_UNUSED(renderDebug);
+ PX_UNUSED(positions);
+ PX_UNUSED(boneIndices);
+ PX_UNUSED(boneWeights);
+ PX_UNUSED(numBonesPerVertex);
+ PX_UNUSED(numVertices);
+#else
+ const PxMat44* matrices = mData.mInternalBoneMatricesCur;
+ if (matrices == NULL)
+ {
+ return;
+ }
+
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ // skin the vertex
+ PxVec3 pos(0.0f);
+ for (uint32_t j = 0; j < numBonesPerVertex; j++)
+ {
+ float boneWeight = (boneWeights == NULL) ? 1.0f : boneWeights[i * numBonesPerVertex + j];
+ if (boneWeight > 0.0f)
+ {
+ uint32_t boneIndex = boneIndices[i * numBonesPerVertex + j];
+ pos += matrices[boneIndex].transform(positions[i]) * boneWeight;
+ }
+ }
+
+ // draw the lines to the bones
+ for (uint32_t j = 0; j < numBonesPerVertex; j++)
+ {
+ float boneWeight = (boneWeights == NULL) ? 1.0f : boneWeights[i * numBonesPerVertex + j];
+ if (boneWeight > 0.0f)
+ {
+ uint32_t boneIndex = boneIndices[i * numBonesPerVertex + j];
+ uint32_t b = (uint32_t)(255 * boneWeight);
+ uint32_t color = (b << 16) + (b << 8) + b;
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(color);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(pos, matrices[boneIndex].transform(mAsset->getBoneBindPose(boneIndex).getPosition()));
+ }
+ }
+ }
+#endif
+}
+
+
+
+// collision functions
+ClothingPlane* ClothingActorImpl::createCollisionPlane(const PxPlane& plane)
+{
+ ClothingPlane* actorPlane = NULL;
+ actorPlane = PX_NEW(ClothingPlaneImpl)(mCollisionPlanes, *this, plane);
+ PX_ASSERT(actorPlane != NULL);
+ bActorCollisionChanged = true;
+ return actorPlane;
+}
+
+ClothingConvex* ClothingActorImpl::createCollisionConvex(ClothingPlane** planes, uint32_t numPlanes)
+{
+ if (numPlanes < 3)
+ return NULL;
+
+ ClothingConvex* convex = NULL;
+ convex = PX_NEW(ClothingConvexImpl)(mCollisionConvexes, *this, planes, numPlanes);
+ PX_ASSERT(convex != NULL);
+ bActorCollisionChanged = true;
+
+ return convex;
+}
+
+ClothingSphere* ClothingActorImpl::createCollisionSphere(const PxVec3& position, float radius)
+{
+
+ ClothingSphere* actorSphere = NULL;
+ actorSphere = PX_NEW(ClothingSphereImpl)(mCollisionSpheres, *this, position, radius);
+ PX_ASSERT(actorSphere != NULL);
+ bActorCollisionChanged = true;
+ return actorSphere;
+}
+
+ClothingCapsule* ClothingActorImpl::createCollisionCapsule(ClothingSphere& sphere1, ClothingSphere& sphere2)
+{
+ ClothingCapsule* actorCapsule = NULL;
+ actorCapsule = PX_NEW(ClothingCapsuleImpl)(mCollisionCapsules, *this, sphere1, sphere2);
+ PX_ASSERT(actorCapsule != NULL);
+ bActorCollisionChanged = true;
+ return actorCapsule;
+}
+
+ClothingTriangleMesh* ClothingActorImpl::createCollisionTriangleMesh()
+{
+ ClothingTriangleMesh* triMesh = NULL;
+ triMesh = PX_NEW(ClothingTriangleMeshImpl)(mCollisionTriangleMeshes, *this);
+ PX_ASSERT(triMesh != NULL);
+ bActorCollisionChanged = true;
+ return triMesh;
+}
+
+
+void ClothingActorImpl::releaseCollision(ClothingCollisionImpl& collision)
+{
+ bActorCollisionChanged = 1;
+ if (mClothingSimulation != NULL)
+ {
+ mClothingSimulation->releaseCollision(collision);
+ }
+ collision.destroy();
+}
+
+#if APEX_UE4
+void ClothingActorImpl::simulate(PxF32 dt)
+{
+ // before tick task
+ tickSynchBeforeSimulate_LocksPhysX(dt, dt, 0, 1);
+
+ if (mClothingSimulation != NULL)
+ mClothingSimulation->simulate(dt);
+
+ // during tick task
+ tickAsynch_NoPhysX(); // this is a no-op
+
+ // start fetch result task
+ mFetchResultsRunningMutex.lock();
+ mFetchResultsRunning = true;
+ mFetchResultsSync.reset();
+ mFetchResultsRunningMutex.unlock();
+
+ // fetch result task
+ fetchResults();
+ getActorData().tickSynchAfterFetchResults_LocksPhysX(); // this is a no-op
+ setFetchResultsSync();
+}
+#endif
+
+}
+} // namespace nvidia
+
diff --git a/APEX_1.4/module/clothing/src/ClothingActorTasks.cpp b/APEX_1.4/module/clothing/src/ClothingActorTasks.cpp
new file mode 100644
index 00000000..31407a78
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/ClothingActorTasks.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+
+#include "ApexDefs.h"
+#include "ClothingActorTasks.h"
+#include "ClothingActorImpl.h"
+#include "ModulePerfScope.h"
+
+
+namespace nvidia
+{
+namespace clothing
+{
+
+void ClothingActorBeforeTickTask::run()
+{
+#if APEX_UE4 // SHORTCUT_CLOTH_TASKS
+ mActor->simulate(mDeltaTime);
+#else
+#ifdef PROFILE
+ PIXBeginNamedEvent(0, "ClothingActorBeforeTickTask");
+#endif
+ //PX_ASSERT(mDeltaTime > 0.0f); // need to allow simulate(0) calls
+ mActor->tickSynchBeforeSimulate_LocksPhysX(mDeltaTime, mSubstepSize, 0, mNumSubSteps);
+#ifdef PROFILE
+ PIXEndNamedEvent();
+#endif
+#endif // SHORTCUT_CLOTH_TASKS
+}
+
+
+
+const char* ClothingActorBeforeTickTask::getName() const
+{
+ return "ClothingActorImpl::BeforeTickTask";
+}
+
+
+// --------------------------------------------------------------------
+
+
+void ClothingActorDuringTickTask::run()
+{
+ mActor->tickAsynch_NoPhysX();
+}
+
+
+
+const char* ClothingActorDuringTickTask::getName() const
+{
+ return "ClothingActorImpl::DuringTickTask";
+}
+
+// --------------------------------------------------------------------
+
+void ClothingActorFetchResultsTask::run()
+{
+#ifdef PROFILE
+ PIXBeginNamedEvent(0, "ClothingActorFetchResultsTask");
+#endif
+ mActor->fetchResults();
+ ClothingActorData& actorData = mActor->getActorData();
+
+ actorData.tickSynchAfterFetchResults_LocksPhysX();
+#ifdef PROFILE
+ PIXEndNamedEvent();
+#endif
+#if APEX_UE4
+ mActor->setFetchResultsSync();
+#endif
+}
+
+
+#if APEX_UE4
+void ClothingActorFetchResultsTask::release()
+{
+ PxTask::release();
+}
+#endif
+
+
+const char* ClothingActorFetchResultsTask::getName() const
+{
+ return "ClothingActorImpl::FetchResultsTask";
+}
+
+
+}
+}
+
+
diff --git a/APEX_1.4/module/clothing/src/ClothingAssetAuthoringImpl.cpp b/APEX_1.4/module/clothing/src/ClothingAssetAuthoringImpl.cpp
new file mode 100644
index 00000000..cd7d83aa
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/ClothingAssetAuthoringImpl.cpp
@@ -0,0 +1,3931 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+
+#include "ApexDefs.h"
+#include "ApexUsingNamespace.h"
+
+#ifndef WITHOUT_APEX_AUTHORING
+
+#include "ClothingAssetAuthoringImpl.h"
+#include "ApexMeshHash.h"
+#include "PsSort.h"
+#include "ApexPermute.h"
+#include "CookingPhysX.h"
+#include "ClothingGlobals.h"
+#include "ClothingPhysicalMeshImpl.h"
+
+#define MAX_DISTANCE_NAME "MAX_DISTANCE"
+#define COLLISION_SPHERE_DISTANCE_NAME "COLLISION_SPHERE_DISTANCE"
+#define COLLISION_SPHERE_RADIUS_NAME "COLLISION_SPHERE_RADIUS"
+#define USED_FOR_PHYSICS_NAME "USED_FOR_PHYSICS"
+
+#define LATCH_TO_NEAREST_SLAVE_NAME "LATCH_TO_NEAREST_SLAVE"
+#define LATCH_TO_NEAREST_MASTER_NAME "LATCH_TO_NEAREST_MASTER"
+
+#include "AbstractMeshDescription.h"
+#include "RenderMesh.h"
+
+#include "ApexSDKIntl.h"
+#include "AuthorableObjectIntl.h"
+
+#include "PsMathUtils.h"
+
+
+namespace nvidia
+{
+namespace clothing
+{
+
+struct uint32_t_3
+{
+ uint32_t indices[3];
+};
+
+
+
+class TriangleGreater_3
+{
+public:
+ TriangleGreater_3() {}
+
+ TriangleGreater_3(uint32_t* deformableIndices, ClothingConstrainCoefficients* constrainCoeffs) :
+ mDeformableIndices(deformableIndices),
+ mConstrainCoeffs(constrainCoeffs)
+ {}
+
+ inline bool operator()(uint32_t_3 a, uint32_t_3 b) const
+ {
+ float maxDistA = mConstrainCoeffs[mDeformableIndices[a.indices[0]]].maxDistance;
+ float maxDistB = mConstrainCoeffs[mDeformableIndices[b.indices[0]]].maxDistance;
+ bool aHasEqualMaxDistances = (maxDistA == mConstrainCoeffs[mDeformableIndices[a.indices[1]]].maxDistance);
+ bool bHasEqualMaxDistances = (maxDistB == mConstrainCoeffs[mDeformableIndices[b.indices[1]]].maxDistance);
+ for (uint32_t i = 1; i < 3; i++)
+ {
+ if (aHasEqualMaxDistances)
+ {
+ aHasEqualMaxDistances = (mConstrainCoeffs[mDeformableIndices[a.indices[i - 1]]].maxDistance == mConstrainCoeffs[mDeformableIndices[a.indices[i]]].maxDistance);
+ }
+ if (bHasEqualMaxDistances)
+ {
+ bHasEqualMaxDistances = (mConstrainCoeffs[mDeformableIndices[b.indices[i - 1]]].maxDistance == mConstrainCoeffs[mDeformableIndices[b.indices[i]]].maxDistance);
+ }
+ maxDistA = PxMax(maxDistA, mConstrainCoeffs[mDeformableIndices[a.indices[i]]].maxDistance);
+ maxDistB = PxMax(maxDistB, mConstrainCoeffs[mDeformableIndices[b.indices[i]]].maxDistance);
+ }
+
+ if (maxDistA == maxDistB)
+ {
+ return aHasEqualMaxDistances && !bHasEqualMaxDistances;
+ }
+
+ return maxDistA > maxDistB;
+ }
+
+private:
+ uint32_t* mDeformableIndices;
+ ClothingConstrainCoefficients* mConstrainCoeffs;
+};
+
+
+
+struct uint32_t_4
+{
+ uint32_t indices[4];
+};
+
+
+
+class TriangleGreater_4
+{
+public:
+ TriangleGreater_4() {}
+
+ TriangleGreater_4(uint32_t* deformableIndices, ClothingConstrainCoefficients* constrainCoeffs) :
+ mDeformableIndices(deformableIndices),
+ mConstrainCoeffs(constrainCoeffs)
+ {}
+
+ inline bool operator()(uint32_t_4 a, uint32_t_4 b) const
+ {
+ float maxDistA = mConstrainCoeffs[mDeformableIndices[a.indices[0]]].maxDistance;
+ float maxDistB = mConstrainCoeffs[mDeformableIndices[b.indices[0]]].maxDistance;
+ bool aHasEqualMaxDistances = (maxDistA == mConstrainCoeffs[mDeformableIndices[a.indices[1]]].maxDistance);
+ bool bHasEqualMaxDistances = (maxDistB == mConstrainCoeffs[mDeformableIndices[b.indices[1]]].maxDistance);
+ for (uint32_t i = 1; i < 4; i++)
+ {
+ if (aHasEqualMaxDistances)
+ {
+ aHasEqualMaxDistances = (mConstrainCoeffs[mDeformableIndices[a.indices[i - 1]]].maxDistance == mConstrainCoeffs[mDeformableIndices[a.indices[i]]].maxDistance);
+ }
+ if (bHasEqualMaxDistances)
+ {
+ bHasEqualMaxDistances = (mConstrainCoeffs[mDeformableIndices[b.indices[i - 1]]].maxDistance == mConstrainCoeffs[mDeformableIndices[b.indices[i]]].maxDistance);
+ }
+ maxDistA = PxMax(maxDistA, mConstrainCoeffs[mDeformableIndices[a.indices[i]]].maxDistance);
+ maxDistB = PxMax(maxDistB, mConstrainCoeffs[mDeformableIndices[b.indices[i]]].maxDistance);
+ }
+
+ if (maxDistA == maxDistB)
+ {
+ return aHasEqualMaxDistances && !bHasEqualMaxDistances;
+ }
+
+ return maxDistA > maxDistB;
+ }
+
+private:
+ uint32_t* mDeformableIndices;
+ ClothingConstrainCoefficients* mConstrainCoeffs;
+};
+
+
+
+class BoneEntryPredicate
+{
+public:
+ bool operator()(const ClothingAssetParametersNS::BoneEntry_Type& a, const ClothingAssetParametersNS::BoneEntry_Type& b) const
+ {
+ // mesh referenced bones first
+ if (a.numMeshReferenced == 0 && b.numMeshReferenced > 0)
+ {
+ return false;
+ }
+ if (a.numMeshReferenced > 0 && b.numMeshReferenced == 0)
+ {
+ return true;
+ }
+
+ if (a.numMeshReferenced == 0) // both are 0 as they have to be equal here
+ {
+ PX_ASSERT(b.numMeshReferenced == 0);
+
+ // RB referenced bones next, this will leave non referenced bones at the end
+ if (a.numRigidBodiesReferenced != b.numRigidBodiesReferenced)
+ {
+ return a.numRigidBodiesReferenced > b.numRigidBodiesReferenced;
+ }
+ else
+ {
+ return a.externalIndex < b.externalIndex;
+ }
+ }
+
+ return a.externalIndex < b.externalIndex;
+ }
+};
+
+
+
+class ActorEntryPredicate
+{
+public:
+ bool operator()(const ClothingAssetParametersNS::ActorEntry_Type& a, const ClothingAssetParametersNS::ActorEntry_Type& b) const
+ {
+ if (a.boneIndex < b.boneIndex)
+ {
+ return true;
+ }
+ else if (a.boneIndex > b.boneIndex)
+ {
+ return false;
+ }
+ return a.convexVerticesCount < b.convexVerticesCount;
+ }
+};
+
+
+
+static bool getClosestVertex(RenderMeshAssetAuthoringIntl* renderMeshAsset, const PxVec3& position, uint32_t& resultSubmeshIndex,
+ uint32_t& resultGraphicalVertexIndex, const char* bufferName, bool ignoreUnused)
+{
+ resultSubmeshIndex = 0;
+ resultGraphicalVertexIndex = 0;
+
+ bool found = false;
+
+ if (renderMeshAsset != NULL)
+ {
+ float closestDistanceSquared = FLT_MAX;
+
+ for (uint32_t submeshIndex = 0; submeshIndex < renderMeshAsset->getSubmeshCount(); submeshIndex++)
+ {
+ RenderDataFormat::Enum outFormat = RenderDataFormat::UNSPECIFIED;
+ const VertexBuffer& vb = renderMeshAsset->getSubmesh(submeshIndex).getVertexBuffer();
+ const VertexFormat& vf = vb.getFormat();
+ if (bufferName != NULL)
+ {
+ VertexFormat::BufferID id = ::strcmp(bufferName, "NORMAL") == 0 ? vf.getSemanticID(RenderVertexSemantic::NORMAL) : vf.getID(bufferName);
+ outFormat = vf.getBufferFormat((uint32_t)vf.getBufferIndexFromID(id));
+ if (outFormat == RenderDataFormat::UNSPECIFIED)
+ {
+ continue;
+ }
+ }
+
+ const uint8_t* usedForPhysics = NULL;
+ if (ignoreUnused)
+ {
+ uint32_t usedForPhysicsIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID(USED_FOR_PHYSICS_NAME));
+ outFormat = vf.getBufferFormat(usedForPhysicsIndex);
+ if (outFormat == RenderDataFormat::UBYTE1)
+ {
+ usedForPhysics = (const uint8_t*)vb.getBuffer(usedForPhysicsIndex);
+ }
+ }
+
+ const uint32_t* slave = NULL;
+ if (ignoreUnused)
+ {
+ uint32_t slaveIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID(LATCH_TO_NEAREST_SLAVE_NAME));
+ outFormat = vf.getBufferFormat(slaveIndex);
+ if (outFormat == RenderDataFormat::UINT1)
+ {
+ slave = (const uint32_t*)vb.getBuffer(slaveIndex);
+ }
+ }
+
+ const uint32_t vertexCount = renderMeshAsset->getSubmesh(submeshIndex).getVertexCount(0); // only 1 part supported
+ RenderDataFormat::Enum format;
+ uint32_t bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::POSITION));
+ const PxVec3* positions = (const PxVec3*)vb.getBufferAndFormat(format, bufferIndex);
+ if (format != RenderDataFormat::FLOAT3)
+ {
+ PX_ALWAYS_ASSERT();
+ positions = NULL;
+ }
+ for (uint32_t vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++)
+ {
+ if (usedForPhysics != NULL && usedForPhysics[vertexIndex] == 0)
+ {
+ continue;
+ }
+
+ if (slave != NULL && slave[vertexIndex] != 0)
+ {
+ continue;
+ }
+
+ const float distSquared = (position - positions[vertexIndex]).magnitudeSquared();
+ if (distSquared < closestDistanceSquared)
+ {
+ closestDistanceSquared = distSquared;
+ resultSubmeshIndex = submeshIndex;
+ resultGraphicalVertexIndex = vertexIndex;
+ found = true;
+ }
+ }
+ }
+ }
+
+ return found;
+}
+
+
+
+
+ClothingAssetAuthoringImpl::ClothingAssetAuthoringImpl(ModuleClothingImpl* module, ResourceList& list) :
+ ClothingAssetImpl(module, list, "ClothingAuthoring"),
+ mExportScale(1.0f),
+ mDeriveNormalsFromBones(false),
+ mOwnsMaterialLibrary(true),
+ mPreviousCookedType("Embedded")
+{
+ mInvalidConstrainCoefficients.maxDistance = -1.0f;
+ mInvalidConstrainCoefficients.collisionSphereDistance = -FLT_MAX;
+ mInvalidConstrainCoefficients.collisionSphereRadius = -1.0f;
+
+ initParams();
+}
+
+ClothingAssetAuthoringImpl::ClothingAssetAuthoringImpl(ModuleClothingImpl* module, ResourceList& list, const char* name) :
+ ClothingAssetImpl(module, list, name),
+ mExportScale(1.0f),
+ mDeriveNormalsFromBones(false),
+ mOwnsMaterialLibrary(true),
+ mPreviousCookedType("Embedded")
+{
+ mInvalidConstrainCoefficients.maxDistance = -1.0f;
+ mInvalidConstrainCoefficients.collisionSphereDistance = -FLT_MAX;
+ mInvalidConstrainCoefficients.collisionSphereRadius = -1.0f;
+
+ initParams();
+}
+
+ClothingAssetAuthoringImpl::ClothingAssetAuthoringImpl(ModuleClothingImpl* module, ResourceList& list, NvParameterized::Interface* params, const char* name) :
+ ClothingAssetImpl(module, list, params, name),
+ mExportScale(1.0f),
+ mDeriveNormalsFromBones(false),
+ mOwnsMaterialLibrary(true),
+ mPreviousCookedType("Embedded")
+{
+ mDefaultConstrainCoefficients.maxDistance = 0.0f;
+ mDefaultConstrainCoefficients.collisionSphereDistance = 0.0f;
+ mDefaultConstrainCoefficients.collisionSphereRadius = 0.0f;
+
+ mInvalidConstrainCoefficients.maxDistance = -1.0f;
+ mInvalidConstrainCoefficients.collisionSphereDistance = -FLT_MAX;
+ mInvalidConstrainCoefficients.collisionSphereRadius = -1.0f;
+
+ initParams();
+
+ if (mParams->rootBoneIndex < (uint32_t)mParams->bones.arraySizes[0])
+ {
+ mRootBoneName = mParams->bones.buf[mParams->rootBoneIndex].name;
+ }
+}
+
+
+
+void ClothingAssetAuthoringImpl::release()
+{
+ mModule->mSdk->releaseAssetAuthoring(*this);
+}
+
+
+
+bool ClothingAssetAuthoringImpl::checkSetMeshesInput(uint32_t lod, ClothingPhysicalMesh* nxPhysicalMesh, uint32_t& graphicalLodIndex)
+{
+ // index where it will be inserted
+ for (graphicalLodIndex = 0; graphicalLodIndex < mGraphicalLods.size(); ++graphicalLodIndex)
+ {
+ if (mGraphicalLods[graphicalLodIndex]->lod >= lod)
+ {
+ break;
+ }
+ }
+
+
+ if (nxPhysicalMesh != NULL)
+ {
+ if (mPhysicalMeshesInput.size() != mPhysicalMeshes.size())
+ {
+ APEX_INVALID_PARAMETER("Trying to operate add a physical mesh to an authoring object that has been deserialized. This is not suppored.");
+ return false;
+ }
+
+ // check that shared physics meshes are only in subsequent lods
+ int32_t i = (int32_t)graphicalLodIndex - 1;
+ uint32_t physMeshId = (uint32_t) - 1;
+ while (i >= 0)
+ {
+ physMeshId = mGraphicalLods[(uint32_t)i]->physicalMeshId;
+ if (physMeshId != (uint32_t) - 1 && mPhysicalMeshesInput[physMeshId] != nxPhysicalMesh)
+ {
+ break;
+ }
+ --i;
+ }
+
+ while (i >= 0)
+ {
+ physMeshId = mGraphicalLods[(uint32_t)i]->physicalMeshId;
+ if (physMeshId != (uint32_t) - 1 && mPhysicalMeshesInput[physMeshId] == nxPhysicalMesh)
+ {
+ APEX_INVALID_PARAMETER("Only subsequent graphical lods can share a physical mesh.");
+ return false;
+ }
+ --i;
+ }
+
+ i = (int32_t)graphicalLodIndex + 1;
+ physMeshId = (uint32_t) - 1;
+ while (i < (int32_t)mGraphicalLods.size())
+ {
+ physMeshId = mGraphicalLods[(uint32_t)i]->physicalMeshId;
+ if (physMeshId != (uint32_t) - 1 && mPhysicalMeshesInput[physMeshId] != nxPhysicalMesh)
+ {
+ break;
+ }
+ ++i;
+ }
+
+ while (i < (int32_t)mGraphicalLods.size())
+ {
+ physMeshId = mGraphicalLods[(uint32_t)i]->physicalMeshId;
+ if (physMeshId != (uint32_t) - 1 && mPhysicalMeshesInput[physMeshId] == nxPhysicalMesh)
+ {
+ APEX_INVALID_PARAMETER("Only subsequent graphical lods can share a physical mesh.");
+ return false;
+ }
+ ++i;
+ }
+ }
+ return true;
+}
+
+
+
+void ClothingAssetAuthoringImpl::sortPhysicalMeshes()
+{
+ if (mPhysicalMeshes.size() == 0)
+ {
+ return;
+ }
+
+ // sort physical lods according to references in graphical lods
+ Array<uint32_t> new2old(mPhysicalMeshes.size(), (uint32_t) - 1);
+ Array<uint32_t> old2new(mPhysicalMeshes.size(), (uint32_t) - 1);
+ bool reorderFailed = false;
+
+ uint32_t nextId = 0;
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ uint32_t physMeshId = mGraphicalLods[i]->physicalMeshId;
+ if (physMeshId == (uint32_t) - 1)
+ {
+ continue;
+ }
+
+ if (nextId == 0 || new2old[nextId - 1] != physMeshId) // if there's a new ID
+ {
+ // the new ID already appeared before, we can't sort
+ if (old2new[physMeshId] != (uint32_t) - 1)
+ {
+ PX_ALWAYS_ASSERT();
+ APEX_INTERNAL_ERROR("The assignment of graphics and physics mesh in the asset does not allow ordering of the physical meshes. Reuse of physical mesh is only allowed on subsequend graphical lods.");
+ reorderFailed = true;
+ break;
+ }
+
+ new2old[nextId] = physMeshId;
+ old2new[physMeshId] = nextId;
+ ++nextId;
+ }
+ }
+
+ if (!reorderFailed)
+ {
+ // reorder
+ ApexPermute<ClothingPhysicalMeshParameters*>(&mPhysicalMeshes[0], &new2old[0], mPhysicalMeshes.size());
+
+ // update references
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ mGraphicalLods[i]->physicalMeshId = old2new[mGraphicalLods[i]->physicalMeshId];
+ }
+
+ // clear transition maps
+ for (uint32_t i = 0; i < mPhysicalMeshes.size(); i++)
+ {
+ ParamArray<SkinClothMapB> transitionDownB(mPhysicalMeshes[i], "transitionDownB", reinterpret_cast<ParamDynamicArrayStruct*>(&mPhysicalMeshes[i]->transitionDownB));
+ transitionDownB.clear();
+ ParamArray<SkinClothMapB> transitionUpB(mPhysicalMeshes[i], "transitionUpB", reinterpret_cast<ParamDynamicArrayStruct*>(&mPhysicalMeshes[i]->transitionUpB));
+ transitionUpB.clear();
+
+ ParamArray<SkinClothMap> transitionDown(mPhysicalMeshes[i], "transitionDown", reinterpret_cast<ParamDynamicArrayStruct*>(&mPhysicalMeshes[i]->transitionDown));
+ transitionDown.clear();
+ ParamArray<SkinClothMap> transitionUp(mPhysicalMeshes[i], "transitionUp", reinterpret_cast<ParamDynamicArrayStruct*>(&mPhysicalMeshes[i]->transitionUp));
+ transitionUp.clear();
+ }
+ }
+}
+
+
+void ClothingAssetAuthoringImpl::setMeshes(uint32_t lod, RenderMeshAssetAuthoring* renderMeshAssetDontReference,
+ ClothingPhysicalMesh* nxPhysicalMesh,
+ float normalResemblance, bool ignoreUnusedVertices,
+ IProgressListener* progress)
+{
+ WRITE_ZONE();
+ // check input
+ uint32_t graphicalLodIndexTest = (uint32_t) - 1;
+ if (!checkSetMeshesInput(lod, nxPhysicalMesh, graphicalLodIndexTest))
+ {
+ return;
+ }
+
+ // get index and add lod if necessary, only adds if lod doesn't exist already
+ const uint32_t graphicalLodIndex = addGraphicalLod(lod);
+ PX_ASSERT(graphicalLodIndex == graphicalLodIndexTest);
+ PX_ASSERT(lod == mGraphicalLods[graphicalLodIndex]->lod);
+
+ clearMapping(graphicalLodIndex);
+
+ // reset counters to 0
+ for (uint32_t i = 0; i < mBones.size(); i++)
+ {
+ mBones[i].numMeshReferenced = mBones[i].numRigidBodiesReferenced = 0;
+ }
+
+ // remove existing physical of this lod mesh if it is not used by other lod
+ const uint32_t oldPhysicalMeshId = mGraphicalLods[graphicalLodIndex]->physicalMeshId;
+ if (oldPhysicalMeshId != (uint32_t) - 1)
+ {
+ // check if it's referenced by someone else
+ bool removePhysicalMesh = true;
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ // don't consider the current graphical lod
+ if (mGraphicalLods[i]->lod == lod)
+ {
+ continue;
+ }
+
+ if (mGraphicalLods[i]->physicalMeshId == oldPhysicalMeshId)
+ {
+ removePhysicalMesh = false;
+ break;
+ }
+ }
+
+ // if it's not referenced, remove it
+ if (removePhysicalMesh)
+ {
+ if (mPhysicalMeshesInput.size() == mPhysicalMeshes.size()) // mPhysicalMeshesInput is not set if the authoring is created from an existing params object
+ {
+ mPhysicalMeshesInput.replaceWithLast(oldPhysicalMeshId);
+ }
+
+ // replace with last and update the references to the last
+ mPhysicalMeshes.replaceWithLast(oldPhysicalMeshId);
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ if (mGraphicalLods[i]->physicalMeshId == mPhysicalMeshes.size())
+ {
+ mGraphicalLods[i]->physicalMeshId = oldPhysicalMeshId;
+ }
+ }
+ }
+ }
+
+ // copy physical mesh if we don't already have it
+ bool newPhysicalMesh = false;
+ ClothingPhysicalMeshParameters* physicalMesh = NULL;
+
+ if (nxPhysicalMesh != NULL)
+ {
+ ClothingPhysicalMeshImpl* physicalMeshInput = DYNAMIC_CAST(ClothingPhysicalMeshImpl*)(nxPhysicalMesh);
+ PX_ASSERT(physicalMeshInput != NULL);
+
+ PX_ASSERT(mPhysicalMeshes.size() == mPhysicalMeshesInput.size());
+ for (uint32_t i = 0; i < mPhysicalMeshesInput.size(); i++)
+ {
+ if (physicalMeshInput == mPhysicalMeshesInput[i]) // TODO check some more stuff in case it has been released and a new one was created at the same address
+ {
+ physicalMesh = mPhysicalMeshes[i];
+ PX_ASSERT(physicalMesh != NULL);
+ mGraphicalLods[graphicalLodIndex]->physicalMeshId = i;
+ break;
+ }
+ }
+ if (physicalMesh == NULL)
+ {
+ physicalMesh = DYNAMIC_CAST(ClothingPhysicalMeshParameters*)(GetInternalApexSDK()->getParameterizedTraits()->createNvParameterized(ClothingPhysicalMeshParameters::staticClassName()));
+ physicalMeshInput->makeCopy(physicalMesh);
+ physicalMesh->referenceCount = 1;
+ mPhysicalMeshes.pushBack(physicalMesh);
+ mPhysicalMeshesInput.pushBack(physicalMeshInput);
+
+ ClothingPhysicalMeshImpl* mesh = mModule->createPhysicalMeshInternal(physicalMesh);
+ mesh->updateSkinningNormals();
+ mesh->release();
+
+ newPhysicalMesh = true;
+ PX_ASSERT(physicalMesh != NULL);
+ mGraphicalLods[graphicalLodIndex]->physicalMeshId = mPhysicalMeshes.size() - 1;
+ }
+ }
+
+ bool hasLod = addGraphicalMesh(renderMeshAssetDontReference, graphicalLodIndex);
+ if (hasLod && physicalMesh)
+ {
+ PX_ASSERT(mGraphicalLods[graphicalLodIndex] != NULL);
+ RenderMeshAssetIntl* renderMeshAssetCopy = reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[graphicalLodIndex]->renderMeshAssetPointer);
+
+ // update mapping
+ updateMappingAuthoring(*mGraphicalLods[graphicalLodIndex], renderMeshAssetCopy, static_cast<RenderMeshAssetAuthoringIntl*>(renderMeshAssetDontReference),
+ normalResemblance, ignoreUnusedVertices, progress);
+
+ // sort physics mesh triangles and vertices
+ ClothingPhysicalMeshImpl* mesh = mModule->createPhysicalMeshInternal(physicalMesh);
+ sortDeformableIndices(*mesh);
+
+ // calculate and setup number of simulated vertices and indices
+ setupPhysicalMesh(*physicalMesh);
+
+ // "reordering has to be done after creating the submeshes because the vertices must be sorted per submesh" - not valid anymore
+ reorderDeformableVertices(*mesh);
+
+ // re-order vertices in graphical mesh to make tangent recompute faster
+ reorderGraphicsVertices(graphicalLodIndex, false);
+ removeMaxDistance0Mapping(*mGraphicalLods[graphicalLodIndex], renderMeshAssetCopy);
+
+ mesh->release();
+ mesh = NULL;
+
+ // conditionally drop the immediate map (perf optimization)
+ conditionalMergeMapping(*renderMeshAssetCopy, *mGraphicalLods[graphicalLodIndex]);
+ }
+
+ // keep physical meshes sorted such that the transition maps are correct
+ // (needs to be called after 'addGraphicalMesh', so a graphicalLOD deletion is not missed)
+ sortPhysicalMeshes();
+
+ bool isIdentity = true;
+ Array<int32_t> old2new(mBones.size(), -1);
+ for (uint32_t i = 0; i < mBones.size(); i++)
+ {
+ old2new[(uint32_t)mBones[i].externalIndex] = mBones[i].internalIndex;
+ isIdentity &= mBones[i].externalIndex == mBones[i].internalIndex;
+ }
+
+ if (!isIdentity && hasLod)
+ {
+ reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[graphicalLodIndex]->renderMeshAssetPointer)->permuteBoneIndices(old2new);
+
+ if (newPhysicalMesh)
+ {
+ const uint32_t physicalMeshId = mGraphicalLods[graphicalLodIndex]->physicalMeshId;
+ ClothingPhysicalMeshImpl* mesh = mModule->createPhysicalMeshInternal(mPhysicalMeshes[physicalMeshId]);
+ mesh->permuteBoneIndices(old2new);
+ mesh->release();
+ }
+ }
+}
+
+
+
+bool ClothingAssetAuthoringImpl::addPlatformToGraphicalLod(uint32_t lod, PlatformTag platform)
+{
+ WRITE_ZONE();
+ uint32_t index;
+ if (!getGraphicalLodIndex(lod, index))
+ {
+ return false;
+ }
+
+ ClothingGraphicalLodParameters* graphicalLod = mGraphicalLods[index];
+
+ // pushback to an array of strings
+ NvParameterized::Handle handle(*graphicalLod);
+ if (graphicalLod->getParameterHandle("platforms", handle) != NvParameterized::ERROR_NONE)
+ {
+ return false;
+ }
+
+ int32_t numPlatforms = 0;
+ graphicalLod->getArraySize(handle, numPlatforms);
+ graphicalLod->resizeArray(handle, numPlatforms + 1);
+ NvParameterized::Handle elementHandle(*graphicalLod);
+ handle.getChildHandle(numPlatforms, elementHandle);
+ graphicalLod->setParamString(elementHandle, platform);
+
+ return true;
+}
+
+
+bool ClothingAssetAuthoringImpl::removePlatform(uint32_t lod, PlatformTag platform)
+{
+ WRITE_ZONE();
+ uint32_t index;
+ if (!getGraphicalLodIndex(lod, index))
+ {
+ return false;
+ }
+
+ ClothingGraphicalLodParameters* graphicalLod = mGraphicalLods[index];
+
+ ParamArray<NvParameterized::DummyStringStruct> platforms(graphicalLod, "platforms", reinterpret_cast<ParamDynamicArrayStruct*>(&graphicalLod->platforms));
+
+ bool removed = false;
+ for (int32_t i = (int32_t)platforms.size() - 1; i >= 0 ; --i)
+ {
+ if (::strcmp(platforms[(uint32_t)i], platform) == 0)
+ {
+ platforms.replaceWithLast((uint32_t)i);
+ removed = true;
+ }
+ }
+
+ return removed;
+}
+
+
+uint32_t ClothingAssetAuthoringImpl::getNumPlatforms(uint32_t lod) const
+{
+ uint32_t index;
+ if (!getGraphicalLodIndex(lod, index))
+ {
+ return 0;
+ }
+
+ ClothingGraphicalLodParameters* graphicalLod = mGraphicalLods[index];
+
+ ParamArray<NvParameterized::DummyStringStruct> platforms(graphicalLod, "platforms", reinterpret_cast<ParamDynamicArrayStruct*>(&graphicalLod->platforms));
+ return platforms.size();
+}
+
+
+PlatformTag ClothingAssetAuthoringImpl::getPlatform(uint32_t lod, uint32_t i) const
+{
+ READ_ZONE();
+ uint32_t index;
+ if (!getGraphicalLodIndex(lod, index))
+ {
+ return 0;
+ }
+
+ ClothingGraphicalLodParameters* graphicalLod = mGraphicalLods[index];
+
+ ParamArray<NvParameterized::DummyStringStruct> platforms(graphicalLod, "platforms", reinterpret_cast<ParamDynamicArrayStruct*>(&graphicalLod->platforms));
+
+ if (i >= platforms.size())
+ {
+ return 0;
+ }
+
+ return platforms[i];
+}
+
+
+bool ClothingAssetAuthoringImpl::prepareForPlatform(PlatformTag platform)
+{
+ bool retVal = false;
+
+ // go through graphical lods and remove the ones that are not tagged with "platform"
+ for (int32_t i = (int32_t)mGraphicalLods.size() - 1; i >= 0; --i)
+ {
+ ClothingGraphicalLodParameters* graphicalLod = mGraphicalLods[(uint32_t)i];
+ ParamArray<NvParameterized::DummyStringStruct> platforms(graphicalLod, "platforms", reinterpret_cast<ParamDynamicArrayStruct*>(&graphicalLod->platforms));
+
+ bool keep = platforms.size() == 0; // keep it if it has no platforms at all
+ for (uint32_t j = 0; j < platforms.size(); j++)
+ {
+ const char* storedPlatform = platforms[j].buf;
+ if (::strcmp(platform, storedPlatform) == 0)
+ {
+ keep = true;
+ }
+ }
+
+ if (!keep)
+ {
+ setMeshes(graphicalLod->lod, NULL, NULL); // remove
+ }
+ else
+ {
+ retVal = true; // keep
+ }
+ }
+
+ return retVal;
+}
+
+
+
+uint32_t ClothingAssetAuthoringImpl::getNumLods() const
+{
+ READ_ZONE();
+ return mGraphicalLods.size();
+}
+
+
+
+int32_t ClothingAssetAuthoringImpl::getLodValue(uint32_t lod) const
+{
+ READ_ZONE();
+ if (lod < mGraphicalLods.size())
+ {
+ return (int32_t)mGraphicalLods[lod]->lod;
+ }
+
+ return -1;
+}
+
+
+
+void ClothingAssetAuthoringImpl::clearMeshes()
+{
+ WRITE_ZONE();
+ for (int32_t i = (int32_t)mGraphicalLods.size() - 1; i >= 0; i--)
+ {
+ setMeshes(mGraphicalLods[(uint32_t)i]->lod, NULL, NULL);
+ }
+ PX_ASSERT(mGraphicalLods.isEmpty());
+
+ PX_ASSERT(mPhysicalMeshes.size() == mPhysicalMeshesInput.size());
+ for (uint32_t i = 0; i < mPhysicalMeshes.size(); i++)
+ {
+ mPhysicalMeshes[i]->destroy();
+ }
+ mPhysicalMeshes.clear();
+ mPhysicalMeshesInput.clear();
+}
+
+
+
+ClothingPhysicalMesh* ClothingAssetAuthoringImpl::getClothingPhysicalMesh(uint32_t graphicalLod) const
+{
+ READ_ZONE();
+ uint32_t graphicalLodIndex = 0;
+ if (!getGraphicalLodIndex(graphicalLod, graphicalLodIndex))
+ {
+ return NULL;
+ }
+
+ uint32_t physicalMeshId = mGraphicalLods[graphicalLodIndex]->physicalMeshId;
+
+ if (physicalMeshId == (uint32_t) - 1)
+ {
+ return NULL;
+ }
+
+ return mModule->createPhysicalMeshInternal(mPhysicalMeshes[physicalMeshId]);
+}
+
+
+
+bool ClothingAssetAuthoringImpl::getBoneBindPose(uint32_t boneIndex, PxMat44& bindPose) const
+{
+ READ_ZONE();
+ bool ret = false;
+ if (boneIndex < mBones.size())
+ {
+ bindPose = mBones[boneIndex].bindPose;
+ ret = true;
+ }
+ return ret;
+}
+
+bool ClothingAssetAuthoringImpl::setBoneBindPose(uint32_t boneIndex, const PxMat44& bindPose)
+{
+ WRITE_ZONE();
+ bool ret = false;
+ if (boneIndex < mBones.size())
+ {
+ mBones[boneIndex].bindPose = bindPose;
+ ret = true;
+ }
+ return ret;
+}
+
+void ClothingAssetAuthoringImpl::setBoneInfo(uint32_t boneIndex, const char* boneName, const PxMat44& bindPose, int32_t parentIndex)
+{
+ WRITE_ZONE();
+ for (uint32_t i = 0; i < mBones.size(); i++)
+ {
+ if (mBones[i].externalIndex == (int32_t)boneIndex)
+ {
+ if (mBones[i].name == NULL || ::strcmp(mBones[i].name, boneName) != 0)
+ {
+ setBoneName(i, boneName);
+ }
+
+ mBones[i].bindPose = bindPose;
+
+ // parentIndex should be an internal index, so let's see
+ int32_t oldInternalParent = mBones[i].parentIndex;
+ int32_t newInternalParent = oldInternalParent;
+ PX_ASSERT((oldInternalParent == -1) == (parentIndex == -1)); // both are -1 or valid
+ if (oldInternalParent >= 0)
+ {
+ PX_ASSERT(parentIndex >= 0);
+ PX_ASSERT((uint32_t)oldInternalParent < mBones.size());
+ if ((uint32_t)oldInternalParent < mBones.size())
+ {
+ PX_ASSERT(mBones[(uint32_t)oldInternalParent].internalIndex == oldInternalParent); // just some sanity
+ if (mBones[(uint32_t)oldInternalParent].externalIndex != parentIndex)
+ {
+ // it seems the parent changed, let's hope this doesn't kill us
+ for (uint32_t b = 0; b < mBones.size(); b++)
+ {
+ if (mBones[b].externalIndex == parentIndex)
+ {
+ newInternalParent = (int32_t)b;
+ break;
+ }
+ }
+ }
+ }
+ }
+ mBones[i].parentIndex = newInternalParent;
+ return;
+ }
+ }
+
+ ClothingAssetParametersNS::BoneEntry_Type& bm = mBones.pushBack();
+ bm.internalIndex = (int32_t)boneIndex;
+ bm.externalIndex = (int32_t)boneIndex;
+ bm.numMeshReferenced = 0;
+ bm.numRigidBodiesReferenced = 0;
+ bm.parentIndex = parentIndex;
+ bm.bindPose = bindPose;
+ setBoneName(mBones.size() - 1, boneName);
+}
+
+
+
+void ClothingAssetAuthoringImpl::setRootBone(const char* boneName)
+{
+ WRITE_ZONE();
+ mRootBoneName = boneName;
+}
+
+
+
+uint32_t ClothingAssetAuthoringImpl::addBoneConvex(const char* boneName, const PxVec3* positions, uint32_t numPositions)
+{
+ WRITE_ZONE();
+ int32_t internalBoneIndex = getBoneInternalIndex(boneName);
+
+ if (internalBoneIndex == -1)
+ {
+ return 0;
+ }
+
+ return addBoneConvexInternal((uint32_t)internalBoneIndex , positions, numPositions);
+}
+
+uint32_t ClothingAssetAuthoringImpl::addBoneConvex(uint32_t boneIndex, const PxVec3* positions, uint32_t numPositions)
+{
+ WRITE_ZONE();
+ int32_t internalBoneIndex = getBoneInternalIndex(boneIndex);
+
+ if (internalBoneIndex == -1)
+ {
+ return 0;
+ }
+
+ return addBoneConvexInternal((uint32_t)internalBoneIndex , positions, numPositions);
+
+}
+
+
+
+void ClothingAssetAuthoringImpl::addBoneCapsule(const char* boneName, float capsuleRadius, float capsuleHeight, const PxMat44& localPose)
+{
+ WRITE_ZONE();
+ int32_t internalBoneIndex = getBoneInternalIndex(boneName);
+
+ if (internalBoneIndex == -1)
+ {
+ return;
+ }
+
+ addBoneCapsuleInternal((uint32_t)internalBoneIndex, capsuleRadius, capsuleHeight, localPose);
+}
+
+
+
+void ClothingAssetAuthoringImpl::addBoneCapsule(uint32_t boneIndex, float capsuleRadius, float capsuleHeight, const PxMat44& localPose)
+{
+ WRITE_ZONE();
+ int32_t internalBoneIndex = getBoneInternalIndex(boneIndex);
+
+ if (internalBoneIndex == -1)
+ {
+ return;
+ }
+
+ addBoneCapsuleInternal((uint32_t)internalBoneIndex, capsuleRadius, capsuleHeight, localPose);
+}
+
+
+
+void ClothingAssetAuthoringImpl::clearBoneActors(const char* boneName)
+{
+ WRITE_ZONE();
+ int32_t internalBoneIndex = getBoneInternalIndex(boneName);
+
+ if (internalBoneIndex == -1)
+ {
+ return;
+ }
+
+ clearBoneActorsInternal(internalBoneIndex);
+}
+
+
+
+void ClothingAssetAuthoringImpl::clearBoneActors(uint32_t boneIndex)
+{
+ WRITE_ZONE();
+ int32_t internalBoneIndex = getBoneInternalIndex(boneIndex);
+
+ if (internalBoneIndex == -1)
+ {
+ return;
+ }
+
+ clearBoneActorsInternal(internalBoneIndex);
+}
+
+
+
+void ClothingAssetAuthoringImpl::clearAllBoneActors()
+{
+ WRITE_ZONE();
+ mBoneActors.clear();
+ mBoneVertices.clear();
+ mBonePlanes.clear();
+ clearCooked();
+}
+
+
+
+void ClothingAssetAuthoringImpl::setCollision(const char** boneNames, float* radii, PxVec3* localPositions, uint32_t numSpheres, uint16_t* pairs, uint32_t numPairs)
+{
+ WRITE_ZONE();
+ nvidia::Array<uint32_t> boneIndices(numSpheres, 0);
+ for (uint32_t i = 0; i < numSpheres; ++i)
+ {
+ int32_t internalBoneIndex = getBoneInternalIndex(boneNames[i]);
+ if (internalBoneIndex < 0 || internalBoneIndex >= (int32_t)mBones.size())
+ {
+ APEX_INVALID_PARAMETER("Bone \'%s\' not found, setting to root", boneNames[i]);
+ boneIndices[i] = 0;
+ }
+ else
+ {
+ boneIndices[i] = (uint32_t)mBones[i].externalIndex;
+ }
+ }
+
+ setCollision(boneIndices.begin(), radii, localPositions, numSpheres, pairs, numPairs);
+}
+
+
+
+void ClothingAssetAuthoringImpl::setCollision(uint32_t* boneIndices, float* radii, PxVec3* localPositions, uint32_t numSpheres, uint16_t* pairs, uint32_t numPairs)
+{
+ WRITE_ZONE();
+ if (numPairs & 0x1)
+ {
+ APEX_INVALID_PARAMETER("numPairs must be a multiple of 2");
+ return;
+ }
+
+ mBoneSpheres.clear();
+ for (uint32_t i = 0; i < numSpheres; ++i)
+ {
+ int32_t internalBoneIndex = getBoneInternalIndex(boneIndices[i]);
+
+ PX_ASSERT(internalBoneIndex < (int32_t)mBones.size());
+ internalBoneIndex = PxClamp(internalBoneIndex, 0, (int32_t)mBones.size() - 1);
+ float radius = radii[i];
+ if (radius <= 0.0f)
+ {
+ APEX_INVALID_PARAMETER("Sphere radius must be bigger than 0.0 (sphere %d has radius %f)", i, radius);
+ radius = 0.0f;
+ }
+ ClothingAssetParametersNS::BoneSphere_Type& newEntry = mBoneSpheres.pushBack();
+ memset(&newEntry, 0, sizeof(ClothingAssetParametersNS::BoneSphere_Type));
+ newEntry.boneIndex = internalBoneIndex;
+ newEntry.radius = radius;
+ newEntry.localPos = localPositions[i];
+ }
+
+ mSpherePairs.clear();
+ for (uint32_t i = 0; i < numPairs; i += 2)
+ {
+ const uint16_t p1 = PxMin(pairs[i + 0], pairs[i + 1]);
+ const uint16_t p2 = PxMax(pairs[i + 0], pairs[i + 1]);
+ if (p1 == p2)
+ {
+ APEX_INVALID_PARAMETER("pairs[%d] and pairs[%d] are identical (%d), skipping", i, i + 1, p1);
+ continue;
+ }
+ else if (p1 >= mBoneSpheres.size() || p2 >= mBoneSpheres.size())
+ {
+ APEX_INVALID_PARAMETER("pairs[%d] = %d and pairs[%d] = %d are overflowing bone spheres, skipping", i, pairs[i], i + 1, pairs[i + 1]);
+ }
+ else
+ {
+ bool skip = false;
+ for (uint32_t j = 0; j < mSpherePairs.size(); j += 2)
+ {
+ if (mSpherePairs[j] == p1 && mSpherePairs[j + 1] == p2)
+ {
+ APEX_INVALID_PARAMETER("pairs[%d] = %d and pairs[%d] = %d are a duplicate, skipping", i, pairs[i], i + 1, pairs[i + 1]);
+ skip = true;
+ break;
+ }
+ }
+ if (!skip)
+ {
+ mSpherePairs.pushBack(p1);
+ mSpherePairs.pushBack(p2);
+ }
+ }
+ }
+}
+
+
+
+void ClothingAssetAuthoringImpl::clearCollision()
+{
+ WRITE_ZONE();
+ mBoneSpheres.clear();
+ mSpherePairs.clear();
+}
+
+
+
+NvParameterized::Interface* ClothingAssetAuthoringImpl::getMaterialLibrary()
+{
+ READ_ZONE();
+ PX_ASSERT(mParams->materialLibrary != NULL);
+ return mParams->materialLibrary;
+}
+
+
+
+bool ClothingAssetAuthoringImpl::setMaterialLibrary(NvParameterized::Interface* materialLibrary, uint32_t materialIndex, bool transferOwnership)
+{
+ WRITE_ZONE();
+ if (::strcmp(materialLibrary->className(), ClothingMaterialLibraryParameters::staticClassName()) == 0)
+ {
+ if (mParams->materialLibrary != NULL && mOwnsMaterialLibrary)
+ {
+ mParams->materialLibrary->destroy();
+ }
+
+ mParams->materialLibrary = materialLibrary;
+ mParams->materialIndex = materialIndex;
+ mOwnsMaterialLibrary = transferOwnership;
+
+ return true;
+ }
+
+ return false;
+}
+
+
+
+NvParameterized::Interface* ClothingAssetAuthoringImpl::getRenderMeshAssetAuthoring(uint32_t lodLevel) const
+{
+ READ_ZONE();
+ NvParameterized::Interface* ret = NULL;
+
+ if (lodLevel < mGraphicalLods.size())
+ {
+ ret = mGraphicalLods[lodLevel]->renderMeshAsset;
+ }
+
+ return ret;
+}
+
+
+
+NvParameterized::Interface* ClothingAssetAuthoringImpl::releaseAndReturnNvParameterizedInterface()
+{
+ // this is important for destroy() !
+ if (!mOwnsMaterialLibrary && mParams->materialLibrary != NULL)
+ {
+ NvParameterized::Interface* foreignMatLib = mParams->materialLibrary;
+
+ // clone the mat lib
+ mParams->materialLibrary = mParams->getTraits()->createNvParameterized(foreignMatLib->className());
+ mParams->materialLibrary->copy(*foreignMatLib);
+ }
+ mOwnsMaterialLibrary = true;
+
+ if (NvParameterized::ERROR_NONE != mParams->callPreSerializeCallback())
+ {
+ return NULL;
+ }
+
+ mParams->setSerializationCallback(NULL, NULL);
+
+ // release the object without mParams
+ NvParameterized::Interface* ret = mParams;
+ mParams = NULL;
+
+ release();
+ return ret;
+}
+
+
+
+void ClothingAssetAuthoringImpl::preSerialize(void* userData)
+{
+ PX_ASSERT(userData == NULL);
+ PX_UNUSED(userData);
+
+
+ ParamArray<ClothingAssetParametersNS::CookedEntry_Type> cookedEntries(mParams, "cookedData", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->cookedData));
+ if (cookedEntries.isEmpty())
+ {
+ ClothingAssetParametersNS::CookedEntry_Type entry;
+ entry.cookedData = NULL;
+ entry.scale = 1.0f;
+ cookedEntries.pushBack(entry);
+ }
+
+ for (uint32_t i = 0; i < cookedEntries.size(); i++)
+ {
+ if (cookedEntries[i].cookedData != NULL)
+ {
+ mPreviousCookedType = cookedEntries[i].cookedData->className();
+ cookedEntries[i].cookedData->destroy();
+ cookedEntries[i].cookedData = NULL;
+ }
+
+ PX_ASSERT(mPreviousCookedType != NULL);
+ BackendFactory* cookingFactory = mModule->getBackendFactory(mPreviousCookedType);
+ PX_ASSERT(cookingFactory != NULL);
+ if (cookingFactory != NULL)
+ {
+ CookingAbstract* cookingJob = cookingFactory->createCookingJob();
+ PX_ASSERT(cookingJob != NULL);
+ if (cookingJob)
+ {
+ prepareCookingJob(*cookingJob, cookedEntries[i].scale, NULL, NULL);
+
+ if (cookingJob->isValid())
+ {
+ cookedEntries[i].cookedData = cookingJob->execute();
+ }
+ PX_DELETE_AND_RESET(cookingJob);
+ }
+ }
+ }
+
+ compressBones();
+
+ for (uint32_t graphicalMeshId = 0; graphicalMeshId < mGraphicalLods.size(); graphicalMeshId++)
+ {
+ RenderMeshAssetIntl* renderMeshAsset = reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[graphicalMeshId]->renderMeshAssetPointer);
+ for (uint32_t submeshIndex = 0; submeshIndex < renderMeshAsset->getSubmeshCount(); submeshIndex++)
+ {
+ VertexFormat& format = renderMeshAsset->getInternalSubmesh(submeshIndex).getVertexBufferWritable().getFormatWritable();
+ format.setBufferAccess((uint32_t)format.getBufferIndexFromID(format.getSemanticID(RenderVertexSemantic::POSITION)), RenderDataAccess::DYNAMIC);
+ format.setBufferAccess((uint32_t)format.getBufferIndexFromID(format.getSemanticID(RenderVertexSemantic::NORMAL)), RenderDataAccess::DYNAMIC);
+ if (format.getBufferFormat((uint32_t)format.getBufferIndexFromID(format.getSemanticID(RenderVertexSemantic::TANGENT))) != RenderDataFormat::UNSPECIFIED)
+ {
+ format.setBufferAccess((uint32_t)format.getBufferIndexFromID(format.getSemanticID(RenderVertexSemantic::TANGENT)), RenderDataAccess::DYNAMIC);
+ format.setBufferAccess((uint32_t)format.getBufferIndexFromID(format.getSemanticID(RenderVertexSemantic::BINORMAL)), RenderDataAccess::DYNAMIC);
+ }
+ format.setHasSeparateBoneBuffer(true);
+ }
+ }
+
+ // create lod transition maps
+ for (uint32_t i = 0; i < mPhysicalMeshes.size(); i++)
+ {
+ AbstractMeshDescription other;
+ other.pPosition = mPhysicalMeshes[i]->physicalMesh.vertices.buf;
+ other.pNormal = mPhysicalMeshes[i]->physicalMesh.normals.buf;
+ other.numVertices = mPhysicalMeshes[i]->physicalMesh.numVertices;
+
+ if (i > 0)
+ {
+ ParamArray<SkinClothMap> transitionDown(mPhysicalMeshes[i], "transitionDown",
+ reinterpret_cast<ParamDynamicArrayStruct*>(&mPhysicalMeshes[i]->transitionDown));
+ if (transitionDown.isEmpty())
+ {
+ generateSkinClothMap(&other, 1, mPhysicalMeshes[i - 1]->physicalMesh, NULL, NULL, 0, transitionDown,
+ mPhysicalMeshes[i]->transitionDownOffset, false, NULL);
+
+ mPhysicalMeshes[i]->transitionDownThickness = 1.0f;
+ }
+ }
+ if (i + 1 < mPhysicalMeshes.size())
+ {
+
+ ParamArray<SkinClothMap> transitionUp(mPhysicalMeshes[i], "transitionUp",
+ reinterpret_cast<ParamDynamicArrayStruct*>(&mPhysicalMeshes[i]->transitionUp));
+ if (transitionUp.isEmpty())
+ {
+ generateSkinClothMap(&other, 1, mPhysicalMeshes[i + 1]->physicalMesh, NULL, NULL, 0, transitionUp,
+ mPhysicalMeshes[i]->transitionUpOffset, false, NULL);
+
+ mPhysicalMeshes[i]->transitionUpThickness = 1.0f;
+ }
+ }
+ }
+
+ updateBoundingBox();
+
+ ClothingAssetImpl::preSerialize(userData);
+}
+
+
+
+void ClothingAssetAuthoringImpl::setToolString(const char* toolString)
+{
+ if (mParams != NULL)
+ {
+ NvParameterized::Handle handle(*mParams, "toolString");
+ PX_ASSERT(handle.isValid());
+ if (handle.isValid())
+ {
+ PX_ASSERT(handle.parameterDefinition()->type() == NvParameterized::TYPE_STRING);
+ handle.setParamString(toolString);
+ }
+ }
+}
+
+
+
+void ClothingAssetAuthoringImpl::applyTransformation(const PxMat44& transformation, float scale, bool applyToGraphics, bool applyToPhysics)
+{
+ WRITE_ZONE();
+ if (applyToPhysics)
+ {
+ clearCooked();
+
+ for (uint32_t i = 0; i < mPhysicalMeshes.size(); i++)
+ {
+ ClothingPhysicalMeshImpl* mesh = mModule->createPhysicalMeshInternal(mPhysicalMeshes[i]);
+ mesh->applyTransformation(transformation, scale);
+ mesh->release();
+ }
+
+ for (uint32_t i = 0; i < mBones.size(); i++)
+ {
+ mBones[i].bindPose = transformation * mBones[i].bindPose;
+ mBones[i].bindPose.setPosition(mBones[i].bindPose.getPosition() * scale);
+ }
+
+ for (uint32_t i = 0; i < mBoneVertices.size(); i++)
+ {
+ // PH: Do not apply transformation, bindpose was already adapted!
+ //mBoneVertices[i] = transformation * mBoneVertices[i];
+ mBoneVertices[i] *= scale;
+ }
+
+ for(uint32_t i = 0; i < mBonePlanes.size(); i++)
+ {
+ mBonePlanes[i].d *= scale;
+ }
+
+ for (uint32_t i = 0; i < mBoneActors.size(); i++)
+ {
+ mBoneActors[i].capsuleRadius *= scale;
+ mBoneActors[i].capsuleHeight *= scale;
+ mBoneActors[i].localPose.setPosition(mBoneActors[i].localPose.getPosition() * scale);
+ }
+
+ for (uint32_t i = 0; i < mBoneSpheres.size(); i++)
+ {
+ mBoneSpheres[i].radius *= scale;
+ mBoneSpheres[i].localPos *= scale;
+ }
+
+ mParams->simulation.thickness *= scale;
+
+ ClothingMaterialLibraryParameters* materialLib = static_cast<ClothingMaterialLibraryParameters*>(mParams->materialLibrary);
+ for (int32_t i = 0; i < materialLib->materials.arraySizes[0]; ++i)
+ {
+ materialLib->materials.buf[i].selfcollisionThickness *= scale;
+ }
+ }
+
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ if (applyToGraphics)
+ {
+ reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[i]->renderMeshAssetPointer)->applyTransformation(transformation, scale);
+ }
+
+ if (applyToPhysics)
+ {
+ const uint32_t numSkinClothMap = (uint32_t)mGraphicalLods[i]->skinClothMap.arraySizes[0];
+ SkinClothMap* skinClothMap = mGraphicalLods[i]->skinClothMap.buf;
+
+ mGraphicalLods[i]->skinClothMapThickness *= scale;
+
+ for (uint32_t j = 0; j < numSkinClothMap; j++)
+ {
+ // make sure no INF is created
+ if (skinClothMap[j].vertexBary.z != PX_MAX_F32) skinClothMap[j].vertexBary.z *= scale;
+ if (skinClothMap[j].normalBary.z != PX_MAX_F32) skinClothMap[j].normalBary.z *= scale;
+ if (skinClothMap[j].tangentBary.z != PX_MAX_F32) skinClothMap[j].tangentBary.z *= scale;
+ }
+ const PxMat33 t(transformation.column0.getXYZ(), transformation.column1.getXYZ(), transformation.column2.getXYZ());
+
+ if (t.getDeterminant() * scale < 0.0f)
+ {
+ const uint32_t numTetraMap = (uint32_t)mGraphicalLods[i]->tetraMap.arraySizes[0];
+ ClothingGraphicalLodParametersNS::TetraLink_Type* tetraMap = mGraphicalLods[i]->tetraMap.buf;
+
+ for (uint32_t j = 0; j < numTetraMap; j++)
+ {
+ PxVec3 bary = tetraMap[j].vertexBary;
+ bary.z = 1.0f - bary.x - bary.y - bary.z;
+ tetraMap[j].vertexBary = bary;
+
+ bary = tetraMap[j].normalBary;
+ bary.z = 1.0f - bary.x - bary.y - bary.z;
+ tetraMap[j].normalBary = bary;
+ }
+ }
+ }
+ }
+}
+
+
+
+void ClothingAssetAuthoringImpl::updateBindPoses(const PxMat44* newBindPoses, uint32_t newBindPosesCount, bool isInternalOrder, bool collisionMaintainWorldPose)
+{
+ WRITE_ZONE();
+ Array<PxMat44> transformation(mBones.size());
+
+ bool hasSkew = false;
+ for (uint32_t i = 0; i < mBones.size(); i++)
+ {
+ PX_ASSERT(mBones[i].internalIndex == (int32_t)i);
+ const uint32_t externalIndex = isInternalOrder ? i : mBones[i].externalIndex;
+
+ if (externalIndex >= newBindPosesCount)
+ {
+ transformation[i] = PxMat44(PxIdentity);
+ }
+ else
+ {
+ PxMat44 temp;
+ temp = mBones[i].bindPose.inverseRT();
+ mBones[i].bindPose = newBindPoses[externalIndex];
+ transformation[i] = temp * mBones[i].bindPose;
+
+ PxMat33 m(transformation[i].column0.getXYZ(), transformation[i].column1.getXYZ(), transformation[i].column2.getXYZ());
+ float det = m.getDeterminant();
+
+ if (PxAbs(det) < 0.99f)
+ {
+ hasSkew = true;
+ }
+ }
+ }
+
+ if (hasSkew)
+ {
+ APEX_INVALID_PARAMETER("Skew on matrices is not allowed, aborting");
+ return;
+ }
+
+ int32_t errorInSize = -1;
+
+ if (collisionMaintainWorldPose)
+ {
+ for (uint32_t i = 0; i < mBoneActors.size(); i++)
+ {
+ const uint32_t boneIndex = (uint32_t)mBoneActors[i].boneIndex;
+ if (transformation[boneIndex].transform(PxVec3(1.f)) != PxVec3(1.f))
+ {
+ if (mBoneActors[i].convexVerticesCount == 0)
+ {
+ // capsule
+ PxMat33 m33(transformation[boneIndex].column0.getXYZ(), transformation[boneIndex].column1.getXYZ(), transformation[boneIndex].column2.getXYZ());
+ PxMat44 invTransformation(m33.getInverse(), m33.transform(-transformation[boneIndex].getPosition()));
+ mBoneActors[i].localPose = invTransformation * mBoneActors[i].localPose;
+ }
+ else
+ {
+ // convex
+ const uint32_t start = mBoneActors[i].convexVerticesStart;
+ const uint32_t end = start + mBoneActors[i].convexVerticesCount;
+ for (uint32_t j = start; j < end; j++)
+ {
+ PX_ASSERT(j < mBoneVertices.size());
+ mBoneVertices[j] = transformation[boneIndex].transform(mBoneVertices[j]);
+ }
+ }
+ }
+ else
+ {
+ const uint32_t boneIdx = (uint32_t)mBoneActors[i].boneIndex;
+ const int32_t externalIndex = isInternalOrder ? (int32_t)boneIdx : mBones[boneIdx].externalIndex;
+
+ errorInSize = PxMax(errorInSize, externalIndex);
+ }
+ }
+ for (uint32_t i = 0; i < mBoneSpheres.size(); i++)
+ {
+ const uint32_t boneIndex = (uint32_t)mBoneSpheres[i].boneIndex;
+ if (transformation[boneIndex].transform(PxVec3(1.f)) != PxVec3(1.f))
+ {
+ PxMat33 invTransformation(transformation[boneIndex].column0.getXYZ(), transformation[boneIndex].column1.getXYZ(), transformation[boneIndex].column2.getXYZ());
+ invTransformation = invTransformation.getInverse();
+ mBoneSpheres[i].localPos = invTransformation.transform(mBoneSpheres[i].localPos)
+ + invTransformation.transform(-transformation[boneIndex].getPosition());
+ }
+ else
+ {
+ const int32_t externalIndex = isInternalOrder ? (int32_t)boneIndex : mBones[boneIndex].externalIndex;
+ errorInSize = PxMax(errorInSize, externalIndex);
+ }
+ }
+ }
+
+#if 0
+ // PH: This proved to be actually wrong. We should just adapt the bind pose without moving
+ // the meshes AT ALL.
+ for (uint32_t physicalMeshIndex = 0; physicalMeshIndex < mPhysicalMeshes.size(); physicalMeshIndex++)
+ {
+
+ const uint32_t numBonesPerVertex = mPhysicalMeshes[physicalMeshIndex]->physicalMesh.numBonesPerVertex;
+ if (numBonesPerVertex > 0)
+ {
+ const uint32_t numVertices = mPhysicalMeshes[physicalMeshIndex]->physicalMesh.numVertices;
+ PxVec3* positions = mPhysicalMeshes[physicalMeshIndex]->physicalMesh.vertices.buf;
+ PxVec3* normals = mPhysicalMeshes[physicalMeshIndex]->physicalMesh.normals.buf;
+ uint16_t* boneIndices = mPhysicalMeshes[physicalMeshIndex]->physicalMesh.boneIndices.buf;
+ float* boneWeights = mPhysicalMeshes[physicalMeshIndex]->physicalMesh.boneWeights.buf;
+ PX_ASSERT(positions != NULL);
+ PX_ASSERT(normals != NULL);
+ PX_ASSERT(numBonesPerVertex == 1 || boneWeights != NULL);
+
+ for (uint32_t vertexID = 0; vertexID < numVertices; vertexID++)
+ {
+ PxVec3 position(0.0f, 0.0f, 0.0f);
+ PxVec3 normal(0.0f, 0.0f, 0.0f);
+ float sumWeight = 0.0f;
+ for (uint32_t k = 0; k < numBonesPerVertex; k++)
+ {
+ const float weight = numBonesPerVertex > 1 ? boneWeights[vertexID * numBonesPerVertex + k] : 1.0f;
+ if (weight > 0.0f)
+ {
+ const PxMat44 matrix = transformation[boneIndices[vertexID * numBonesPerVertex + k]];
+ sumWeight += weight;
+ position += matrix.transform(positions[vertexID]) * weight;
+ normal += matrix.rotate(normals[vertexID]) * weight;
+ }
+ }
+ if (sumWeight > 0.0f)
+ {
+ PX_ASSERT(sumWeight >= 0.9999f);
+ PX_ASSERT(sumWeight <= 1.0001f);
+
+ positions[vertexID] = position;
+ normals[vertexID] = normal;
+ }
+ }
+ }
+ }
+
+ PX_ASSERT(mGraphicalLods.size() == mGraphicalMeshesRuntime.size());
+ for (uint32_t graphicalMeshIndex = 0; graphicalMeshIndex < mGraphicalLods.size(); graphicalMeshIndex++)
+ {
+ ClothingGraphicalMeshAsset meshAsset(*mGraphicalMeshesRuntime[graphicalMeshIndex]);
+ const uint32_t submeshCount = meshAsset.getSubmeshCount();
+
+ for (uint32_t submeshIndex = 0; submeshIndex < submeshCount; submeshIndex++)
+ {
+ const uint32_t numBonesPerVertex = meshAsset.getNumBonesPerVertex(submeshIndex);
+ const uint32_t numVertices = meshAsset.getNumVertices(submeshIndex);
+
+ if (numBonesPerVertex > 0 && numVertices > 0)
+ {
+ RenderDataFormat::Enum outFormat;
+ const uint16_t* boneIndices = (const uint16_t*)meshAsset.getVertexBuffer(submeshIndex, RenderVertexSemantic::BONE_INDEX, outFormat);
+ const float* boneWeights = (const float*)meshAsset.getVertexBuffer(submeshIndex, RenderVertexSemantic::BONE_WEIGHT, outFormat);
+
+ PxVec3* positions = (PxVec3*)meshAsset.getVertexBuffer(submeshIndex, RenderVertexSemantic::POSITION, outFormat);
+ PxVec3* normals = (PxVec3*)meshAsset.getVertexBuffer(submeshIndex, RenderVertexSemantic::NORMAL, outFormat);
+ PxVec3* tangents = (PxVec3*)meshAsset.getVertexBuffer(submeshIndex, RenderVertexSemantic::TANGENT, outFormat);
+ PxVec3* bitangents = (PxVec3*)meshAsset.getVertexBuffer(submeshIndex, RenderVertexSemantic::BINORMAL, outFormat);
+
+ if (boneWeights != NULL || numBonesPerVertex == 1)
+ {
+ for (uint32_t vertexID = 0; vertexID < numVertices; vertexID++)
+ {
+ PxVec3 position(0.0f, 0.0f, 0.0f);
+ PxVec3 normal(0.0f, 0.0f, 0.0f);
+ PxVec3 tangent(0.0f, 0.0f, 0.0f);
+ PxVec3 bitangent(0.0f, 0.0f, 0.0f);
+ float sumWeight = 0.0f;
+
+ for (uint32_t k = 0; k < numBonesPerVertex; k++)
+ {
+ const float weight = (boneWeights == NULL) ? 1.0f : boneWeights[vertexID * numBonesPerVertex + k];
+ if (weight > 0.0f)
+ {
+ const PxMat44 matrix = transformation[boneIndices[vertexID * numBonesPerVertex + k]];
+
+ if (positions != NULL)
+ {
+ position += matrix.transform(positions[vertexID]) * weight;
+ }
+ if (normals != NULL)
+ {
+ normal += matrix.rotate(normals[vertexID]) * weight;
+ }
+ if (tangents != NULL)
+ {
+ tangent += matrix.rotate(tangents[vertexID]) * weight;
+ }
+ if (bitangents != NULL)
+ {
+ bitangent += matrix.rotate(bitangents[vertexID]) * weight;
+ }
+ }
+ }
+
+ if (sumWeight != 0.0f)
+ {
+ PX_ASSERT(sumWeight > 0.9999f);
+ PX_ASSERT(sumWeight < 1.0001f);
+
+ // copy back
+ if (positions != NULL)
+ {
+ positions[vertexID] = position;
+ }
+ if (normals != NULL)
+ {
+ normals[vertexID] = normal * ClothingUserRecompute::invSqrt(normal.magnitudeSquared());
+ }
+ if (tangents != NULL)
+ {
+ tangents[vertexID] = tangent * ClothingUserRecompute::invSqrt(tangent.magnitudeSquared());
+ }
+ if (bitangents != NULL)
+ {
+ bitangents[vertexID] = bitangent * ClothingUserRecompute::invSqrt(bitangent.magnitudeSquared());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ if (errorInSize > -1)
+ {
+ APEX_INVALID_PARAMETER("newBindPosesCount must be bigger than %d (is %d)", errorInSize, newBindPosesCount);
+ }
+}
+
+
+void ClothingAssetAuthoringImpl::destroy()
+{
+ if (!mOwnsMaterialLibrary)
+ {
+ PX_ASSERT(mParams != NULL);
+ mParams->materialLibrary = NULL;
+ }
+
+ ClothingAssetImpl::destroy(); // delete gets called in here
+}
+
+
+
+// ----- protected methods ----------------
+
+
+uint32_t ClothingAssetAuthoringImpl::addBoneConvexInternal(uint32_t boneIndex, const PxVec3* positions, uint32_t numPositions)
+{
+ // compute average
+ PxVec3 average(0.0f, 0.0f, 0.0f);
+
+ uint32_t maxNumberPositions = PxMin(20u, numPositions);
+ uint32_t newNumPositions = 0;
+
+ Array<PxVec3> newPositions(numPositions);
+ Array<float> minDist(numPositions, PX_MAX_F32);
+
+ if (numPositions > 0)
+ {
+ for (uint32_t i = 0; i < numPositions; i++)
+ {
+ average += positions[i];
+ }
+ average /= (float)numPositions;
+
+ float squaredDistFromAverage = (average - positions[0]).magnitudeSquared();
+ uint32_t startVertex = 0;
+ for (uint32_t i = 1; i < numPositions; i++)
+ {
+ float squaredDist = (average - positions[i]).magnitudeSquared();
+ if (squaredDist > squaredDistFromAverage)
+ {
+ squaredDistFromAverage = squaredDist;
+ startVertex = i;
+ }
+ }
+
+ for (uint32_t i = 0; i < numPositions; i++)
+ {
+ newPositions[i] = positions[i];
+ }
+
+ if (startVertex != 0)
+ {
+ newPositions[0] = positions[startVertex];
+ newPositions[startVertex] = positions[0];
+ }
+
+
+ for (uint32_t i = 1; i < maxNumberPositions; i++)
+ {
+ float max = 0.0f;
+ int32_t maxj = -1;
+ for (uint32_t j = i; j < numPositions; j++)
+ {
+ const float distSquared = (newPositions[j] - newPositions[i - 1]).magnitudeSquared();
+ if (distSquared < minDist[j])
+ {
+ minDist[j] = distSquared;
+ }
+
+ if (minDist[j] > max)
+ {
+ max = minDist[j];
+ maxj = (int32_t)j;
+ }
+ }
+
+ if (maxj < 0)
+ {
+ break;
+ }
+
+ const PxVec3 v = newPositions[i];
+ newPositions[i] = newPositions[(uint32_t)maxj];
+ newPositions[(uint32_t)maxj] = v;
+
+ const float dist = minDist[i];
+ minDist[i] = minDist[(uint32_t)maxj];
+ minDist[(uint32_t)maxj] = dist;
+ newNumPositions = i + 1;
+ }
+
+ ClothingAssetParametersNS::ActorEntry_Type& newEntry = mBoneActors.pushBack();
+ memset(&newEntry, 0, sizeof(ClothingAssetParametersNS::ActorEntry_Type));
+ newEntry.boneIndex = (int32_t)boneIndex;
+ newEntry.convexVerticesStart = mBoneVertices.size();
+ newEntry.convexVerticesCount = newNumPositions;
+ for (uint32_t i = 0; i < newNumPositions; i++)
+ {
+ mBoneVertices.pushBack(newPositions[i]);
+ }
+ compressBoneCollision();
+ }
+ clearCooked();
+
+
+ // extract planes from points
+ ConvexHullImpl convexHull;
+ convexHull.init();
+ Array<PxPlane> planes;
+
+ convexHull.buildFromPoints(&newPositions[0], newNumPositions, sizeof(PxVec3));
+
+ uint32_t planeCount = convexHull.getPlaneCount();
+ if (planeCount + mBonePlanes.size() > 32)
+ {
+ APEX_DEBUG_WARNING("The asset is trying to use more than 32 planes for convexes. The collision convex will not be simulated with 3.x cloth.");
+ }
+ else
+ {
+ uint32_t convex = 0; // each bit references a plane
+ for (uint32_t i = 0; i < planeCount; ++i)
+ {
+ PxPlane plane = convexHull.getPlane(i);
+ convex |= 1 << mBonePlanes.size();
+
+ ClothingAssetParametersNS::BonePlane_Type& newEntry = mBonePlanes.pushBack();
+ memset(&newEntry, 0, sizeof(ClothingAssetParametersNS::BonePlane_Type));
+ newEntry.boneIndex = (int32_t)boneIndex;
+ newEntry.n = plane.n;
+ newEntry.d = plane.d;
+ }
+
+ mCollisionConvexes.pushBack(convex);
+ }
+
+
+ return newNumPositions;
+}
+
+
+
+void ClothingAssetAuthoringImpl::addBoneCapsuleInternal(uint32_t boneIndex, float capsuleRadius, float capsuleHeight, const PxMat44& localPose)
+{
+ PX_ASSERT(boneIndex < mBones.size());
+ if (capsuleRadius > 0)
+ {
+ ClothingAssetParametersNS::ActorEntry_Type& newEntry = mBoneActors.pushBack();
+ memset(&newEntry, 0, sizeof(ClothingAssetParametersNS::ActorEntry_Type));
+ newEntry.boneIndex = (int32_t)boneIndex;
+ newEntry.capsuleRadius = capsuleRadius;
+ newEntry.capsuleHeight = capsuleHeight;
+ newEntry.localPose = localPose;
+ }
+}
+
+
+
+void ClothingAssetAuthoringImpl::clearBoneActorsInternal(int32_t internalBoneIndex)
+{
+ PX_ASSERT(internalBoneIndex >= 0);
+ for (uint32_t i = 0; i < mBoneActors.size(); i++)
+ {
+ if (mBoneActors[i].boneIndex == internalBoneIndex)
+ {
+ mBoneActors[i].boneIndex = -1;
+ }
+ }
+
+ compressBoneCollision();
+}
+
+
+
+void ClothingAssetAuthoringImpl::compressBones() const
+{
+ if (mBones.isEmpty())
+ {
+ return;
+ }
+
+ // reset counters
+ mParams->rootBoneIndex = uint32_t(-1);
+ for (uint32_t i = 0; i < mBones.size(); i++)
+ {
+ mBones[i].numMeshReferenced = 0;
+ mBones[i].numRigidBodiesReferenced = 0;
+
+ if (::strcmp(mBones[i].name, mRootBoneName.c_str()) == 0)
+ {
+ // set root bone index
+ mParams->rootBoneIndex = i;
+
+ // declare bone as referenced
+ mBones[i].numRigidBodiesReferenced++;
+ }
+ }
+
+ // update bone reference count from graphics mesh
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ ClothingGraphicalMeshAssetWrapper meshAsset(reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[i]->renderMeshAssetPointer));
+
+ for (uint32_t submeshIndex = 0; submeshIndex < meshAsset.getSubmeshCount(); submeshIndex++)
+ {
+ RenderDataFormat::Enum outFormat;
+ const uint16_t* boneIndices = (const uint16_t*)meshAsset.getVertexBuffer(submeshIndex, RenderVertexSemantic::BONE_INDEX, outFormat);
+ if (outFormat != RenderDataFormat::USHORT1 && outFormat != RenderDataFormat::USHORT2 &&
+ outFormat != RenderDataFormat::USHORT3 && outFormat != RenderDataFormat::USHORT4)
+ {
+ boneIndices = NULL;
+ }
+
+ const float* boneWeights = (const float*)meshAsset.getVertexBuffer(submeshIndex, RenderVertexSemantic::BONE_WEIGHT, outFormat);
+ if (outFormat != RenderDataFormat::FLOAT1 && outFormat != RenderDataFormat::FLOAT2 &&
+ outFormat != RenderDataFormat::FLOAT3 && outFormat != RenderDataFormat::FLOAT4)
+ {
+ boneWeights = NULL;
+ }
+
+ collectBoneIndices(meshAsset.getNumVertices(submeshIndex), boneIndices, boneWeights, meshAsset.getNumBonesPerVertex(submeshIndex));
+ }
+ }
+
+ // update bone reference count from physics mesh
+ for (uint32_t i = 0; i < mPhysicalMeshes.size(); i++)
+ {
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type& physicalMesh = mPhysicalMeshes[i]->physicalMesh;
+ collectBoneIndices(physicalMesh.numVertices, physicalMesh.boneIndices.buf, physicalMesh.boneWeights.buf, physicalMesh.numBonesPerVertex);
+ }
+
+ // update bone reference count from bone actors
+ for (uint32_t i = 0; i < mBoneActors.size(); i++)
+ {
+ mBones[(uint32_t)mBoneActors[i].boneIndex].numRigidBodiesReferenced++;
+ }
+
+ // update bone reference count from spheres
+ for (uint32_t i = 0; i < mBoneSpheres.size(); i++)
+ {
+ mBones[(uint32_t)mBoneSpheres[i].boneIndex].numRigidBodiesReferenced++;
+ }
+
+ // update bone reference count from spheres
+ for (uint32_t i = 0; i < mBonePlanes.size(); i++)
+ {
+ mBones[(uint32_t)mBonePlanes[i].boneIndex].numRigidBodiesReferenced++;
+ }
+
+ // sort the bones to the following structure:
+ // |-- bones referenced by mesh --|-- bones referenced by collision RBs, but not mesh --|-- unreferenced bones --|
+ {
+ BoneEntryPredicate predicate;
+ sort(mBones.begin(), mBones.size(), predicate);
+ }
+
+
+ // create map from old indices to new ones and store the number of used bones
+ Array<int32_t> old2new(mBones.size(), -1);
+ mParams->bonesReferenced = 0;
+ mParams->bonesReferencedByMesh = 0;
+ for (uint32_t i = 0; i < mBones.size(); i++)
+ {
+ if (mBones[i].numMeshReferenced > 0)
+ {
+ mParams->bonesReferencedByMesh++;
+ }
+
+ if (mBones[i].numMeshReferenced > 0 || mBones[i].numRigidBodiesReferenced > 0)
+ {
+ mParams->bonesReferenced++;
+ }
+
+ old2new[(uint32_t)mBones[i].internalIndex] = (int32_t)i;
+ mBones[i].internalIndex = (int32_t)i;
+ }
+
+ // update bone indices in parent
+ for (uint32_t i = 0; i < mBones.size(); i++)
+ {
+ if (mBones[i].parentIndex != -1)
+ {
+ mBones[i].parentIndex = old2new[(uint32_t)mBones[i].parentIndex];
+ }
+ }
+
+ // update bone indices in bone actors
+ for (uint32_t i = 0; i < mBoneActors.size(); i++)
+ {
+ PX_ASSERT(mBoneActors[i].boneIndex != -1);
+ mBoneActors[i].boneIndex = old2new[(uint32_t)mBoneActors[i].boneIndex];
+ }
+
+ // update bone indices in bone spheres
+ for (uint32_t i = 0; i < mBoneSpheres.size(); i++)
+ {
+ PX_ASSERT(mBoneSpheres[i].boneIndex != -1);
+ mBoneSpheres[i].boneIndex = old2new[(uint32_t)mBoneSpheres[i].boneIndex];
+ }
+
+ // update bone indices in bone planes
+ for (uint32_t i = 0; i < mBonePlanes.size(); i++)
+ {
+ PX_ASSERT(mBonePlanes[i].boneIndex != -1);
+ mBonePlanes[i].boneIndex = old2new[(uint32_t)mBonePlanes[i].boneIndex];
+ }
+
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[i]->renderMeshAssetPointer)->permuteBoneIndices(old2new);
+ }
+
+ for (uint32_t i = 0; i < mPhysicalMeshes.size(); i++)
+ {
+ ClothingPhysicalMeshImpl* mesh = mModule->createPhysicalMeshInternal(mPhysicalMeshes[i]);
+ mesh->permuteBoneIndices(old2new);
+ mesh->release();
+ }
+
+ if (mParams->rootBoneIndex == uint32_t(-1))
+ {
+ // no root bone defined, find one within referenced bones
+ mParams->rootBoneIndex = 0;
+ uint32_t minDepth = mBones.size();
+ for (uint32_t i = 0; i < mParams->bonesReferenced; i++)
+ {
+ uint32_t depth = 0;
+ int32_t parent = mBones[i].parentIndex;
+ while (parent != -1 && depth < mBones.size())
+ {
+ parent = mBones[(uint32_t)parent].parentIndex;
+ depth++;
+ }
+
+ if (depth < minDepth)
+ {
+ minDepth = depth;
+ mParams->rootBoneIndex = i;
+ }
+ }
+ }
+ else
+ {
+ // update root bone index
+ mParams->rootBoneIndex = (uint32_t)old2new[mParams->rootBoneIndex];
+ }
+ PX_ASSERT(mParams->rootBoneIndex < mParams->bonesReferenced);
+}
+
+
+
+void ClothingAssetAuthoringImpl::compressBoneCollision()
+{
+ const PxVec3* oldBoneVertices = (const PxVec3*)GetInternalApexSDK()->getTempMemory(sizeof(PxVec3) * mBoneVertices.size());
+ if (oldBoneVertices == NULL)
+ {
+ return;
+ }
+
+ memcpy(const_cast<PxVec3*>(oldBoneVertices), mBoneVertices.begin(), sizeof(PxVec3) * mBoneVertices.size());
+
+ // clean out all unused actors
+ for (int32_t i = (int32_t)mBoneActors.size() - 1; i >= 0; i--)
+ {
+ if (mBoneActors[(uint32_t)i].boneIndex < 0)
+ {
+ mBoneActors.replaceWithLast((uint32_t)i);
+ }
+ }
+ if (!mBoneActors.isEmpty())
+ {
+ nvidia::sort(mBoneActors.begin(), mBoneActors.size(), ActorEntryPredicate());
+ }
+
+ uint32_t boneVerticesWritten = 0;
+ for (uint32_t i = 0; i < mBoneActors.size(); i++)
+ {
+ if (mBoneActors[i].convexVerticesCount == 0)
+ {
+ mBoneActors[i].convexVerticesStart = 0;
+ }
+ else
+ {
+ const uint32_t oldStart = mBoneActors[i].convexVerticesStart;
+ const uint32_t count = mBoneActors[i].convexVerticesCount;
+ mBoneActors[i].convexVerticesStart = boneVerticesWritten;
+ for (uint32_t j = 0; j < count; j++)
+ {
+ mBoneVertices[boneVerticesWritten++] = oldBoneVertices[oldStart + j];
+ }
+ }
+ }
+ mBoneVertices.resize(boneVerticesWritten);
+
+ GetInternalApexSDK()->releaseTempMemory(const_cast<PxVec3*>(oldBoneVertices));
+ clearCooked();
+}
+
+
+
+void ClothingAssetAuthoringImpl::collectBoneIndices(uint32_t numVertices, const uint16_t* boneIndices, const float* boneWeights, uint32_t numBonesPerVertex) const
+{
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ for (uint32_t j = 0; j < numBonesPerVertex; j++)
+ {
+ uint16_t index = boneIndices[i * numBonesPerVertex + j];
+ float weight = (boneWeights == NULL) ? 1.0f : boneWeights[i * numBonesPerVertex + j];
+ if (weight > 0.0f)
+ {
+ PX_ASSERT(index < mBones.size());
+ PX_ASSERT(mBones[index].internalIndex == (int32_t)index);
+ mBones[index].numMeshReferenced++;
+ }
+ }
+ }
+}
+
+
+
+struct Confidentially
+{
+ Confidentially() : maxDistConfidence(0.0f), collisionDistConfidence(0.0f), collisionRadiusConfidence(0.0f), normalConfidence(0.0f) {}
+ float maxDistConfidence;
+ float collisionDistConfidence;
+ float collisionRadiusConfidence;
+ float normalConfidence;
+};
+
+
+
+void ClothingAssetAuthoringImpl::updateMappingAuthoring(ClothingGraphicalLodParameters& graphicalLod, RenderMeshAssetIntl* renderMeshAssetCopy,
+ RenderMeshAssetAuthoringIntl* renderMeshAssetOrig, float normalResemblance, bool ignoreUnusedVertices, IProgressListener* progressListener)
+{
+ if (graphicalLod.physicalMeshId == (uint32_t) - 1 || renderMeshAssetCopy == NULL)
+ {
+ return;
+ }
+
+ const uint32_t physicalMeshId = graphicalLod.physicalMeshId;
+
+ if (normalResemblance < 0)
+ {
+ APEX_DEBUG_WARNING("A normal resemblance of %f not allowed, must be positive.", normalResemblance);
+ normalResemblance = 90.0f;
+ }
+ else if (normalResemblance < 5)
+ {
+ APEX_DEBUG_WARNING("A physicalNormal resemblance of %f is very small, it might discard too many values", normalResemblance);
+ }
+ else if (normalResemblance > 90.0f)
+ {
+ normalResemblance = 90.0f;
+ }
+
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type& physicalMesh = mPhysicalMeshes[physicalMeshId]->physicalMesh;
+ uint32_t* masterFlags = mPhysicalMeshesInput[physicalMeshId]->getMasterFlagsBuffer();
+
+ bool skipConstraints = false;
+ if (physicalMesh.constrainCoefficients.arraySizes[0] != 0)
+ {
+ skipConstraints = true;
+ }
+
+ PX_ASSERT(graphicalLod.immediateClothMap.buf == NULL);
+ PX_ASSERT(graphicalLod.skinClothMapB.buf == NULL);
+ PX_ASSERT(graphicalLod.tetraMap.buf == NULL);
+
+ HierarchicalProgressListener progress(100, progressListener);
+
+ Array<AbstractMeshDescription> targetMeshes(renderMeshAssetCopy->getSubmeshCount());
+ uint32_t numTotalVertices = 0;
+ bool hasTangents = false;
+ for (uint32_t submeshIndex = 0; submeshIndex < targetMeshes.size(); submeshIndex++)
+ {
+ const VertexBuffer& vb = renderMeshAssetCopy->getSubmesh(submeshIndex).getVertexBuffer();
+ const VertexFormat& vf = vb.getFormat();
+
+ RenderDataFormat::Enum outFormat;
+
+ uint32_t bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::POSITION));
+ targetMeshes[submeshIndex].pPosition = (PxVec3*)vb.getBufferAndFormat(outFormat, bufferIndex);
+ PX_ASSERT(outFormat == RenderDataFormat::FLOAT3);
+
+ bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::NORMAL));
+ targetMeshes[submeshIndex].pNormal = (PxVec3*)(vb.getBufferAndFormat(outFormat, bufferIndex));
+ if (outFormat != RenderDataFormat::FLOAT3)
+ {
+ // Phil - you might need to handle other normal formats
+ targetMeshes[submeshIndex].pNormal = NULL;
+ }
+
+ bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::TANGENT));
+ const void* tangents = vb.getBufferAndFormat(outFormat, bufferIndex);
+ if (outFormat == RenderDataFormat::FLOAT3)
+ {
+ targetMeshes[submeshIndex].pTangent = (PxVec3*)tangents;
+ hasTangents = true;
+ }
+ else if (outFormat == RenderDataFormat::FLOAT4)
+ {
+ targetMeshes[submeshIndex].pTangent4 = (PxVec4*)tangents;
+ hasTangents = true;
+ }
+
+ const uint32_t numVertices = renderMeshAssetCopy->getSubmesh(submeshIndex).getVertexCount(0);
+ targetMeshes[submeshIndex].numVertices = numVertices;
+
+ bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID(LATCH_TO_NEAREST_SLAVE_NAME));
+ uint32_t* submeshSlaveFlags = (uint32_t*)vb.getBufferAndFormat(outFormat, bufferIndex);
+ targetMeshes[submeshIndex].pVertexFlags = submeshSlaveFlags;
+ PX_ASSERT(submeshSlaveFlags == NULL || outFormat == RenderDataFormat::UINT1);
+
+ if (!skipConstraints)
+ {
+ bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID(LATCH_TO_NEAREST_MASTER_NAME));
+ uint32_t* submeshMasterFlags = (uint32_t*)vb.getBufferAndFormat(outFormat, bufferIndex);
+ PX_ASSERT(submeshMasterFlags == NULL || outFormat == RenderDataFormat::UINT1);
+
+ if (submeshSlaveFlags != NULL && submeshMasterFlags != NULL)
+ {
+ // overwrite the empty slaves with the master mask
+ // provides self-attachment, very important!
+ // the original slave values are in the orig render mesh still
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ if (submeshSlaveFlags[i] == 0)
+ {
+ submeshSlaveFlags[i] = submeshMasterFlags[i];
+ }
+ if (submeshSlaveFlags[i] == 0)
+ {
+ submeshSlaveFlags[i] = 0xffffffff;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (submeshSlaveFlags != NULL)
+ {
+ // overwrite the empty slaves with 0xffffffff flags
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ if (submeshSlaveFlags[i] == 0)
+ {
+ submeshSlaveFlags[i] = 0xffffffff;
+ }
+ }
+ }
+ }
+
+ numTotalVertices += targetMeshes[submeshIndex].numVertices;
+ }
+
+ if (physicalMesh.isTetrahedralMesh)
+ {
+ ParamArray<ClothingGraphicalLodParametersNS::TetraLink_Type> tetraMap(&graphicalLod, "tetraMap", reinterpret_cast<ParamDynamicArrayStruct*>(&graphicalLod.tetraMap));
+ progress.setSubtaskWork(50, "Generate Tetra Map");
+ generateTetraMap(targetMeshes.begin(), targetMeshes.size(), physicalMesh, masterFlags, tetraMap, &progress);
+ progress.completeSubtask();
+ }
+ else
+ {
+ ParamArray<uint32_t> immediateClothMap(&graphicalLod, "immediateClothMap", reinterpret_cast<ParamDynamicArrayStruct*>(&graphicalLod.immediateClothMap));
+ uint32_t numNotFoundVertices = 0;
+ progress.setSubtaskWork(5, "Generate immediate mapping");
+
+
+ generateImmediateClothMap(targetMeshes.begin(), targetMeshes.size(), physicalMesh, masterFlags,
+ 0.0f, numNotFoundVertices, normalResemblance, immediateClothMap, &progress);
+
+ progress.completeSubtask();
+
+ if (immediateClothMap.isEmpty() || numNotFoundVertices > 0 || hasTangents)
+ {
+ // if more than 3/4 of all vertices are not found, completely forget about immediate mode.
+ const bool clearImmediateMap = (numNotFoundVertices > numTotalVertices * 3 / 4);
+
+ progress.setSubtaskWork(45, "Generate mesh-mesh skinning");
+ ParamArray<SkinClothMap> skinClothMap(&graphicalLod, "skinClothMap",
+ reinterpret_cast<ParamDynamicArrayStruct*>(&graphicalLod.skinClothMap));
+
+ generateSkinClothMap(targetMeshes.begin(), targetMeshes.size(), physicalMesh,
+ masterFlags, graphicalLod.immediateClothMap.buf, numNotFoundVertices,
+ skinClothMap, graphicalLod.skinClothMapOffset, clearImmediateMap, &progress);
+
+ graphicalLod.skinClothMapThickness = 1.0f;
+
+ progress.completeSubtask();
+
+ if (clearImmediateMap)
+ {
+ immediateClothMap.clear();
+ }
+ }
+ }
+
+ if (physicalMesh.normals.arraySizes[0] == 0)
+ {
+ progress.setSubtaskWork(50, "Update Painting");
+
+ // update painting stuff from all submeshes
+
+ ClothingPhysicalMeshImpl* tempMesh = mModule->createPhysicalMeshInternal(mPhysicalMeshes[physicalMeshId]);
+
+ tempMesh->allocateNormalBuffer();
+ if (!skipConstraints)
+ {
+ tempMesh->allocateConstrainCoefficientBuffer();
+ }
+
+ AbstractMeshDescription pMesh;
+ pMesh.pPosition = physicalMesh.vertices.buf;
+ pMesh.pNormal = physicalMesh.normals.buf;
+ ClothingPhysicalMeshParametersNS::ConstrainCoefficient_Type* myConstrains = physicalMesh.constrainCoefficients.buf;
+ pMesh.numVertices = physicalMesh.numVertices;
+
+ pMesh.pIndices = physicalMesh.indices.buf;
+ pMesh.numIndices = physicalMesh.numIndices;
+
+ uint32_t maxNumBonesPerVertex = 0;
+ for (uint32_t submeshIndex = 0; submeshIndex < renderMeshAssetCopy->getSubmeshCount(); submeshIndex++)
+ {
+ const VertexFormat& vf = renderMeshAssetCopy->getSubmesh(submeshIndex).getVertexBuffer().getFormat();
+ RenderDataFormat::Enum format = vf.getBufferFormat((uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::BONE_INDEX)));
+ const uint32_t numBonesPerVertex = vertexSemanticFormatElementCount(RenderVertexSemantic::BONE_INDEX, format);
+ maxNumBonesPerVertex = PxMax(maxNumBonesPerVertex, numBonesPerVertex);
+ }
+
+ if (maxNumBonesPerVertex > 0)
+ {
+ tempMesh->setNumBonesPerVertex(maxNumBonesPerVertex);
+ tempMesh->allocateBoneIndexAndWeightBuffers();
+ pMesh.numBonesPerVertex = maxNumBonesPerVertex;
+ pMesh.pBoneIndices = physicalMesh.boneIndices.buf;
+ pMesh.pBoneWeights = physicalMesh.boneWeights.buf;
+ }
+
+ Array<Confidentially> confidence(pMesh.numVertices);
+
+ uint32_t graphicalVertexOffset = 0;
+ const uint32_t numGraphicalVerticesTotal = numTotalVertices;
+ PX_ASSERT(renderMeshAssetCopy->getSubmeshCount() == renderMeshAssetOrig->getSubmeshCount());
+
+ for (uint32_t submeshIndex = 0; submeshIndex < renderMeshAssetCopy->getSubmeshCount(); submeshIndex++)
+ {
+ const VertexBuffer& vb = renderMeshAssetCopy->getSubmesh(submeshIndex).getVertexBuffer();
+
+ if (vb.getVertexCount() == 0)
+ {
+ APEX_DEBUG_WARNING("submesh %d has no vertices at all!", submeshIndex);
+ continue;
+ }
+
+ const VertexBuffer& vbOrig = renderMeshAssetOrig->getSubmesh(submeshIndex).getVertexBuffer();
+ PX_ASSERT(vbOrig.getVertexCount() == vb.getVertexCount());
+
+ const VertexFormat& vf = vb.getFormat();
+ const uint32_t graphicalMaxDistanceIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID(MAX_DISTANCE_NAME));
+ RenderDataFormat::Enum outFormat = vf.getBufferFormat(graphicalMaxDistanceIndex);
+ const float* graphicalMaxDistance = outFormat == RenderDataFormat::UNSPECIFIED ? NULL :
+ reinterpret_cast<const float*>(vb.getBuffer(graphicalMaxDistanceIndex));
+ PX_ASSERT(graphicalMaxDistance == NULL || outFormat == RenderDataFormat::FLOAT1);
+
+ const uint32_t graphicalCollisionSphereRadiusIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID(COLLISION_SPHERE_RADIUS_NAME));
+ outFormat = vf.getBufferFormat(graphicalCollisionSphereRadiusIndex);
+ const float* graphicalCollisionSphereRadius = outFormat == RenderDataFormat::UNSPECIFIED ? NULL :
+ reinterpret_cast<const float*>(vb.getBuffer(graphicalCollisionSphereRadiusIndex));
+ PX_ASSERT(graphicalCollisionSphereRadius == NULL || outFormat == RenderDataFormat::FLOAT1);
+
+ const uint32_t graphicalCollisionSphereDistanceIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID(COLLISION_SPHERE_DISTANCE_NAME));
+ outFormat = vf.getBufferFormat(graphicalCollisionSphereDistanceIndex);
+ const float* graphicalCollisionSphereDistance = outFormat == RenderDataFormat::UNSPECIFIED ? NULL :
+ reinterpret_cast<const float*>(vb.getBuffer(graphicalCollisionSphereDistanceIndex));
+ PX_ASSERT(graphicalCollisionSphereDistance == NULL || outFormat == RenderDataFormat::FLOAT1);
+ PX_ASSERT((graphicalCollisionSphereDistance == NULL && graphicalCollisionSphereRadius == NULL) || (graphicalCollisionSphereDistance != NULL && graphicalCollisionSphereRadius != NULL));
+
+ const uint32_t graphicalUsedForPhysicsIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID(USED_FOR_PHYSICS_NAME));
+ outFormat = vf.getBufferFormat(graphicalUsedForPhysicsIndex);
+ const uint8_t* graphicalUsedForPhysics = outFormat == RenderDataFormat::UNSPECIFIED ? NULL :
+ reinterpret_cast<const uint8_t*>(vb.getBuffer(graphicalUsedForPhysicsIndex));
+ PX_ASSERT(graphicalUsedForPhysics == NULL || outFormat == RenderDataFormat::UBYTE1);
+
+ const uint32_t graphicalSlaveIndex = (uint32_t)vbOrig.getFormat().getBufferIndexFromID(vbOrig.getFormat().getID(LATCH_TO_NEAREST_SLAVE_NAME));
+ outFormat = vbOrig.getFormat().getBufferFormat(graphicalSlaveIndex);
+ const uint32_t* graphicalSlavesOrig = outFormat != RenderDataFormat::UINT1 ? NULL :
+ reinterpret_cast<const uint32_t*>(vbOrig.getBuffer(graphicalSlaveIndex));
+
+ // should not be used anymore!
+ outFormat = RenderDataFormat::UNSPECIFIED;
+
+ RenderDataFormat::Enum normalFormat;
+ uint32_t bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::NORMAL));
+ const PxVec3* graphicalNormals = reinterpret_cast<const PxVec3*>(vb.getBufferAndFormat(normalFormat, bufferIndex));
+ if (normalFormat != RenderDataFormat::FLOAT3)
+ {
+ // Phil - you might need to handle other normal formats
+ graphicalNormals = NULL;
+ }
+
+ RenderDataFormat::Enum positionFormat;
+ bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::POSITION));
+ const PxVec3* graphicalPositions = reinterpret_cast<const PxVec3*>(vb.getBufferAndFormat(positionFormat, bufferIndex));
+ if (positionFormat != RenderDataFormat::FLOAT3)
+ {
+ graphicalPositions = NULL;
+ }
+
+ RenderDataFormat::Enum boneIndexFormat;
+ bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::BONE_INDEX));
+ const uint16_t* graphicalBoneIndices = (const uint16_t*)vb.getBufferAndFormat(boneIndexFormat, bufferIndex);
+ if (boneIndexFormat != RenderDataFormat::USHORT1 && boneIndexFormat != RenderDataFormat::USHORT2 &&
+ boneIndexFormat != RenderDataFormat::USHORT3 && boneIndexFormat != RenderDataFormat::USHORT4)
+ {
+ // Phil - you might need to handle other normal formats
+ graphicalBoneIndices = NULL;
+ }
+
+ RenderDataFormat::Enum boneWeightFormat;
+ bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::BONE_WEIGHT));
+ const float* graphicalBoneWeights = reinterpret_cast<const float*>(vb.getBufferAndFormat(boneWeightFormat, bufferIndex));
+ if (boneWeightFormat != RenderDataFormat::FLOAT1 && boneWeightFormat != RenderDataFormat::FLOAT2 &&
+ boneWeightFormat != RenderDataFormat::FLOAT3 && boneWeightFormat != RenderDataFormat::FLOAT4)
+ {
+ // Phil - you might need to handle other normal formats
+ graphicalBoneWeights = NULL;
+ }
+
+ const uint32_t numBonesPerVertex = vertexSemanticFormatElementCount(RenderVertexSemantic::BONE_INDEX, boneIndexFormat);
+ PX_ASSERT((graphicalBoneIndices == NULL && graphicalBoneWeights == NULL && numBonesPerVertex == 0) ||
+ (graphicalBoneIndices != NULL && numBonesPerVertex > 0));
+
+ const uint32_t numGraphicalVertices = renderMeshAssetCopy->getSubmesh(submeshIndex).getVertexCount(0);
+ for (uint32_t graphicalVertexIndex = 0; graphicalVertexIndex < numGraphicalVertices; graphicalVertexIndex++)
+ {
+ if ((graphicalVertexIndex & 0xff) == 0)
+ {
+ const int32_t percent = int32_t(100 * (graphicalVertexIndex + graphicalVertexOffset) / numGraphicalVerticesTotal);
+ progress.setProgress(percent);
+ }
+
+ // figure out how many physical vertices this graphical vertex relates to
+ uint32_t indices[4];
+ float trust[4];
+
+ const bool isSlave =
+ (graphicalUsedForPhysics != NULL && graphicalUsedForPhysics[graphicalVertexIndex] == 0) ||
+ (graphicalSlavesOrig != NULL && graphicalSlavesOrig[graphicalVertexIndex] != 0);
+
+ uint32_t numIndices = getCorrespondingPhysicalVertices(graphicalLod, submeshIndex, graphicalVertexIndex, pMesh, graphicalVertexOffset, indices, trust);
+
+ // now we have the relevant physical vertices in indices[4]
+
+ if (!skipConstraints && graphicalMaxDistance != NULL && graphicalMaxDistance[graphicalVertexIndex] != mInvalidConstrainCoefficients.maxDistance &&
+ graphicalMaxDistance[graphicalVertexIndex] < 0.0f)
+ {
+ APEX_INVALID_PARAMETER("Max Distance at vertex %d (submesh %d) must be >= 0.0 (is %f) or equal to invalid (%f)",
+ graphicalVertexIndex, submeshIndex, graphicalMaxDistance[graphicalVertexIndex], mInvalidConstrainCoefficients.maxDistance);
+ }
+
+ for (uint32_t temporalIndex = 0; temporalIndex < numIndices; temporalIndex++)
+ {
+ const uint32_t vertexIndex = indices[temporalIndex];
+ const float vertexTrust = trust[temporalIndex];
+
+ if (ignoreUnusedVertices && isSlave)
+ {
+ continue;
+ }
+
+ if (vertexTrust < -0.0001f)
+ {
+ continue;
+ }
+
+ const float confidenceDelta = 0.1f;
+ if (!skipConstraints)
+ {
+ if (graphicalMaxDistance != NULL && graphicalMaxDistance[graphicalVertexIndex] != mInvalidConstrainCoefficients.maxDistance)
+ {
+ if (vertexTrust + confidenceDelta > confidence[vertexIndex].maxDistConfidence)
+ {
+ confidence[vertexIndex].maxDistConfidence = vertexTrust;
+
+ float& target = myConstrains[vertexIndex].maxDistance;
+ const float source = graphicalMaxDistance[graphicalVertexIndex];
+
+ target = source;
+ }
+ }
+
+ if (graphicalCollisionSphereDistance != NULL && graphicalCollisionSphereDistance[graphicalVertexIndex] != mInvalidConstrainCoefficients.collisionSphereDistance)
+ {
+ if (vertexTrust + confidenceDelta > confidence[vertexIndex].collisionDistConfidence)
+ {
+ confidence[vertexIndex].collisionDistConfidence = vertexTrust;
+
+ const float source = graphicalCollisionSphereDistance[graphicalVertexIndex];
+ float& target = myConstrains[vertexIndex].collisionSphereDistance;
+
+ target = source;
+ }
+ }
+
+ if (graphicalCollisionSphereRadius != NULL && graphicalCollisionSphereRadius[graphicalVertexIndex] != mInvalidConstrainCoefficients.collisionSphereRadius)
+ {
+ if (vertexTrust + confidenceDelta > confidence[vertexIndex].collisionRadiusConfidence)
+ {
+ confidence[vertexIndex].collisionRadiusConfidence = vertexTrust;
+
+ float& target = myConstrains[vertexIndex].collisionSphereRadius;
+ const float source = graphicalCollisionSphereRadius[graphicalVertexIndex];
+
+ target = source;
+ }
+ }
+ }
+
+ if (graphicalBoneIndices != NULL)
+ {
+ for (uint32_t i = 0; i < numBonesPerVertex; i++)
+ {
+ const float weight = (graphicalBoneWeights != NULL) ? graphicalBoneWeights[graphicalVertexIndex * numBonesPerVertex + i] : 1.0f;
+ if (weight > 0.0f)
+ {
+ tempMesh->addBoneToVertex(vertexIndex, graphicalBoneIndices[graphicalVertexIndex * numBonesPerVertex + i], weight);
+ }
+ }
+ }
+
+ if (!isSlave)
+ {
+ if (vertexTrust + confidenceDelta > confidence[vertexIndex].normalConfidence)
+ {
+ confidence[vertexIndex].normalConfidence = vertexTrust;
+
+ pMesh.pNormal[vertexIndex] = graphicalNormals[graphicalVertexIndex];
+ }
+ }
+ }
+ }
+
+ graphicalVertexOffset += numGraphicalVertices;
+ }
+
+
+ bool hasMaxDistance = false;
+ bool hasCollisionSphereDistance = false;
+ bool hasCollisionSphereRadius = false;
+ bool hasBoneWeights = false;
+ for (uint32_t i = 0; i < renderMeshAssetCopy->getSubmeshCount(); i++)
+ {
+ const VertexFormat& vf = renderMeshAssetCopy->getSubmesh(i).getVertexBuffer().getFormat();
+ RenderDataFormat::Enum outFormat;
+ outFormat = vf.getBufferFormat((uint32_t)vf.getBufferIndexFromID(vf.getID(MAX_DISTANCE_NAME)));
+ hasMaxDistance |= outFormat == RenderDataFormat::FLOAT1;
+ outFormat = vf.getBufferFormat((uint32_t)vf.getBufferIndexFromID(vf.getID(COLLISION_SPHERE_DISTANCE_NAME)));
+ hasCollisionSphereDistance |= outFormat == RenderDataFormat::FLOAT1;
+ outFormat = vf.getBufferFormat((uint32_t)vf.getBufferIndexFromID(vf.getID(COLLISION_SPHERE_RADIUS_NAME)));
+ hasCollisionSphereRadius |= outFormat == RenderDataFormat::FLOAT1;
+ outFormat = vf.getBufferFormat((uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::BONE_WEIGHT)));
+ hasBoneWeights |= outFormat != RenderDataFormat::UNSPECIFIED;
+ }
+
+ // all values that have not been set are set by nearest neighbor
+ uint32_t count[5] = { 0, 0, 0, 0, 0 };
+ const uint32_t numVertices = physicalMesh.numVertices;
+ for (uint32_t vertexIndex = 0; vertexIndex < numVertices; vertexIndex++)
+ {
+ if (!skipConstraints)
+ {
+ float& physicalMaxDistance = myConstrains[vertexIndex].maxDistance;
+ if (physicalMaxDistance == PX_MAX_F32)
+ {
+ count[0]++;
+ uint32_t submeshIndex = 0, graphicalVertexIndex = 0;
+ if (hasMaxDistance && getClosestVertex(renderMeshAssetOrig, pMesh.pPosition[vertexIndex], submeshIndex, graphicalVertexIndex, MAX_DISTANCE_NAME, ignoreUnusedVertices))
+ {
+ const VertexFormat& vf = renderMeshAssetCopy->getSubmesh(submeshIndex).getVertexBuffer().getFormat();
+ const uint32_t graphicalMaxDistanceIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID(MAX_DISTANCE_NAME));
+ RenderDataFormat::Enum outFormat = vf.getBufferFormat(graphicalMaxDistanceIndex);
+ const float* graphicalMaxDistance = reinterpret_cast<const float*>(renderMeshAssetCopy->getSubmesh(submeshIndex).getVertexBuffer().getBuffer(graphicalMaxDistanceIndex));
+
+ PX_ASSERT(outFormat == RenderDataFormat::FLOAT1);
+ if (outFormat == RenderDataFormat::FLOAT1)
+ {
+ physicalMaxDistance = PxMax(0.0f, graphicalMaxDistance[graphicalVertexIndex]);
+ }
+ }
+ else
+ {
+ physicalMaxDistance = 0.0f;
+ }
+ }
+
+ float& physicalCollisionSphereDistance = myConstrains[vertexIndex].collisionSphereDistance;
+ if (physicalCollisionSphereDistance == PX_MAX_F32)
+ {
+ count[1]++;
+ uint32_t submeshIndex = 0, graphicalVertexIndex = 0;
+ if (hasCollisionSphereDistance && getClosestVertex(renderMeshAssetOrig, pMesh.pPosition[vertexIndex], submeshIndex, graphicalVertexIndex, COLLISION_SPHERE_DISTANCE_NAME, ignoreUnusedVertices))
+ {
+ const VertexFormat& vf = renderMeshAssetCopy->getSubmesh(submeshIndex).getVertexBuffer().getFormat();
+ const uint32_t graphicalCollisionSphereDistanceIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID(COLLISION_SPHERE_DISTANCE_NAME));
+ RenderDataFormat::Enum outFormat = vf.getBufferFormat(graphicalCollisionSphereDistanceIndex);
+ const float* graphicalCollisionSphereDistance = reinterpret_cast<const float*>(renderMeshAssetCopy->getSubmesh(submeshIndex).getVertexBuffer().getBuffer(graphicalCollisionSphereDistanceIndex));
+
+ PX_ASSERT(outFormat == RenderDataFormat::FLOAT1);
+ if (outFormat == RenderDataFormat::FLOAT1)
+ {
+ physicalCollisionSphereDistance = graphicalCollisionSphereDistance[graphicalVertexIndex];
+ }
+ }
+ else
+ {
+ physicalCollisionSphereDistance = 0.0f;
+ }
+ }
+
+ float& physicalCollisionSphereRadius = myConstrains[vertexIndex].collisionSphereRadius;
+ if (physicalCollisionSphereRadius == PX_MAX_F32)
+ {
+ count[2]++;
+ uint32_t submeshIndex = 0, graphicalVertexIndex = 0;
+ if (hasCollisionSphereRadius && getClosestVertex(renderMeshAssetOrig, pMesh.pPosition[vertexIndex], submeshIndex, graphicalVertexIndex, COLLISION_SPHERE_RADIUS_NAME, ignoreUnusedVertices))
+ {
+ const VertexFormat& vf = renderMeshAssetCopy->getSubmesh(submeshIndex).getVertexBuffer().getFormat();
+ const uint32_t graphicalCollisionSphereRadiusIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID(COLLISION_SPHERE_RADIUS_NAME));
+ RenderDataFormat::Enum outFormat = vf.getBufferFormat(graphicalCollisionSphereRadiusIndex);
+ const float* graphicalCollisionSphereRadius = reinterpret_cast<const float*>(renderMeshAssetCopy->getSubmesh(submeshIndex).getVertexBuffer().getBuffer(graphicalCollisionSphereRadiusIndex));
+
+ PX_ASSERT(outFormat == RenderDataFormat::FLOAT1);
+ if (outFormat == RenderDataFormat::FLOAT1)
+ {
+ physicalCollisionSphereRadius = graphicalCollisionSphereRadius[graphicalVertexIndex];
+ }
+ }
+ else
+ {
+ physicalCollisionSphereRadius = 0.0f;
+ }
+ }
+ }
+
+ PxVec3& physicalNormal = pMesh.pNormal[vertexIndex];
+ if (physicalNormal.isZero() && !(mDeriveNormalsFromBones && pMesh.numBonesPerVertex > 0))
+ {
+ count[3]++;
+ uint32_t submeshIndex = 0, graphicalVertexIndex = 0;
+ if (getClosestVertex(renderMeshAssetOrig, pMesh.pPosition[vertexIndex], submeshIndex, graphicalVertexIndex, NULL, true))
+ {
+ RenderDataFormat::Enum normalFormat;
+ const VertexBuffer& vb = renderMeshAssetCopy->getSubmesh(submeshIndex).getVertexBuffer();
+ const VertexFormat& vf = vb.getFormat();
+ uint32_t bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::NORMAL));
+ const PxVec3* graphicalNormals = (const PxVec3*)vb.getBufferAndFormat(normalFormat, bufferIndex);
+ if (normalFormat != RenderDataFormat::FLOAT3)
+ {
+ // Phil - you might need to handle other normal formats
+ graphicalNormals = NULL;
+ }
+ if (graphicalNormals != NULL)
+ {
+ physicalNormal = graphicalNormals[graphicalVertexIndex];
+ }
+ }
+ else
+ {
+ physicalNormal = PxVec3(0.0f, 1.0f, 0.0f);
+ }
+ }
+
+ float* boneWeights = (pMesh.pBoneWeights != NULL) ? pMesh.pBoneWeights + (vertexIndex * pMesh.numBonesPerVertex) : NULL;
+ if (boneWeights != NULL && hasBoneWeights)
+ {
+ // is first weight already 0.0 ?
+ if (boneWeights[0] <= 0.0f)
+ {
+ count[4]++;
+ uint32_t submeshIndex = 0, graphicalVertexIndex = 0;
+ if (getClosestVertex(renderMeshAssetOrig, pMesh.pPosition[vertexIndex], submeshIndex, graphicalVertexIndex, NULL, ignoreUnusedVertices))
+ {
+ const VertexBuffer& vb = renderMeshAssetCopy->getSubmesh(submeshIndex).getVertexBuffer();
+ const VertexFormat& vf = vb.getFormat();
+ uint16_t* boneIndices = (pMesh.pBoneIndices != NULL) ? pMesh.pBoneIndices + (vertexIndex * pMesh.numBonesPerVertex) : NULL;
+ if (boneIndices != NULL)
+ {
+ for (uint32_t i = 0; i < pMesh.numBonesPerVertex; i++)
+ {
+ boneIndices[i] = 0;
+ boneWeights[i] = 0.0f;
+ }
+
+ RenderDataFormat::Enum boneIndexFormat;
+ uint32_t bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::BONE_INDEX));
+ const uint16_t* graphicalBoneIndices = reinterpret_cast<const uint16_t*>(vb.getBufferAndFormat(boneIndexFormat, bufferIndex));
+ if (boneIndexFormat != RenderDataFormat::USHORT1 && boneIndexFormat != RenderDataFormat::USHORT2 &&
+ boneIndexFormat != RenderDataFormat::USHORT3 && boneIndexFormat != RenderDataFormat::USHORT4)
+ {
+ // Phil - you might need to handle other normal formats
+ graphicalBoneIndices = NULL;
+ }
+
+ RenderDataFormat::Enum boneWeightFormat;
+ bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::BONE_WEIGHT));
+ const float* graphicalBoneWeights = (const float*)vb.getBufferAndFormat(boneWeightFormat, bufferIndex);
+ if (boneWeightFormat != RenderDataFormat::FLOAT1 && boneWeightFormat != RenderDataFormat::FLOAT2 &&
+ boneWeightFormat != RenderDataFormat::FLOAT3 && boneWeightFormat != RenderDataFormat::FLOAT4)
+ {
+ // Phil - you might need to handle other normal formats
+ graphicalBoneWeights = NULL;
+ }
+
+ const uint32_t graphicalNumBonesPerVertex = vertexSemanticFormatElementCount(RenderVertexSemantic::BONE_INDEX, boneIndexFormat);
+ for (uint32_t i = 0; i < graphicalNumBonesPerVertex; i++)
+ {
+ const float weight = graphicalBoneWeights[graphicalVertexIndex * graphicalNumBonesPerVertex + i];
+ const uint16_t index = graphicalBoneIndices[graphicalVertexIndex * graphicalNumBonesPerVertex + i];
+ tempMesh->addBoneToVertex(vertexIndex, index, weight);
+ }
+ }
+ }
+ }
+ tempMesh->normalizeBonesOfVertex(vertexIndex);
+ }
+ }
+
+ if (mDeriveNormalsFromBones && pMesh.numBonesPerVertex > 0)
+ {
+ for (uint32_t vertexIndex = 0; vertexIndex < numVertices; vertexIndex++)
+ {
+ const PxVec3& pos = pMesh.pPosition[vertexIndex];
+ PxVec3& normal = pMesh.pNormal[vertexIndex];
+ normal = PxVec3(0.0f);
+
+ for (uint32_t j = 0; j < pMesh.numBonesPerVertex; j++)
+ {
+ const float boneWeight = pMesh.pBoneWeights[vertexIndex * pMesh.numBonesPerVertex + j];
+
+ if (boneWeight == 0.0f)
+ {
+ continue;
+ }
+
+ const uint16_t externalBoneIndex = pMesh.pBoneIndices[vertexIndex * pMesh.numBonesPerVertex + j];
+
+ const int32_t internalBoneIndex = getBoneInternalIndex(externalBoneIndex);
+
+ const ClothingAssetParametersNS::BoneEntry_Type& bone = mBones[(uint32_t)internalBoneIndex];
+ PxVec3 closest = bone.bindPose.getPosition();
+ float minDist2 = (closest - pos).magnitudeSquared();
+
+ // find closest point on outgoing bones
+ for (uint32_t k = 0; k < mBones.size(); k++)
+ {
+ if (mBones[k].parentIndex != internalBoneIndex)
+ {
+ continue;
+ }
+
+ // closest point on segment
+ const PxVec3& a = bone.bindPose.getPosition();
+ const PxVec3& b = mBones[k].bindPose.getPosition();
+ if (a == b)
+ {
+ continue;
+ }
+
+ const PxVec3 d = b - a;
+ float s = (pos - a).dot(d) / d.magnitudeSquared();
+ s = PxClamp(s, 0.0f, 1.0f);
+
+ PxVec3 proj = a + d * s;
+ float dist2 = (proj - pos).magnitudeSquared();
+
+ if (dist2 < minDist2)
+ {
+ minDist2 = dist2;
+ closest = proj;
+ }
+ }
+
+ PxVec3 n = pos - closest;
+ n.normalize();
+ normal += n * boneWeight;
+ }
+ normal.normalize();
+ }
+
+ tempMesh->smoothNormals(3);
+ }
+
+
+ progress.completeSubtask();
+
+ tempMesh->release();
+ tempMesh = NULL;
+ }
+}
+
+
+
+bool ClothingAssetAuthoringImpl::hasTangents(const RenderMeshAssetIntl& rma)
+{
+ bool bHasTangents = false;
+ for (uint32_t submeshIndex = 0; submeshIndex < rma.getSubmeshCount(); submeshIndex++)
+ {
+ const VertexBuffer& vb = rma.getSubmesh(submeshIndex).getVertexBuffer();
+ const VertexFormat& vf = vb.getFormat();
+ uint32_t bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(apex::RenderVertexSemantic::TANGENT));
+ RenderDataFormat::Enum outFormat;
+ const void* tangents = vb.getBufferAndFormat(outFormat, bufferIndex);
+ if (tangents != NULL)
+ {
+ bHasTangents = true;
+ break;
+ }
+ }
+
+ return bHasTangents;
+}
+
+
+
+uint32_t ClothingAssetAuthoringImpl::getMaxNumGraphicalVertsActive(const ClothingGraphicalLodParameters& graphicalLod, uint32_t submeshIndex)
+{
+ uint32_t numVerts = 0;
+
+ const uint32_t numParts = (uint32_t)graphicalLod.physicsMeshPartitioning.arraySizes[0];
+ ClothingGraphicalLodParametersNS::PhysicsMeshPartitioning_Type* parts = graphicalLod.physicsMeshPartitioning.buf;
+
+ for (uint32_t i = 0; i < numParts; ++i)
+ {
+ if (parts[i].graphicalSubmesh == submeshIndex)
+ {
+ numVerts = PxMax(numVerts, parts[i].numSimulatedVertices);
+ }
+ }
+
+ return numVerts;
+}
+
+
+
+bool ClothingAssetAuthoringImpl::isMostlyImmediateSkinned(const RenderMeshAssetIntl& rma, const ClothingGraphicalLodParameters& graphicalLod)
+{
+ uint32_t immediateMapSize = (uint32_t)graphicalLod.immediateClothMap.arraySizes[0];
+ if (immediateMapSize == 0)
+ return false;
+
+ // figure out the number of immediate skinned verts.. more complicated than i thought.
+ uint32_t numImmediateSkinnedVerts = 0;
+ uint32_t totalSkinnedVerts = 0;
+ uint32_t* immediateMap = graphicalLod.immediateClothMap.buf;
+ uint32_t numSubmeshes = rma.getSubmeshCount();
+ uint32_t vertexOffset = 0;
+ for (uint32_t submeshIndex = 0; submeshIndex < numSubmeshes; ++submeshIndex)
+ {
+ const apex::RenderSubmesh& submesh = rma.getSubmesh(submeshIndex);
+ uint32_t numVertsToSkin = getMaxNumGraphicalVertsActive(graphicalLod, submeshIndex);
+ for (uint32_t vertexIndex = 0; vertexIndex < numVertsToSkin; ++vertexIndex)
+ {
+ uint32_t mapId = vertexOffset + vertexIndex;
+
+ PX_ASSERT(mapId < immediateMapSize);
+ const uint32_t mapEntry = immediateMap[mapId];
+ const uint32_t flags = mapEntry & ~ClothingConstants::ImmediateClothingReadMask;
+
+ // count the number of mesh-mesh skinned verts (the others are skinned to bones)
+ ++totalSkinnedVerts;
+ if ((flags & ClothingConstants::ImmediateClothingInSkinFlag) == 0)
+ {
+ ++numImmediateSkinnedVerts;
+ }
+
+ }
+ vertexOffset += submesh.getVertexCount(0);
+ }
+
+ return 2*numImmediateSkinnedVerts > totalSkinnedVerts;
+}
+
+
+
+bool ClothingAssetAuthoringImpl::conditionalMergeMapping(const RenderMeshAssetIntl& rma, ClothingGraphicalLodParameters& graphicalLod)
+{
+ bool merged = false;
+ // it's faster to do mesh-mesh skinning on all verts, instead of
+ // mesh-mesh skinning + immediateSkinning + tangent recompute
+ if (hasTangents(rma) && !isMostlyImmediateSkinned(rma, graphicalLod))
+ {
+ merged = mergeMapping(&graphicalLod);
+ }
+
+ return merged;
+}
+
+
+
+class SkinClothMapPredicate
+{
+public:
+ bool operator()(const SkinClothMapB& map1, const SkinClothMapB& map2) const
+ {
+ if (map1.submeshIndex < map2.submeshIndex)
+ {
+ return true;
+ }
+ else if (map1.submeshIndex > map2.submeshIndex)
+ {
+ return false;
+ }
+
+ return map1.faceIndex0 < map2.faceIndex0;
+ }
+};
+
+
+
+void ClothingAssetAuthoringImpl::sortSkinMapB(SkinClothMapB* skinClothMap, uint32_t skinClothMapSize, uint32_t* immediateClothMap, uint32_t immediateClothMapSize)
+{
+
+ sort<SkinClothMapB, SkinClothMapPredicate>(skinClothMap, skinClothMapSize, SkinClothMapPredicate());
+
+ if (immediateClothMap != NULL)
+ {
+ for (uint32_t j = 0; j < skinClothMapSize; j++)
+ {
+ const uint32_t vertexIndex = skinClothMap[j].vertexIndexPlusOffset;
+ if (vertexIndex < immediateClothMapSize)
+ {
+ PX_ASSERT((immediateClothMap[vertexIndex] & ClothingConstants::ImmediateClothingInSkinFlag) != 0);
+ immediateClothMap[vertexIndex] = j | ClothingConstants::ImmediateClothingInSkinFlag;
+ }
+ }
+ }
+}
+
+
+
+class F32Greater
+{
+public:
+ PX_INLINE bool operator()(float v1, float v2) const
+ {
+ return v1 > v2;
+ }
+};
+
+
+
+
+void ClothingAssetAuthoringImpl::setupPhysicalMesh(ClothingPhysicalMeshParameters& physicalMesh) const
+{
+ const uint32_t numIndicesPerElement = (physicalMesh.physicalMesh.isTetrahedralMesh) ? 4u : 3u;
+
+ // index buffer is sorted such that each triangle (or tetrahedra) has a higher or equal max distance than all tuples right of it.
+ for (uint32_t i = 0; i < physicalMesh.physicalMesh.numIndices; i += numIndicesPerElement)
+ {
+ float triangleMaxDistance = getMaxMaxDistance(physicalMesh.physicalMesh, i, numIndicesPerElement);
+ if (triangleMaxDistance == 0.0f // don't simulate triangles that may not move
+ || i == physicalMesh.physicalMesh.numIndices - numIndicesPerElement) // all vertices are painted, i.e. this is the last tuple.
+ {
+ const uint32_t maxIndex = (i == physicalMesh.physicalMesh.numIndices - numIndicesPerElement) ? i + numIndicesPerElement : i;
+ physicalMesh.physicalMesh.numSimulatedIndices = maxIndex;
+
+ // these values get set in reorderDeformableVertices
+ physicalMesh.physicalMesh.numSimulatedVertices = 0;
+ physicalMesh.physicalMesh.numMaxDistance0Vertices = 0;
+
+ if (triangleMaxDistance == 0.0f)
+ {
+ break;
+ }
+ }
+ }
+}
+
+
+
+void ClothingAssetAuthoringImpl::sortDeformableIndices(ClothingPhysicalMeshImpl& physicalMesh)
+{
+ if (physicalMesh.getNumVertices() == 0 || physicalMesh.getConstrainCoefficientBuffer() == NULL)
+ {
+ return;
+ }
+
+ uint32_t* deformableIndices = physicalMesh.getIndicesBuffer();
+ ClothingConstrainCoefficients* constrainCoeffs = physicalMesh.getConstrainCoefficientBuffer();
+
+ Array<uint32_t> deformableIndicesPermutation;
+ deformableIndicesPermutation.resize(physicalMesh.getNumIndices());
+
+ uint32_t numIndices = physicalMesh.isTetrahedralMesh() ? 4u : 3u;
+
+ for (uint32_t i = 0; i < physicalMesh.getNumIndices(); i++)
+ {
+ deformableIndicesPermutation[i] = i;
+ }
+
+ if (numIndices == 3)
+ {
+ TriangleGreater_3 triangleGreater(deformableIndices, constrainCoeffs);
+ nvidia::sort((uint32_t_3*)&deformableIndicesPermutation[0], physicalMesh.getNumIndices() / numIndices, triangleGreater);
+ }
+ else if (numIndices == 4)
+ {
+ TriangleGreater_4 triangleGreater(deformableIndices, constrainCoeffs);
+ nvidia::sort((uint32_t_4*)&deformableIndicesPermutation[0], physicalMesh.getNumIndices() / numIndices, triangleGreater);
+ }
+ else
+ {
+ PX_ALWAYS_ASSERT();
+ }
+
+
+ // inverse permutation
+ Array<int32_t> invPerm(physicalMesh.getNumIndices());
+ for (uint32_t i = 0; i < physicalMesh.getNumIndices(); i++)
+ {
+ PX_ASSERT(deformableIndicesPermutation[i] < physicalMesh.getNumIndices());
+ invPerm[deformableIndicesPermutation[i]] = (int32_t)i;
+ }
+
+
+ // apply permutation
+ ApexPermute<uint32_t>(deformableIndices, &deformableIndicesPermutation[0], physicalMesh.getNumIndices());
+
+ // update mappings into deformable index buffer
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ if (mPhysicalMeshes[mGraphicalLods[i]->physicalMeshId] == physicalMesh.getNvParameterized())
+ {
+ ClothingGraphicalMeshAssetWrapper meshAsset(reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[i]->renderMeshAssetPointer));
+ ClothingGraphicalLodParameters* graphicalLod = mGraphicalLods[i];
+
+ const uint32_t numGraphicalVertices = meshAsset.getNumTotalVertices();
+ if (graphicalLod->tetraMap.arraySizes[0] > 0)
+ {
+ for (uint32_t j = 0; j < numGraphicalVertices; j++)
+ {
+ graphicalLod->tetraMap.buf[j].tetraIndex0 = (uint32_t)invPerm[graphicalLod->tetraMap.buf[j].tetraIndex0];
+ }
+ }
+ const uint32_t skinClothMapBSize = (uint32_t)graphicalLod->skinClothMapB.arraySizes[0];
+ if (skinClothMapBSize > 0)
+ {
+ for (uint32_t j = 0; j < skinClothMapBSize; j++)
+ {
+ graphicalLod->skinClothMapB.buf[j].faceIndex0 = (uint32_t)invPerm[graphicalLod->skinClothMapB.buf[j].faceIndex0];
+ }
+
+ sortSkinMapB(graphicalLod->skinClothMapB.buf, (uint32_t)graphicalLod->skinClothMapB.arraySizes[0], graphicalLod->immediateClothMap.buf, numGraphicalVertices);
+ }
+ }
+ }
+
+ physicalMesh.updateMaxMaxDistance();
+}
+
+
+
+bool ClothingAssetAuthoringImpl::getGraphicalLodIndex(uint32_t lod, uint32_t& graphicalLodIndex) const
+{
+ graphicalLodIndex = UINT32_MAX;
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ if (mGraphicalLods[i]->lod == lod)
+ {
+ graphicalLodIndex = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+uint32_t ClothingAssetAuthoringImpl::addGraphicalLod(uint32_t lod)
+{
+ uint32_t lodIndex = (uint32_t) - 1;
+ if (getGraphicalLodIndex(lod, lodIndex))
+ {
+ return lodIndex;
+ }
+
+ ClothingGraphicalLodParameters* newLod = DYNAMIC_CAST(ClothingGraphicalLodParameters*)(GetInternalApexSDK()->getParameterizedTraits()->createNvParameterized(ClothingGraphicalLodParameters::staticClassName()));
+ newLod->lod = lod;
+ newLod->renderMeshAssetPointer = NULL;
+ PX_ASSERT(newLod->physicalMeshId == (uint32_t) - 1);
+
+ mGraphicalLods.pushBack(NULL);
+
+ // insertion sort
+ int32_t current = (int32_t)mGraphicalLods.size() - 1;
+ while (current > 0 && mGraphicalLods[(uint32_t)current - 1]->lod > newLod->lod)
+ {
+ mGraphicalLods[(uint32_t)current] = mGraphicalLods[(uint32_t)current - 1];
+ current--;
+ }
+ PX_ASSERT(current >= 0);
+ PX_ASSERT((uint32_t)current < mGraphicalLods.size());
+ mGraphicalLods[(uint32_t)current] = newLod;
+
+ return (uint32_t)current;
+}
+
+
+
+void ClothingAssetAuthoringImpl::clearCooked()
+{
+ ParamArray<ClothingAssetParametersNS::CookedEntry_Type> cookedEntries(mParams, "cookedData", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->cookedData));
+
+ if (cookedEntries.size() > 0)
+ {
+ if(cookedEntries[0].cookedData)
+ {
+ mPreviousCookedType = cookedEntries[0].cookedData->className();
+ }
+ }
+
+ cookedEntries.clear();
+}
+
+
+
+bool ClothingAssetAuthoringImpl::addGraphicalMesh(RenderMeshAssetAuthoring* renderMesh, uint32_t graphicalLodIndex)
+{
+ if (mGraphicalLods[graphicalLodIndex]->renderMeshAssetPointer != NULL)
+ {
+ reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[graphicalLodIndex]->renderMeshAssetPointer)->release();
+ mGraphicalLods[graphicalLodIndex]->renderMeshAssetPointer = NULL;
+ }
+ if (mGraphicalLods[graphicalLodIndex]->renderMeshAsset != NULL)
+ {
+ // PH: did the param object already get destroyed in the release call above?
+ mGraphicalLods[graphicalLodIndex]->renderMeshAsset->destroy();
+ mGraphicalLods[graphicalLodIndex]->renderMeshAsset = NULL;
+ }
+
+ if (renderMesh != NULL)
+ {
+ const uint32_t additionalSize = 7;
+ char buf[16];
+ int bufSize = 16;
+ char* rmaName = buf;
+ if (strlen(getName()) + additionalSize > 15)
+ {
+ bufSize = int32_t(strlen(getName()) + additionalSize + 2);
+ rmaName = (char*)PX_ALLOC((size_t)bufSize, PX_DEBUG_EXP("ClothingAssetAuthoring::addGraphicalMesh"));
+ }
+ nvidia::snprintf(rmaName, (size_t)bufSize, "%s_RMA%.3d", getName(), mGraphicalLods[graphicalLodIndex]->lod);
+
+ PX_ASSERT(mGraphicalLods[graphicalLodIndex]->renderMeshAssetPointer == NULL);
+ //mGraphicalMeshesRuntime[graphicalLodIndex] = DYNAMIC_CAST(RenderMeshAssetIntl*)(GetApexSDK()->createAsset(*renderMesh, rmaName));
+ NvParameterized::Interface* newAsset = GetInternalApexSDK()->getParameterizedTraits()->createNvParameterized(renderMesh->getNvParameterized()->className());
+ newAsset->copy(*renderMesh->getNvParameterized());
+
+ RenderMeshAssetIntl* rma = static_cast<RenderMeshAssetIntl*>(GetApexSDK()->createAsset(newAsset, rmaName));
+ PX_ASSERT(rma->getAssetNvParameterized()->equals(*renderMesh->getNvParameterized()));
+ if (rma->mergeBinormalsIntoTangents())
+ {
+ APEX_DEBUG_INFO("The ApexRenderMesh has Tangent and Binormal semantic (both FLOAT3), but clothing needs only Tangent (with FLOAT4). Converted internally");
+ }
+ mGraphicalLods[graphicalLodIndex]->renderMeshAssetPointer = rma;
+
+ PX_ASSERT(::strcmp(newAsset->className(), "RenderMeshAssetParameters") == 0);
+ mGraphicalLods[graphicalLodIndex]->renderMeshAsset = newAsset;
+
+ // make sure the isReferenced value is set!
+ NvParameterized::Handle handle(*newAsset);
+ newAsset->getParameterHandle("isReferenced", handle);
+ PX_ASSERT(handle.isValid());
+ if (handle.isValid())
+ {
+ bool val;
+ handle.getParamBool(val);
+ PX_ASSERT(!val);
+ handle.setParamBool(true);
+ }
+
+ if (rmaName != buf)
+ {
+ PX_FREE(rmaName);
+ rmaName = buf;
+ }
+
+ return true;
+ }
+ else
+ {
+ PX_ASSERT(mGraphicalLods[graphicalLodIndex] != NULL);
+
+ // store the pointer to the element that is removed
+ PX_ASSERT(mGraphicalLods[graphicalLodIndex]->renderMeshAssetPointer == NULL);
+ mGraphicalLods[graphicalLodIndex]->destroy();
+
+ for (uint32_t i = graphicalLodIndex; i < mGraphicalLods.size() - 1; i++)
+ {
+ mGraphicalLods[i] = mGraphicalLods[i + 1];
+ }
+
+ mGraphicalLods.back() = NULL; // set last element to NULL, otherwise the referred object gets destroyed in popBack
+ mGraphicalLods.popBack();
+
+ return false;
+ }
+}
+
+
+
+void ClothingAssetAuthoringImpl::initParams()
+{
+ PX_ASSERT(mParams != NULL);
+ if (mParams != NULL)
+ {
+ mParams->setSerializationCallback(this, NULL);
+ }
+
+ if (mParams->materialLibrary == NULL)
+ {
+ mOwnsMaterialLibrary = true;
+ mParams->materialLibrary = GetInternalApexSDK()->getParameterizedTraits()->createNvParameterized(ClothingMaterialLibraryParameters::staticClassName());
+ }
+}
+
+
+
+bool ClothingAssetAuthoringImpl::generateImmediateClothMap(const AbstractMeshDescription* targetMeshes, uint32_t numTargetMeshes,
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type& physicalMesh, uint32_t* masterFlags,
+ float epsilon, uint32_t& numNotFoundVertices, float normalResemblance, ParamArray<uint32_t>& result,
+ IProgressListener* progress) const
+{
+ // square because distance is also squared.
+ epsilon = epsilon * epsilon;
+
+ bool haveAllBuffers = true;
+
+ uint32_t numGraphicalVertices = 0;
+ for (uint32_t i = 0; i < numTargetMeshes; i++)
+ {
+ numGraphicalVertices += targetMeshes[i].numVertices;
+ bool hasAllBuffers = true;
+ hasAllBuffers &= targetMeshes[i].pPosition != NULL;
+ hasAllBuffers &= targetMeshes[i].pNormal != NULL;
+
+ haveAllBuffers &= hasAllBuffers;
+
+ if (!hasAllBuffers)
+ {
+ APEX_INTERNAL_ERROR("Render mesh asset does not have either position or normal for submesh %d!", i);
+ }
+ }
+
+ if (!haveAllBuffers)
+ {
+ numNotFoundVertices = 0;
+ return false;
+ }
+
+ result.resize(numGraphicalVertices);
+ for (uint32_t i = 0; i < numGraphicalVertices; i++)
+ {
+ result[i] = ClothingConstants::ImmediateClothingInvalidValue;
+ }
+
+ numNotFoundVertices = 0;
+ float notFoundError = 0.0f;
+ float maxDotError = 0.0f;
+ const float maxDotMinimum = PxClamp(PxCos(physx::shdfnd::degToRad(normalResemblance)), 0.0f, 1.0f);
+
+ const PxVec3* physicalPositions = physicalMesh.vertices.buf;
+ const PxVec3* physicalNormals = physicalMesh.skinningNormals.buf;
+ const uint32_t* physicsMasterFlags = masterFlags;
+ const uint32_t numPhysicsVertices = physicalMesh.numVertices;
+ PX_ASSERT(physicsMasterFlags != NULL);
+
+ uint32_t submeshVertexOffset = 0;
+ for (uint32_t submeshIndex = 0; submeshIndex < numTargetMeshes; submeshIndex++)
+ {
+ const PxVec3* positions = targetMeshes[submeshIndex].pPosition;
+ const PxVec3* normals = targetMeshes[submeshIndex].pNormal;
+ const uint32_t* slaveFlags = targetMeshes[submeshIndex].pVertexFlags;
+ const uint32_t numVertices = targetMeshes[submeshIndex].numVertices;
+
+ for (uint32_t index = 0; index < numVertices; index++)
+ {
+ if (progress != NULL && ((index & 0xff) == 0))
+ {
+ const int32_t percent = int32_t(100 * (index + submeshVertexOffset) / numGraphicalVertices);
+
+ progress->setProgress(percent);
+ }
+
+ float minDistanceSquared = FLT_MAX;
+ int32_t optimalMatch = -1;
+ float maxDot = 0.0f;
+ const uint32_t slave = slaveFlags != NULL ? slaveFlags[index] : 0xffffffff;
+
+ for (uint32_t vertexIndex = 0; vertexIndex < numPhysicsVertices && (minDistanceSquared > 0 || maxDot < maxDotMinimum); vertexIndex++)
+ {
+ const uint32_t master = physicsMasterFlags[vertexIndex];
+ if ((master & slave) == 0)
+ {
+ continue;
+ }
+
+ const float distSquared = (physicalPositions[vertexIndex] - positions[index]).magnitudeSquared();
+ const float dot = normals[index].dot(physicalNormals[vertexIndex]);
+ if (distSquared < minDistanceSquared || (distSquared == minDistanceSquared && PxAbs(dot) > PxAbs(maxDot)))
+ {
+ minDistanceSquared = distSquared;
+ optimalMatch = (int32_t)vertexIndex;
+ maxDot = dot;
+ }
+ }
+
+ if (optimalMatch == -1 || minDistanceSquared > epsilon || PxAbs(maxDot) < maxDotMinimum)
+ {
+ notFoundError += sqrtf(minDistanceSquared);
+ maxDotError += PxAbs(maxDot);
+
+ if (PxAbs(maxDot) < maxDotMinimum && minDistanceSquared <= epsilon)
+ {
+ result[index + submeshVertexOffset] = (uint32_t)optimalMatch;
+ result[index + submeshVertexOffset] |= ClothingConstants::ImmediateClothingBadNormal;
+ }
+ else
+ {
+ result[index + submeshVertexOffset] = ClothingConstants::ImmediateClothingInvalidValue;
+ }
+ numNotFoundVertices++;
+ }
+ else
+ {
+ result[index + submeshVertexOffset] = (uint32_t)optimalMatch;
+ if (maxDot < 0)
+ {
+ result[index + submeshVertexOffset] |= ClothingConstants::ImmediateClothingInvertNormal;
+ }
+ }
+ }
+
+ submeshVertexOffset += numVertices;
+ }
+
+ return result.size() == numGraphicalVertices;
+}
+
+
+
+bool ClothingAssetAuthoringImpl::generateSkinClothMap(const AbstractMeshDescription* targetMeshes, uint32_t numTargetMeshes,
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type& physicalMesh,
+ uint32_t* masterFlags, uint32_t* immediateMap, uint32_t numEmptyInImmediateMap,
+ ParamArray<SkinClothMap>& result, float& offsetAlongNormal,
+ bool integrateImmediateMap, IProgressListener* progress) const
+{
+ if (immediateMap == NULL || integrateImmediateMap)
+ {
+ uint32_t sum = 0;
+ for (uint32_t i = 0; i < numTargetMeshes; i++)
+ {
+ sum += targetMeshes[i].numVertices;
+ }
+ result.resize(sum);
+ }
+ else
+ {
+ result.resize(numEmptyInImmediateMap);
+ }
+
+ // figure out some details about the physical mesh
+ AbstractMeshDescription srcPM;
+ srcPM.numIndices = physicalMesh.numIndices;
+ srcPM.numVertices = physicalMesh.numVertices;
+ srcPM.pIndices = physicalMesh.indices.buf;
+ srcPM.pNormal = physicalMesh.skinningNormals.buf;
+ srcPM.pPosition = physicalMesh.vertices.buf;
+ srcPM.pVertexFlags = masterFlags;
+
+ srcPM.UpdateDerivedInformation(NULL);
+
+ // PH: Negating this leads to interesting effects, but also to some side effects...
+ offsetAlongNormal = DEFAULT_PM_OFFSET_ALONG_NORMAL_FACTOR * srcPM.avgEdgeLength;
+
+ const uint32_t physNumIndices = physicalMesh.numIndices;
+
+ // compute mapping
+ Array<TriangleWithNormals> triangles;
+ triangles.reserve(physNumIndices / 3);
+
+ // create a list of physics mesh triangles
+ float avgHalfDiagonal = 0.0f;
+ for (uint32_t i = 0; i < physNumIndices; i += 3)
+ {
+ TriangleWithNormals triangle;
+
+ // store vertex information in triangle
+ triangle.master = 0;
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ triangle.vertices[j] = srcPM.pPosition[srcPM.pIndices[i + j]];
+ triangle.normals[j] = srcPM.pNormal[srcPM.pIndices[i + j]];
+ triangle.master |= srcPM.pVertexFlags != NULL ? srcPM.pVertexFlags[srcPM.pIndices[i + j]] : 0xffffffff;
+ }
+ triangle.faceIndex0 = i;
+
+ triangle.init();
+ triangle.bounds.fattenFast(srcPM.avgEdgeLength);
+
+ PxVec3 boundsDiag = triangle.bounds.getExtents();
+ avgHalfDiagonal += boundsDiag.magnitude();
+ triangles.pushBack(triangle);
+ }
+ avgHalfDiagonal /= triangles.size();
+
+ // hash the triangles
+ ApexMeshHash hash;
+ hash.setGridSpacing(avgHalfDiagonal);
+ for (uint32_t i = 0; i < triangles.size(); i++)
+ {
+ hash.add(triangles[i].bounds, i);
+ }
+
+ // find the best triangle for each graphical vertex
+ SkinClothMap* mapEntry = result.begin();
+
+ Array<uint32_t> queryResult;
+
+ uint32_t targetOffset = 0;
+ for (uint32_t targetIndex = 0; targetIndex < numTargetMeshes; targetIndex++)
+ {
+ const uint32_t numVertices = targetMeshes[targetIndex].numVertices;
+ for (uint32_t vertexIndex = 0; vertexIndex < numVertices; vertexIndex++)
+ {
+ const uint32_t slave = targetMeshes[targetIndex].pVertexFlags != NULL ? targetMeshes[targetIndex].pVertexFlags[vertexIndex] : 0xffffffff;
+ PX_ASSERT(slave != 0);
+
+ const uint32_t index = vertexIndex + targetOffset;
+ const PxVec3 position = targetMeshes[targetIndex].pPosition[vertexIndex];
+ const PxVec3 normal = targetMeshes[targetIndex].pNormal[vertexIndex];
+ const PxVec3 normalRelative = position + (normal * offsetAlongNormal);
+ PxVec3 tangentRelative(0.0f);
+ if (targetMeshes[targetIndex].pTangent != NULL)
+ {
+ tangentRelative = position + (targetMeshes[targetIndex].pTangent[vertexIndex] * offsetAlongNormal);
+ }
+ else if (targetMeshes[targetIndex].pTangent4 != NULL)
+ {
+ const PxVec3 tangent(targetMeshes[targetIndex].pTangent4[vertexIndex].x,
+ targetMeshes[targetIndex].pTangent4[vertexIndex].y,
+ targetMeshes[targetIndex].pTangent4[vertexIndex].z);
+ tangentRelative = position + (tangent * offsetAlongNormal);
+ }
+
+ if (((immediateMap != NULL) && ((immediateMap[index] & ClothingConstants::ImmediateClothingBadNormal) != 0)) || integrateImmediateMap)
+ {
+
+ // read physics vertex
+ const uint32_t bestVertex = immediateMap[index] & ClothingConstants::ImmediateClothingReadMask;
+
+ // mark entry as invalid, because we put it into the skinClothMap
+ immediateMap[index] = ClothingConstants::ImmediateClothingInvalidValue;
+
+ float bestError = PX_MAX_F32;
+ int32_t bestIndex = -1;
+
+ for (uint32_t pIndex = 0; pIndex < physNumIndices; pIndex++)
+ {
+ if (srcPM.pIndices[pIndex] == bestVertex)
+ {
+ // this is a triangle that contains bestVertex (from the immediate map)
+
+ uint32_t faceIndex0 = pIndex - (pIndex % 3);
+ uint32_t triangleIndex = faceIndex0 / 3;
+ PX_ASSERT(triangleIndex < triangles.size());
+
+ TriangleWithNormals& triangle = triangles[triangleIndex];
+ PX_ASSERT(triangle.faceIndex0 == faceIndex0);
+
+ if (triangle.doNotUse)
+ {
+ continue;
+ }
+
+ if ((triangle.master & slave) == 0)
+ {
+ continue;
+ }
+
+ ModuleClothingHelpers::computeTriangleBarys(triangle, position, normalRelative, tangentRelative, offsetAlongNormal, int32_t(vertexIndex + targetOffset), false);
+
+ if (triangle.valid != 2)
+ {
+ continue;
+ }
+
+ float error = computeTriangleError(triangle, normal);
+
+ // use the best triangle that contains the vertex
+ if (error < bestError)
+ {
+ bestIndex = (int32_t)triangleIndex;
+ bestError = error;
+ }
+ }
+ }
+ //PX_ASSERT(bestIndex != -1);
+ if (bestIndex != -1)
+ {
+ immediateMap[index] = (uint32_t)(mapEntry - result.begin());
+ immediateMap[index] |= ClothingConstants::ImmediateClothingInSkinFlag;
+
+ mapEntry->vertexBary = triangles[(uint32_t)bestIndex].tempBaryVertex;
+ uint32_t faceIndex = triangles[(uint32_t)bestIndex].faceIndex0;
+ mapEntry->vertexIndex0 = srcPM.pIndices[faceIndex + 0];
+ mapEntry->vertexIndex1 = srcPM.pIndices[faceIndex + 1];
+ mapEntry->vertexIndex2 = srcPM.pIndices[faceIndex + 2];
+
+ mapEntry->normalBary = triangles[(uint32_t)bestIndex].tempBaryNormal;
+ mapEntry->tangentBary = triangles[(uint32_t)bestIndex].tempBaryTangent;
+ mapEntry->vertexIndexPlusOffset = index;
+ mapEntry++;
+
+ continue;
+ }
+ //PX_ASSERT(0 && "generateSkinClothMapC: We should never end up here");
+ }
+
+ if (immediateMap != NULL && immediateMap[index] != ClothingConstants::ImmediateClothingInvalidValue)
+ {
+ continue;
+ }
+
+ if (progress != NULL && (index & 0xf) == 0)
+ {
+ const uint32_t location = (uint32_t)(mapEntry - result.begin());
+ const int32_t percent = int32_t(100 * location / result.size());
+
+ progress->setProgress(percent);
+ }
+
+ int32_t bestTriangleNr = -1;
+ float bestTriangleError = PX_MAX_F32;
+
+ // query for physical triangles around the graphics vertex
+ hash.query(position, queryResult);
+ for (uint32_t q = 0; q < queryResult.size(); q++)
+ {
+ const uint32_t triangleNr = queryResult[q];
+ TriangleWithNormals& triangle = triangles[triangleNr];
+
+ if (triangle.doNotUse)
+ {
+ continue;
+ }
+
+ if ((triangle.master & slave) == 0)
+ {
+ continue;
+ }
+
+ if (!triangle.bounds.contains(position))
+ {
+ continue;
+ }
+
+ ModuleClothingHelpers::computeTriangleBarys(triangle, position, normalRelative, tangentRelative, offsetAlongNormal, int32_t(vertexIndex + targetOffset), false);
+
+ if (triangle.valid != 2)
+ {
+ continue;
+ }
+
+ const float error = computeTriangleError(triangle, normal);
+
+ if (error < bestTriangleError)
+ {
+ bestTriangleNr = (int32_t)triangleNr;
+ bestTriangleError = error;
+ }
+ }
+
+ if (bestTriangleNr < 0)
+ {
+ // nothing was found nearby, search in all triangles
+ bestTriangleError = PX_MAX_F32;
+ for (uint32_t j = 0; j < triangles.size() && bestTriangleError > 0.0f; j++)
+ {
+ TriangleWithNormals& triangle = triangles[j];
+
+ if (triangle.doNotUse)
+ {
+ continue;
+ }
+
+ if ((triangle.master & slave) == 0)
+ {
+ continue;
+ }
+
+ triangle.timestamp = -1;
+ ModuleClothingHelpers::computeTriangleBarys(triangle, position, normalRelative, tangentRelative, offsetAlongNormal, int32_t(vertexIndex + targetOffset), false);
+
+ if (triangle.valid == 0)
+ {
+ continue;
+ }
+
+ float error = computeTriangleError(triangle, normal);
+
+ // increase the error a lot, but still better than nothing
+ if (triangle.valid != 2)
+ {
+ error += 100.0f;
+ }
+
+ if (error < bestTriangleError)
+ {
+ bestTriangleError = error;
+ bestTriangleNr = (int32_t)j;
+ }
+ }
+ }
+
+ if (bestTriangleNr >= 0)
+ {
+ const TriangleWithNormals& bestTriangle = triangles[(uint32_t)bestTriangleNr];
+
+ if (immediateMap != NULL)
+ {
+ PX_ASSERT(immediateMap[index] == ClothingConstants::ImmediateClothingInvalidValue);
+ immediateMap[index] = (uint32_t)(mapEntry - result.begin());
+ immediateMap[index] |= ClothingConstants::ImmediateClothingInSkinFlag;
+ }
+
+ PX_ASSERT(bestTriangle.faceIndex0 % 3 == 0);
+ //mapEntry->tetraIndex = bestTriangle.tetraIndex;
+ //mapEntry->submeshIndex = targetIndex;
+
+ mapEntry->vertexBary = bestTriangle.tempBaryVertex;
+ uint32_t faceIndex = bestTriangle.faceIndex0;
+ mapEntry->vertexIndex0 = srcPM.pIndices[faceIndex + 0];
+ mapEntry->vertexIndex1 = srcPM.pIndices[faceIndex + 1];
+ mapEntry->vertexIndex2 = srcPM.pIndices[faceIndex + 2];
+ mapEntry->normalBary = bestTriangle.tempBaryNormal;
+ mapEntry->tangentBary = bestTriangle.tempBaryTangent;
+ mapEntry->vertexIndexPlusOffset = index;
+ mapEntry++;
+ }
+ else if (immediateMap != NULL)
+ {
+ PX_ASSERT(immediateMap[index] == ClothingConstants::ImmediateClothingInvalidValue);
+ }
+ }
+
+ targetOffset += numVertices;
+ }
+
+
+ uint32_t sizeused = (uint32_t)(mapEntry - result.begin());
+ if (sizeused < result.size())
+ {
+ APEX_DEBUG_WARNING("%d vertices could not be mapped, they will be static!", result.size() - sizeused);
+ }
+ result.resize(sizeused);
+
+ return true;
+}
+
+template <typename T>
+class SkinClothMapPredicate2
+{
+public:
+ bool operator()(const T& map1, const T& map2) const
+ {
+ return map1.vertexIndexPlusOffset < map2.vertexIndexPlusOffset;
+ }
+};
+
+
+void ClothingAssetAuthoringImpl::removeMaxDistance0Mapping(ClothingGraphicalLodParameters& graphicalLod, RenderMeshAssetIntl* renderMeshAsset) const
+{
+ ParamArray<SkinClothMap> skinClothMap(&graphicalLod, "skinClothMap",
+ reinterpret_cast<ParamDynamicArrayStruct*>(&graphicalLod.skinClothMap));
+
+ ParamArray<uint32_t> immediateClothMap(&graphicalLod, "immediateClothMap",
+ reinterpret_cast<ParamDynamicArrayStruct*>(&graphicalLod.immediateClothMap));
+
+ // temp array to keep the simulated verts, as we want to discard the fixed verts
+ Array<SkinClothMap> skinClothMapNew;
+ skinClothMapNew.reserve(skinClothMap.size());
+
+ uint32_t offset = 0;
+ for (uint32_t s = 0; s < renderMeshAsset->getSubmeshCount(); s++)
+ {
+ // get submesh data
+ const VertexBuffer& vb = renderMeshAsset->getSubmesh(s).getVertexBuffer();
+ const VertexFormat& vf = vb.getFormat();
+
+ const uint32_t graphicalMaxDistanceIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID(MAX_DISTANCE_NAME));
+ RenderDataFormat::Enum outFormat = vf.getBufferFormat(graphicalMaxDistanceIndex);
+ const float* graphicalMaxDistance = outFormat == RenderDataFormat::UNSPECIFIED ? NULL :
+ reinterpret_cast<const float*>(vb.getBuffer(graphicalMaxDistanceIndex));
+
+ const uint32_t numVertices = renderMeshAsset->getSubmesh(s).getVertexCount(0);
+ if (graphicalMaxDistance == NULL)
+ {
+ PX_ALWAYS_ASSERT();
+ offset += numVertices;
+ continue;
+ }
+
+ PX_ASSERT(outFormat == RenderDataFormat::FLOAT1);
+
+ for (uint32_t vertexIndex = 0; vertexIndex < numVertices; vertexIndex++)
+ {
+ const uint32_t index = vertexIndex + offset;
+
+ uint32_t skinClothMapIndex = (uint32_t)-1;
+ if (immediateClothMap.size() > index && immediateClothMap[index] & ClothingConstants::ImmediateClothingInSkinFlag)
+ {
+ // read the index out of the skinClothMap
+ skinClothMapIndex = immediateClothMap[index] & ClothingConstants::ImmediateClothingReadMask;
+ immediateClothMap[index] = skinClothMapNew.size() | ClothingConstants::ImmediateClothingInSkinFlag;
+ }
+ else if (skinClothMap.size() > index && index == skinClothMap[index].vertexIndexPlusOffset)
+ {
+ // if there's no immediateMap, all verts should be in the skinClothMap
+ skinClothMapIndex = index;
+ }
+ else
+ {
+ // we only get here, if there are some verts without mapping -> bad!
+ for (uint32_t i = 0; i < skinClothMap.size(); i++)
+ {
+ if (index == skinClothMap[i].vertexIndexPlusOffset)
+ {
+ skinClothMapIndex = i;
+ }
+ }
+ }
+
+ if (skinClothMapIndex != (uint32_t)-1)
+ {
+ if (graphicalMaxDistance[vertexIndex] != mInvalidConstrainCoefficients.maxDistance
+ && graphicalMaxDistance[vertexIndex] == 0.0f)
+ {
+ // non-simulated verts are removed from the skinClothMap (not added to skinClothMapNew)
+ if (immediateClothMap.size() > index)
+ {
+ immediateClothMap[index] = ClothingConstants::ImmediateClothingInvalidValue;
+ }
+ }
+ else
+ {
+ // keep the entry for simulated verts
+ skinClothMapNew.pushBack(skinClothMap[skinClothMapIndex]);
+ }
+ }
+ }
+
+ offset += numVertices;
+ }
+
+ // store reduced skinClothMap
+ skinClothMap.resize(skinClothMapNew.size());
+ for (uint32_t i = 0; i < skinClothMapNew.size(); ++i)
+ {
+ skinClothMap[i] = skinClothMapNew[i];
+ }
+}
+
+bool ClothingAssetAuthoringImpl::generateTetraMap(const AbstractMeshDescription* targetMeshes, uint32_t numTargetMeshes,
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type& physicalMesh, uint32_t* /*masterFlags*/,
+ ParamArray<ClothingGraphicalLodParametersNS::TetraLink_Type>& result, IProgressListener* progress) const
+{
+ uint32_t numGraphicalVertices = 0;
+
+
+ bool haveAllBuffers = true;
+
+ for (uint32_t submeshIndex = 0; submeshIndex < numTargetMeshes; submeshIndex++)
+ {
+ numGraphicalVertices += targetMeshes[submeshIndex].numVertices;
+
+ bool hasAllBuffers = true;
+ hasAllBuffers &= targetMeshes[submeshIndex].pPosition != NULL;
+ hasAllBuffers &= targetMeshes[submeshIndex].pNormal != NULL;
+
+ haveAllBuffers &= hasAllBuffers;
+ if (!hasAllBuffers)
+ {
+ APEX_INTERNAL_ERROR("Render mesh asset does not have either position or normal for submesh %d!", submeshIndex);
+ }
+ }
+
+ if (!haveAllBuffers)
+ {
+ return false;
+ }
+
+ result.resize(numGraphicalVertices);
+ memset(result.begin(), 0, sizeof(ClothingGraphicalLodParametersNS::TetraLink_Type) * numGraphicalVertices);
+
+ uint32_t submeshVertexOffset = 0;
+
+ const uint32_t* physicalIndices = physicalMesh.indices.buf;
+ const PxVec3* physicalPositions = physicalMesh.vertices.buf;
+
+ for (uint32_t targetIndex = 0; targetIndex < numTargetMeshes; targetIndex++)
+ {
+ const uint32_t numVertices = targetMeshes[targetIndex].numVertices;
+
+ const PxVec3* positions = targetMeshes[targetIndex].pPosition;
+ const PxVec3* normals = targetMeshes[targetIndex].pNormal;
+
+ for (uint32_t vertexIndex = 0; vertexIndex < numVertices; vertexIndex++)
+ {
+ const uint32_t index = vertexIndex + submeshVertexOffset;
+ if (progress != NULL && (index & 0x3f) == 0)
+ {
+ const int32_t percent = int32_t(100 * index / numGraphicalVertices);
+ progress->setProgress(percent);
+ }
+
+ const PxVec3 position = positions[vertexIndex];
+
+ float bestWorstBary = FLT_MAX;
+ int32_t bestTet = -1;
+ PxVec3 bestBary(0.0f, 0.0f, 0.0f);
+ for (uint32_t j = 0; j < physicalMesh.numIndices; j += 4)
+ {
+ PxVec3 p[4];
+ for (uint32_t k = 0; k < 4; k++)
+ {
+ p[k] = physicalPositions[physicalIndices[j + k]];
+ }
+
+ PxVec3 bary;
+ generateBarycentricCoordinatesTet(p[0], p[1], p[2], p[3], position, bary);
+ float baryU = 1 - bary.x - bary.y - bary.z;
+ float worstBary = 0.0f;
+ worstBary = PxMax(worstBary, -bary.x);
+ worstBary = PxMax(worstBary, -bary.y);
+ worstBary = PxMax(worstBary, -bary.z);
+ worstBary = PxMax(worstBary, -baryU);
+ worstBary = PxMax(worstBary, bary.x - 1);
+ worstBary = PxMax(worstBary, bary.y - 1);
+ worstBary = PxMax(worstBary, bary.z - 1);
+ worstBary = PxMax(worstBary, baryU - 1);
+ //PX_ASSERT(worstBary + bestWorstBary > 0 && "they must not be 0 both!!!");
+ if (worstBary < bestWorstBary)
+ {
+ bestWorstBary = worstBary;
+ bestTet = (int32_t)j;
+ bestBary = bary;
+ }
+ }
+
+ PX_ASSERT(result[index].tetraIndex0 == 0);
+
+ result[index].vertexBary = bestBary;
+ result[index].tetraIndex0 = (uint32_t)bestTet;
+
+ // compute barycentric coordinates of normal
+ PxVec3 normal(1.0f, 0.0f, 0.0f);
+ if (normals != NULL)
+ {
+ normal = normals[vertexIndex];
+ normal.normalize();
+ }
+ const PxVec3& pa = physicalPositions[physicalIndices[bestTet + 0]];
+ const PxVec3& pb = physicalPositions[physicalIndices[bestTet + 1]];
+ const PxVec3& pc = physicalPositions[physicalIndices[bestTet + 2]];
+ const PxVec3& pd = physicalPositions[physicalIndices[bestTet + 3]];
+ PxBounds3 bounds;
+ bounds.setEmpty();
+ bounds.include(pa);
+ bounds.include(pb);
+ bounds.include(pc);
+ bounds.include(pd);
+ // we use a second point above pos, along the normal.
+ // The offset must be small but arbitrary since we normalize the resulting normal during skinning
+ const float offset = (bounds.minimum - bounds.maximum).magnitude() * 0.01f;
+ generateBarycentricCoordinatesTet(pa, pb, pc, pd, position + normal * offset, result[index].normalBary);
+
+ }
+
+
+ submeshVertexOffset += numVertices;
+ }
+
+ return true;
+}
+
+
+
+float ClothingAssetAuthoringImpl::computeBaryError(float baryX, float baryY) const
+{
+#if 0
+ const float triangleSize = 1.0f;
+ const float baryZ = 1.0f - baryX - baryY;
+
+ const float errorX = (baryX - (1.0f / 3.0f)) * triangleSize;
+ const float errorY = (baryY - (1.0f / 3.0f)) * triangleSize;
+ const float errorZ = (baryZ - (1.0f / 3.0f)) * triangleSize;
+
+ return (errorX * errorX) + (errorY * errorY) + (errorZ * errorZ);
+#elif 0
+ float dist = 0.0f;
+ if (-baryX > dist)
+ {
+ dist = -baryX;
+ }
+ if (-baryY > dist)
+ {
+ dist = -baryY;
+ }
+ float sum = baryX + baryY - 1.0f;
+ if (sum > dist)
+ {
+ dist = sum;
+ }
+ return dist * dist;
+#else
+ const float baryZ = 1.0f - baryX - baryY;
+
+ const float errorX = PxMax(PxAbs(baryX - 0.5f) - 0.5f, 0.0f);
+ const float errorY = PxMax(PxAbs(baryY - 0.5f) - 0.5f, 0.0f);
+ const float errorZ = PxMax(PxAbs(baryZ - 0.5f) - 0.5f, 0.0f);
+
+ return (errorX * errorX) + (errorY * errorY) + (errorZ * errorZ);
+#endif
+}
+
+
+
+float ClothingAssetAuthoringImpl::computeTriangleError(const TriangleWithNormals& triangle, const PxVec3& normal) const
+{
+ PxVec3 faceNormal = (triangle.vertices[1] - triangle.vertices[0]).cross(triangle.vertices[2] - triangle.vertices[0]);
+ faceNormal.normalize();
+
+ const float avgTriangleEdgeLength = ((triangle.vertices[0] - triangle.vertices[1]).magnitude() +
+ (triangle.vertices[0] - triangle.vertices[2]).magnitude() +
+ (triangle.vertices[1] - triangle.vertices[2]).magnitude()) / 3.0f;
+
+ float error = computeBaryError(triangle.tempBaryVertex.x, triangle.tempBaryVertex.y);
+
+ PX_ASSERT(PxAbs(1 - normal.magnitude()) < 0.001f); // make sure it's normalized.
+
+ //const float normalWeight = faceNormal.cross(normal).magnitude(); // 0 for co-linear, 1 for perpendicular
+ const float normalWeight = 0.5f * (1.0f - faceNormal.dot(normal));
+
+ error += PxClamp(normalWeight, 0.0f, 1.0f) * computeBaryError(triangle.tempBaryNormal.x, triangle.tempBaryNormal.y);
+
+ const float heightValue = triangle.tempBaryVertex.z / avgTriangleEdgeLength;
+ const float heightWeight = 0.1f + 2.5f * computeBaryError(triangle.tempBaryVertex.x, triangle.tempBaryVertex.y);
+ const float heightError = heightWeight * PxAbs(heightValue);
+ error += heightError;
+
+ return error;
+}
+
+}
+} // namespace nvidia
+
+#endif // WITHOUT_APEX_AUTHORING
+
diff --git a/APEX_1.4/module/clothing/src/ClothingAssetData.cpp b/APEX_1.4/module/clothing/src/ClothingAssetData.cpp
new file mode 100644
index 00000000..795e0f04
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/ClothingAssetData.cpp
@@ -0,0 +1,874 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+#include "ApexSimdMath.h"
+#include "PxPreprocessor.h"
+#include "RenderDataFormat.h"
+#include "ClothingAssetData.h"
+#include "PsIntrinsics.h"
+#include "PsVecMath.h"
+#include "PxMat44.h"
+
+#define NX_PARAMETERIZED_ONLY_LAYOUTS
+#include "ClothingGraphicalLodParameters.h"
+
+#pragma warning(disable : 4101 4127) // unreferenced local variable and conditional expression is constant
+
+
+namespace nvidia
+{
+using namespace physx::shdfnd;
+//using namespace physx::shdfnd::aos;
+
+namespace clothing
+{
+
+ClothingAssetSubMesh::ClothingAssetSubMesh() :
+ mPositions(NULL),
+ mNormals(NULL),
+ mTangents(NULL),
+ mBoneWeights(NULL),
+ mBoneIndices(NULL),
+ mIndices(NULL),
+ mUvs(NULL),
+
+ mPositionOutFormat(RenderDataFormat::UNSPECIFIED),
+ mNormalOutFormat(RenderDataFormat::UNSPECIFIED),
+ mTangentOutFormat(RenderDataFormat::UNSPECIFIED),
+ mBoneWeightOutFormat(RenderDataFormat::UNSPECIFIED),
+ mUvFormat(RenderDataFormat::UNSPECIFIED),
+
+ mVertexCount(0),
+ mIndicesCount(0),
+ mUvCount(0),
+ mNumBonesPerVertex(0),
+
+ mCurrentMaxVertexSimulation(0),
+ mCurrentMaxVertexAdditionalSimulation(0),
+ mCurrentMaxIndexSimulation(0)
+{
+}
+
+
+
+ClothingMeshAssetData::ClothingMeshAssetData() :
+ mImmediateClothMap(NULL),
+ mSkinClothMap(NULL),
+ mSkinClothMapB(NULL),
+ mTetraMap(NULL),
+
+ mImmediateClothMapCount(0),
+ mSkinClothMapCount(0),
+ mSkinClothMapBCount(0),
+ mTetraMapCount(0),
+
+ mSubmeshOffset(0),
+ mSubMeshCount(0),
+
+ mPhysicalMeshId(0),
+
+ mSkinClothMapThickness(0.0f),
+ mSkinClothMapOffset(0.0f),
+
+ mBounds(PxBounds3::empty()),
+
+ bActive(false)
+{
+
+}
+
+
+
+ClothingPhysicalMeshData::ClothingPhysicalMeshData() :
+ mVertices(NULL),
+ mVertexCount(0),
+ mSimulatedVertexCount(0),
+ mMaxDistance0VerticesCount(0),
+ mNormals(NULL),
+ mSkinningNormals(NULL),
+ mBoneIndices(NULL),
+ mBoneWeights(NULL),
+ mOptimizationData(NULL),
+ mIndices(NULL),
+
+ mSkinningNormalsCount(0),
+ mBoneWeightsCount(0),
+ mOptimizationDataCount(0),
+ mIndicesCount(0),
+ mSimulatedIndicesCount(0),
+
+ mNumBonesPerVertex(0)
+{
+
+}
+
+
+
+ClothingAssetData::ClothingAssetData() :
+ mData(NULL),
+ mCompressedNumBonesPerVertex(NULL),
+ mCompressedTangentW(NULL),
+ mExt2IntMorphMapping(NULL),
+ mCompressedNumBonesPerVertexCount(0),
+ mCompressedTangentWCount(0),
+ mExt2IntMorphMappingCount(0),
+
+ mAssetSize(0),
+ mGraphicalLodsCount(0),
+ mPhysicalMeshesCount(0),
+ mPhysicalMeshOffset(0),
+ mBoneCount(0),
+ mRootBoneIndex(0)
+{
+
+}
+
+
+
+
+ClothingAssetData::~ClothingAssetData()
+{
+ PX_FREE(mData);
+ mData = NULL;
+}
+
+
+
+void ClothingAssetData::skinToBones(AbstractMeshDescription& destMesh, uint32_t submeshIndex, uint32_t graphicalMeshIndex, uint32_t startVertex,
+ PxMat44* compositeMatrices, PxVec3* morphDisplacements)
+{
+ // This is no nice code, but it allows to have 8 different code paths through skinToBones that have all the if's figured out at compile time (hopefully)
+ PX_ASSERT(destMesh.pTangent == NULL);
+ PX_ASSERT(destMesh.pBitangent == NULL);
+
+ if (destMesh.pNormal != NULL)
+ {
+ if (mBoneCount != 0)
+ {
+ if (morphDisplacements != NULL)
+ {
+ if (destMesh.pTangent4 != NULL)
+ {
+ skinToBonesInternal<true, true, true, true>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ else
+ {
+ skinToBonesInternal<true, true, true, false>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ }
+ else
+ {
+ if (destMesh.pTangent4 != NULL)
+ {
+ skinToBonesInternal<true, true, false, true>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ else
+ {
+ skinToBonesInternal<true, true, false, false>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ }
+ }
+ else
+ {
+ if (morphDisplacements != NULL)
+ {
+ if (destMesh.pTangent4 != NULL)
+ {
+ skinToBonesInternal<true, false, true, true>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ else
+ {
+ skinToBonesInternal<true, false, true, false>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ }
+ else
+ {
+ if (destMesh.pTangent4 != NULL)
+ {
+ skinToBonesInternal<true, false, false, true>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ else
+ {
+ skinToBonesInternal<true, false, false, false>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (mBoneCount != 0)
+ {
+ if (morphDisplacements != NULL)
+ {
+ if (destMesh.pTangent4 != NULL)
+ {
+ skinToBonesInternal<false, true, true, true>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ else
+ {
+ skinToBonesInternal<false, true, true, false>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ }
+ else
+ {
+ if (destMesh.pTangent4 != NULL)
+ {
+ skinToBonesInternal<false, true, false, true>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ else
+ {
+ skinToBonesInternal<false, true, false, false>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ }
+ }
+ else
+ {
+ if (morphDisplacements != NULL)
+ {
+ if (destMesh.pTangent4 != NULL)
+ {
+ skinToBonesInternal<false, false, true, true>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ else
+ {
+ skinToBonesInternal<false, false, true, false>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ }
+ else
+ {
+ if (destMesh.pTangent4 != NULL)
+ {
+ skinToBonesInternal<false, false, false, true>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ else
+ {
+ skinToBonesInternal<false, false, false, false>(destMesh, submeshIndex, graphicalMeshIndex, startVertex, compositeMatrices, morphDisplacements);
+ }
+ }
+ }
+ }
+}
+
+
+template<bool withNormals, bool withBones, bool withMorph, bool withTangents>
+void ClothingAssetData::skinToBonesInternal(AbstractMeshDescription& destMesh, uint32_t submeshIndex, uint32_t graphicalMeshIndex,
+ uint32_t startVertex, PxMat44* compositeMatrices, PxVec3* morphDisplacements)
+{
+ PX_ASSERT(withNormals == (destMesh.pNormal != NULL));
+ PX_ASSERT(withMorph == (morphDisplacements != NULL));
+
+ PX_ASSERT(withTangents == (destMesh.pTangent4 != NULL));
+ PX_ASSERT(destMesh.pTangent == NULL);
+ PX_ASSERT(destMesh.pBitangent == NULL);
+
+ // so we need to start further behind, but to make vec3* still aligned it must be a multiple of 4, and to make
+ // compressedNumBones aligned, it needs to be a multiple of 16 (hence 16)
+ // The start offset is reduced by up to 16, and instead of skipping the first [0, 16) vertices and adding additional logic
+ // they just get computed as well, assuming much less overhead than an additional if in the innermost loop
+ // Note: This only works if the mesh-mesh skinning is executed afterwards!
+ const uint32_t startVertex16 = startVertex - (startVertex % 16);
+
+ PX_ASSERT(((size_t)(compositeMatrices) & 0xf) == 0); // make sure the pointer is 16 byte aligned!!
+
+ ClothingMeshAssetData* meshAsset = GetLod(graphicalMeshIndex);
+ PX_ASSERT(submeshIndex < meshAsset->mSubMeshCount);
+ ClothingAssetSubMesh* pSubmesh = GetSubmesh(meshAsset, submeshIndex);
+ const uint32_t numVertices = pSubmesh->mVertexCount - startVertex16;
+ if(numVertices == 0)
+ {
+ return;
+ }
+
+ // use the per-asset setting
+ const uint32_t startVertexDiv16 = startVertex16 / 16;
+ uint32_t mapSize = 0;
+ const uint32_t* compressedNumBonesPerVertexEa = getCompressedNumBonesPerVertex(graphicalMeshIndex, submeshIndex, mapSize);
+ PX_ASSERT((mapSize - startVertexDiv16) * 16 >= numVertices);
+
+ const uint32_t* compressedNumBonesPerVertex = (const uint32_t*)((uint32_t*)compressedNumBonesPerVertexEa + startVertexDiv16);
+
+ const PxVec3* PX_RESTRICT positionsEa = pSubmesh->mPositions + startVertex16;
+ PX_ASSERT(pSubmesh->mPositionOutFormat == RenderDataFormat::FLOAT3);
+ const PxVec3* PX_RESTRICT normalsEa = pSubmesh->mNormals + startVertex16;
+ PX_ASSERT(pSubmesh->mNormalOutFormat == RenderDataFormat::FLOAT3);
+
+ const PxVec4* PX_RESTRICT tangentsEa = pSubmesh->mTangents + (pSubmesh->mTangents != NULL ? startVertex16 : 0);
+ PX_ASSERT(tangentsEa == NULL || pSubmesh->mTangentOutFormat == RenderDataFormat::FLOAT4);
+
+ //These are effective addresses (ea)
+ PxVec3* PX_RESTRICT destPositionsEa = destMesh.pPosition + startVertex16;
+ PxVec3* PX_RESTRICT destNormalsEa = destMesh.pNormal + startVertex16;
+ PxVec4* PX_RESTRICT destTangentsEa = (destMesh.pTangent4 != NULL) ? destMesh.pTangent4 + startVertex16 : NULL;
+
+ uint32_t* morphReorderingEa = morphDisplacements != NULL ? getMorphMapping(graphicalMeshIndex) : NULL;
+ if (morphReorderingEa != NULL)
+ {
+ morphReorderingEa += startVertex16;
+ }
+ else if (withMorph)
+ {
+ // actually we don't have a morph map, so let's take one step back
+ skinToBonesInternal<withNormals, withBones, false, withTangents>(destMesh, submeshIndex, graphicalMeshIndex,
+ startVertex, compositeMatrices, NULL);
+ return;
+ }
+ PX_ASSERT((morphDisplacements != NULL) == (morphReorderingEa != NULL));
+
+ const uint16_t* PX_RESTRICT boneIndicesEa = NULL;
+ const float* PX_RESTRICT boneWeightsEa = NULL;
+
+ const uint32_t maxNumBonesPerVertex = pSubmesh->mNumBonesPerVertex;
+ if (withBones)
+ {
+ boneIndicesEa = (const uint16_t*)pSubmesh->mBoneIndices + (startVertex16 * maxNumBonesPerVertex);
+ boneWeightsEa = (const float*)pSubmesh->mBoneWeights + (startVertex16 * maxNumBonesPerVertex);
+ }
+
+
+ //bones per vertex is LS address!!!!
+ const uint32_t* PX_RESTRICT bonesPerVertex = compressedNumBonesPerVertex;
+
+ //OK. Need to split this up into an even larger subset of work!!!! Perhaps sets of 1024 vertices/normals/bones....
+
+ const uint32_t WorkSize = 160;
+
+ const uint32_t countWork = (numVertices + (WorkSize - 1)) / WorkSize;
+
+ for (uint32_t a = 0; a < countWork; ++a)
+ {
+ const uint32_t workCount = PxMin(numVertices - (a * WorkSize), WorkSize);
+
+ const PxVec3* PX_RESTRICT positions = (const PxVec3 * PX_RESTRICT)(void*)positionsEa;
+ const PxVec3* PX_RESTRICT normals = NULL;
+ const float* PX_RESTRICT tangents4 = NULL;
+ const uint16_t* PX_RESTRICT boneIndices = NULL;
+ const float* PX_RESTRICT boneWeights = NULL;
+
+ PxVec3* PX_RESTRICT destPositions = (PxVec3 * PX_RESTRICT)(void*)destPositionsEa;
+ PxVec3* PX_RESTRICT destNormals = NULL;
+ float* PX_RESTRICT destTangents4 = NULL;
+
+ uint32_t* morphReordering = NULL;
+ if (withMorph)
+ {
+ morphReordering = (uint32_t*)morphReorderingEa;
+ morphReorderingEa += workCount;
+ }
+
+ if (withBones)
+ {
+ boneIndices = (const uint16_t * PX_RESTRICT)(void*)boneIndicesEa;
+ boneWeights = (const float * PX_RESTRICT)(void*)boneWeightsEa;
+ }
+
+ if (withNormals)
+ {
+ destNormals = (PxVec3 * PX_RESTRICT)(void*)destNormalsEa;
+ normals = (const PxVec3 * PX_RESTRICT)(void*)normalsEa;
+ }
+
+ if (withTangents)
+ {
+ destTangents4 = (float*)(void*)destTangentsEa;
+ tangents4 = (const float*)(void*)tangentsEa;
+ }
+
+
+ const uint32_t count16 = (workCount + 15) / 16;
+ for (uint32_t i = 0; i < count16; ++i)
+ {
+ //Fetch in the next block of stuff...
+ const uint32_t maxVerts = PxMin(numVertices - (a * WorkSize) - (i * 16u), 16u);
+ uint32_t numBoneWeight = *bonesPerVertex++;
+
+ prefetchLine(positions + 16);
+
+ if (withNormals)
+ {
+ prefetchLine(normals + 16);
+ }
+
+ if (withBones)
+ {
+ prefetchLine(boneIndices + (4 * 16));
+ prefetchLine(boneWeights + (2 * 16));
+ prefetchLine(boneWeights + (4 * 16));
+ }
+
+ if (withTangents)
+ {
+ prefetchLine(tangents4 + (4 * 16));
+ }
+
+ for (uint32_t j = 0; j < maxVerts; j++)
+ {
+ const uint32_t vertexIndex = i * 16 + j;
+ const uint32_t numBones = (numBoneWeight & 0x3) + 1;
+ numBoneWeight >>= 2;
+
+ {
+ PxVec3 untransformedPosition = *positions;
+ if (withMorph)
+ {
+ const PxVec3* morphDisplacement = (PxVec3*)&morphDisplacements[morphReordering[vertexIndex]];
+ untransformedPosition += *morphDisplacement;
+ }
+ Simd4f positionV = gSimd4fZero;
+ Simd4f normalV = gSimd4fZero;
+ Simd4f tangentV = gSimd4fZero;
+
+ if (withBones)
+ {
+ for (uint32_t k = 0; k < numBones; k++)
+ {
+ float weight = boneWeights[k];
+
+ PX_ASSERT(PxIsFinite(weight));
+
+ const uint16_t boneNr = boneIndices[k];
+
+ PxMat44& skinningMatrixV = (PxMat44&)compositeMatrices[boneNr];
+
+ const Simd4f weightV = Simd4fScalarFactory(weight);
+
+ Simd4f transformedPositionV = applyAffineTransform(skinningMatrixV, createSimd3f(untransformedPosition));
+ transformedPositionV = transformedPositionV * weightV;
+ positionV = positionV + transformedPositionV;
+
+ if (withNormals)
+ {
+ Simd4f transformedNormalV = applyLinearTransform(skinningMatrixV, createSimd3f(*normals));
+ transformedNormalV = transformedNormalV * weightV;
+ normalV = normalV + transformedNormalV;
+ }
+
+ if (withTangents)
+ {
+ const Simd4f inTangent = Simd4fAlignedLoadFactory(tangents4);
+ const Simd4f transformedTangentV = applyLinearTransform(skinningMatrixV, inTangent);
+ tangentV = tangentV + transformedTangentV * weightV;
+ }
+ }
+ }
+ else
+ {
+ PxMat44& skinningMatrixV = (PxMat44&)compositeMatrices[0];
+ positionV = applyAffineTransform(skinningMatrixV, createSimd3f(untransformedPosition));
+ if (withNormals)
+ {
+ normalV = applyLinearTransform(skinningMatrixV, createSimd3f(*normals));
+ }
+ if (withTangents)
+ {
+ const Simd4f inTangent = Simd4fAlignedLoadFactory(tangents4);
+ tangentV = applyLinearTransform(skinningMatrixV, inTangent);
+ }
+
+ }
+
+ if (withNormals)
+ {
+ normalV = normalizeSimd3f(normalV);
+ store3(&(destNormals->x), normalV);
+ }
+
+
+ if (withTangents)
+ {
+ tangentV = normalizeSimd3f(tangentV);
+ const Simd4f bitangent = Simd4fScalarFactory(tangents4[3]);
+ const Simd4f outTangent = select(gSimd4fMaskXYZ, tangentV, bitangent);
+ storeAligned(destTangents4, outTangent);
+ }
+
+ // if all weights are 0, we use the bind pose
+ // we don't really need that and it just slows us down..
+ //*destPositions = (numBones == 0) ? *positions : ps;
+ //*destPositions = ps;
+ store3(&destPositions->x, positionV);
+ }
+
+ positions++;
+ positionsEa++;
+ normals++;
+ normalsEa++;
+ if (withBones)
+ {
+ boneWeights += maxNumBonesPerVertex;
+ boneWeightsEa += maxNumBonesPerVertex;
+ boneIndices += maxNumBonesPerVertex;
+ boneIndicesEa += maxNumBonesPerVertex;
+ }
+ if (withTangents)
+ {
+ tangents4 += 4;
+ tangentsEa++;
+ destTangents4 += 4;
+ destTangentsEa++;
+ }
+ destPositions++;
+ destPositionsEa++;
+ destNormals++;
+ destNormalsEa++;
+ }
+ }
+ }
+
+}
+
+
+
+uint32_t* ClothingAssetData::getMorphMapping(uint32_t graphicalLod)
+{
+ if (mExt2IntMorphMappingCount == 0)
+ {
+ return NULL;
+ }
+
+ if (graphicalLod == (uint32_t) - 1 || graphicalLod > mGraphicalLodsCount)
+ {
+ graphicalLod = mGraphicalLodsCount;
+ }
+
+ uint32_t offset = 0;
+ for (uint32_t i = 0; i < graphicalLod; i++)
+ {
+ const ClothingMeshAssetData* meshAsset = GetLod(i);
+ for (uint32_t s = 0; s < meshAsset->mSubMeshCount; s++)
+ {
+ offset += GetSubmesh(meshAsset, s)->mVertexCount;
+ }
+ }
+
+ PX_ASSERT(offset < mExt2IntMorphMappingCount);
+ return mExt2IntMorphMapping + offset;
+}
+
+
+
+const uint32_t* ClothingAssetData::getCompressedNumBonesPerVertex(uint32_t graphicalLod, uint32_t submeshIndex, uint32_t& mapSize)
+{
+ mapSize = 0;
+
+ uint32_t offset = 0;
+ for (uint32_t lodIndex = 0; lodIndex < mGraphicalLodsCount; lodIndex++)
+ {
+ const ClothingMeshAssetData* meshAsset = GetLod(lodIndex);
+
+ for (uint32_t s = 0; s < meshAsset->mSubMeshCount; s++)
+ {
+ const uint32_t numVertices = GetSubmesh(meshAsset, s)->mVertexCount;
+
+ uint32_t numEntries = (numVertices + 15) / 16;
+ while ((numEntries & 0x3) != 0) // this is a numEntries % 4
+ {
+ numEntries++;
+ }
+
+ if (lodIndex == graphicalLod && submeshIndex == s)
+ {
+ mapSize = numEntries;
+ PX_ASSERT((mapSize % 4) == 0);
+ return &mCompressedNumBonesPerVertex[offset];
+ }
+
+ offset += numEntries;
+ PX_ASSERT(mCompressedNumBonesPerVertexCount >= offset);
+ }
+ }
+ return NULL;
+}
+
+
+
+const uint32_t* ClothingAssetData::getCompressedTangentW(uint32_t graphicalLod, uint32_t submeshIndex, uint32_t& mapSize)
+{
+ mapSize = 0;
+
+ uint32_t offset = 0;
+ for (uint32_t lodIndex = 0; lodIndex < mGraphicalLodsCount; lodIndex++)
+ {
+ const ClothingMeshAssetData* meshAsset = GetLod(lodIndex);
+
+ for (uint32_t s = 0; s < meshAsset->mSubMeshCount; s++)
+ {
+ const uint32_t numVertices = GetSubmesh(meshAsset, s)->mVertexCount;
+
+ uint32_t numEntries = (numVertices + 31) / 32;
+ while ((numEntries & 0x3) != 0) // this is a numEntries % 4
+ {
+ numEntries++;
+ }
+
+ if (lodIndex == graphicalLod && submeshIndex == s)
+ {
+ mapSize = numEntries;
+ PX_ASSERT((mapSize % 4) == 0);
+ return (uint32_t*)&mCompressedTangentW[offset];
+ }
+
+ offset += numEntries;
+ PX_ASSERT(mCompressedTangentWCount >= offset);
+ }
+ }
+ return NULL;
+}
+
+
+
+void ClothingAssetData::getNormalsAndVerticesForFace(PxVec3* vtx, PxVec3* nrm, uint32_t i,
+ const AbstractMeshDescription& srcPM) const
+{
+ // copy indices for convenience
+ PX_ASSERT(i < srcPM.numIndices);
+ uint32_t di[3];
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ di[j] = srcPM.pIndices[i + j];
+ }
+
+ // To guarantee consistency in our implicit tetrahedral mesh definition we must always order vertices
+ // idx[0,1,2] = min, max and mid
+ uint32_t idx[3];
+ idx[0] = PxMin(di[0], PxMin(di[1], di[2]));
+ idx[1] = PxMax(di[0], PxMax(di[1], di[2]));
+ idx[2] = idx[0];
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ if ((idx[0] != di[j]) && (idx[1] != di[j]))
+ {
+ idx[2] = di[j];
+ }
+ }
+
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ vtx[j] = srcPM.pPosition[idx[j]];
+ nrm[j] = srcPM.pNormal[idx[j]];
+#ifdef _DEBUG
+ // sanity
+ // PH: These normals 'should' always be normalized, maybe we can get rid of the normalize completely!
+ const float length = nrm[j].magnitudeSquared();
+ if (!(length >= 0.99f && length <= 1.01f))
+ {
+ static bool first = true;
+ if (first)
+ {
+ PX_ALWAYS_ASSERT();
+ first = false;
+ }
+ }
+#else
+ // PH: let's try and disable it in release mode...
+ //nrm[j].normalize();
+#endif
+ };
+}
+
+
+uint32_t ClothingAssetData::skinClothMapBSkinVertex(PxVec3& dstPos, PxVec3* dstNormal, uint32_t vIndex,
+ ClothingGraphicalLodParametersNS::SkinClothMapB_Type* pTCMB, const ClothingGraphicalLodParametersNS::SkinClothMapB_Type* pTCMBEnd,
+ const AbstractMeshDescription& srcPM) const
+{
+ uint32_t numIterations(0);
+ //uint32_t numSkipped(0);
+
+ //PX_ASSERT(dstPos.isZero());
+ //PX_ASSERT(dstNormal == NULL || dstNormal->isZero());
+
+ PX_ASSERT(srcPM.avgEdgeLength != 0.0f);
+ const float pmThickness = srcPM.avgEdgeLength;
+
+ while ((pTCMB->vertexIndexPlusOffset == vIndex) && (pTCMB < pTCMBEnd))
+ {
+ // skip vertices that we couldn't find a binding for
+ if (pTCMB->faceIndex0 == 0xFFFFFFFF || pTCMB->faceIndex0 >= srcPM.numIndices)
+ {
+ pTCMB++;
+ //numSkipped++;
+ //numIterations++;
+ continue;
+ }
+
+ PxVec3 vtx[3], nrm[3];
+ getNormalsAndVerticesForFace(vtx, nrm, pTCMB->faceIndex0, srcPM);
+
+ const TetraEncoding_Local& tetEnc = tetraTableLocal[pTCMB->tetraIndex];
+ const PxVec3 tv0 = vtx[0] + (tetEnc.sign[0] * pmThickness) * nrm[0];
+ const PxVec3 tv1 = vtx[1] + (tetEnc.sign[1] * pmThickness) * nrm[1];
+ const PxVec3 tv2 = vtx[2] + (tetEnc.sign[2] * pmThickness) * nrm[2];
+ const PxVec3 tv3 = vtx[tetEnc.lastVtxIdx] + (tetEnc.sign[3] * pmThickness) * nrm[tetEnc.lastVtxIdx];
+
+ const PxVec3& vtb = pTCMB->vtxTetraBary;
+ const float vtbw = 1.0f - vtb.x - vtb.y - vtb.z;
+ dstPos = (vtb.x * tv0) + (vtb.y * tv1) + (vtb.z * tv2) + (vtbw * tv3);
+ PX_ASSERT(dstPos.isFinite());
+
+ if (dstNormal != NULL)
+ {
+ const PxVec3& ntb = pTCMB->nrmTetraBary;
+ const float ntbw = 1.0f - ntb.x - ntb.y - ntb.z;
+ *dstNormal = (ntb.x * tv0) + (ntb.y * tv1) + (ntb.z * tv2) + (ntbw * tv3);
+ PX_ASSERT(dstNormal->isFinite());
+ }
+
+ pTCMB++;
+ numIterations++;
+ }
+
+ if (dstNormal != NULL && numIterations > 0)
+ {
+ // PH: this code certainly does not work if numIterations is bigger than 1 (it would need to average by dividing through numIterations)
+ PX_ASSERT(numIterations == 1);
+ *dstNormal -= dstPos;
+ *dstNormal *= physx::shdfnd::recipSqrtFast(dstNormal->magnitudeSquared());
+ }
+
+ return numIterations;
+}
+
+
+uint32_t ClothingAssetData::skinClothMapB(PxVec3* dstPositions, PxVec3* dstNormals, uint32_t numVertices,
+ const AbstractMeshDescription& srcPM, ClothingGraphicalLodParametersNS::SkinClothMapB_Type* map,
+ uint32_t numVerticesInMap, bool computeNormals) const
+{
+ PX_ASSERT(srcPM.numIndices % 3 == 0);
+
+ PX_ASSERT(srcPM.avgEdgeLength != 0.0f);
+
+ ClothingGraphicalLodParametersNS::SkinClothMapB_Type* pTCMB = map;
+ ClothingGraphicalLodParametersNS::SkinClothMapB_Type* pTCMBEnd = map + numVerticesInMap;
+
+ for (uint32_t j = 0; j < numVerticesInMap; j++)
+ {
+ uint32_t vertexIndex = pTCMB->vertexIndexPlusOffset;
+
+ if (vertexIndex >= numVertices)
+ {
+ pTCMB++;
+ continue;
+ }
+
+ PxVec3& p = dstPositions[vertexIndex];
+
+ PxVec3* n = NULL;
+ if (computeNormals)
+ {
+ n = dstNormals + vertexIndex;
+ }
+
+ uint32_t numIters = skinClothMapBSkinVertex(p, n, vertexIndex, pTCMB, pTCMBEnd, srcPM);
+ if (numIters == 0)
+ {
+ // PH: find next submesh
+ const uint32_t currentIterations = (uint32_t)(size_t)(pTCMB - map);
+ for (uint32_t i = currentIterations; i < numVerticesInMap; i++)
+ {
+ if (map[i].submeshIndex > pTCMB->submeshIndex)
+ {
+ numIters = i - currentIterations;
+ break;
+ }
+ }
+
+ // only return if it's still 0
+ if (numIters == 0)
+ {
+ return currentIterations;
+ }
+ }
+
+ pTCMB += numIters;
+ }
+
+ return numVertices;
+}
+
+bool ClothingAssetData::skinToTetraMesh(AbstractMeshDescription& destMesh,
+ const AbstractMeshDescription& srcPM,
+ const ClothingMeshAssetData& graphicalLod)
+{
+ if (graphicalLod.mTetraMap == NULL)
+ {
+ return false;
+ }
+
+ PX_ASSERT(srcPM.numIndices % 4 == 0);
+
+ PX_ASSERT(destMesh.pIndices == NULL);
+ PX_ASSERT(destMesh.pTangent == NULL);
+ PX_ASSERT(destMesh.pBitangent == NULL);
+ const bool computeNormals = destMesh.pNormal != NULL;
+
+ PxVec3 dummyNormal;
+
+ const uint32_t numGraphicalVertices = destMesh.numVertices;
+
+ const uint32_t* mainIndices = GetPhysicalMesh(graphicalLod.mPhysicalMeshId)->mIndices;
+
+ for (uint32_t i = 0; i < numGraphicalVertices; i++)
+ {
+ const ClothingGraphicalLodParametersNS::TetraLink_Type& currentLink = graphicalLod.mTetraMap[i];
+ if (currentLink.tetraIndex0 >= srcPM.numIndices)
+ {
+ continue;
+ }
+
+ PxVec3& position = destMesh.pPosition[i];
+ position = PxVec3(0.0f);
+
+ float vertexBary[4];
+ vertexBary[0] = currentLink.vertexBary.x;
+ vertexBary[1] = currentLink.vertexBary.y;
+ vertexBary[2] = currentLink.vertexBary.z;
+ vertexBary[3] = 1 - vertexBary[0] - vertexBary[1] - vertexBary[2];
+
+ const uint32_t* indices = mainIndices + currentLink.tetraIndex0;
+
+ if (computeNormals)
+ {
+ PxVec3& normal = computeNormals ? destMesh.pNormal[i] : dummyNormal;
+ normal = PxVec3(0.0f);
+
+ float normalBary[4];
+ normalBary[0] = currentLink.normalBary.x;
+ normalBary[1] = currentLink.normalBary.y;
+ normalBary[2] = currentLink.normalBary.z;
+ normalBary[3] = 1 - normalBary[0] - normalBary[1] - normalBary[2];
+
+ // compute skinned positions and normals
+ for (uint32_t j = 0; j < 4; j++)
+ {
+ const PxVec3& pos = srcPM.pPosition[indices[j]];
+ position += pos * vertexBary[j];
+ normal += pos * normalBary[j];
+ }
+
+ normal = normal - position;
+ normal *= nvidia::recipSqrtFast(normal.magnitudeSquared());
+ }
+ else
+ {
+ // only compute skinned positions, not normals
+ for (uint32_t j = 0; j < 4; j++)
+ {
+ const PxVec3& pos = srcPM.pPosition[indices[j]];
+ position += pos * vertexBary[j];
+ }
+ }
+ PX_ASSERT(position.isFinite());
+ }
+ return true;
+}
+
+
+
+}
+}
diff --git a/APEX_1.4/module/clothing/src/ClothingAssetImpl.cpp b/APEX_1.4/module/clothing/src/ClothingAssetImpl.cpp
new file mode 100644
index 00000000..cba5ef51
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/ClothingAssetImpl.cpp
@@ -0,0 +1,3849 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+
+#include "ApexDefs.h"
+
+#include "ClothingAsset.h"
+
+#include "ApexAuthorableObject.h"
+#include "ClothingActorProxy.h"
+#include "ClothingAssetImpl.h"
+#include "ClothingAssetData.h"
+#include "ClothingGlobals.h"
+#include "ClothingPhysicalMeshImpl.h"
+#include "ClothingPreviewProxy.h"
+#include "ClothingScene.h"
+#include "CookingPhysX.h"
+#include "ModulePerfScope.h"
+#include "nvparameterized/NvParamUtils.h"
+
+#include "ApexMath.h"
+#include "ClothingActorParam.h"
+#include "ClothingAssetParameters.h"
+#include "ClothingGraphicalLodParameters.h"
+#include "ModuleClothingHelpers.h"
+
+#include "PxStrideIterator.h"
+#include "PsSort.h"
+#include "PsThread.h"
+#include "ApexUsingNamespace.h"
+#include "PxMat33.h"
+#include "PsVecMath.h"
+
+#include "SimulationAbstract.h"
+#include "ApexPermute.h"
+
+#include "ApexPvdClient.h"
+#include "PxPvdDataStream.h"
+
+#define PX_SIMD_SKINNING 1
+
+#pragma warning( disable: 4101 ) // PX_COMPILE_TIME_ASSERT causes these warnings since they are
+// used within our apex namespace
+
+namespace nvidia
+{
+namespace clothing
+{
+
+AuthObjTypeID ClothingAssetImpl::mAssetTypeID = 0xffffffff;
+
+ClothingAssetImpl::ClothingAssetImpl(ModuleClothingImpl* module, ResourceList& list, const char* name) :
+ mModule(module),
+ mParams(DYNAMIC_CAST(ClothingAssetParameters*)(GetInternalApexSDK()->getParameterizedTraits()->createNvParameterized(ClothingAssetParameters::staticClassName()))),
+ mPhysicalMeshes(mParams, "physicalMeshes", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->physicalMeshes)),
+ mGraphicalLods(mParams, "graphicalLods", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->graphicalLods)),
+ mBones(mParams, "bones", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->bones)),
+ mBoneSpheres(mParams, "boneSpheres", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->boneSpheres)),
+ mSpherePairs(mParams, "boneSphereConnections", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->boneSphereConnections)),
+ mBoneActors(mParams, "boneActors", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->boneActors)),
+ mBoneVertices(mParams, "boneVertices", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->boneVertices)),
+ mBonePlanes(mParams, "bonePlanes", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->bonePlanes)),
+ mCollisionConvexes(mParams, "collisionConvexes", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->collisionConvexes)),
+ mName(name),
+ mExt2IntMorphMappingMaxValue(0),
+ mDirty(false),
+ mMorphMappingWarning(false)
+{
+ // this constructor is only executed when initializing the authoring asset
+ list.add(*this);
+
+#ifndef WITHOUT_PVD
+ mActors.setupForPvd(static_cast<ApexResourceInterface*>(this), "ClothingActors", "ClothingActor");
+#endif
+
+ // make sure these two methods are compiled!
+ AbstractMeshDescription pcm;
+ pcm.avgEdgeLength = 0.1f;
+}
+
+
+ClothingAssetImpl::ClothingAssetImpl(ModuleClothingImpl* module, ResourceList& list, NvParameterized::Interface* params, const char* name) :
+ mModule(module),
+ mParams(NULL),
+ mName(name),
+ mExt2IntMorphMappingMaxValue(0),
+ mDirty(false),
+ mMorphMappingWarning(false)
+{
+
+#ifndef WITHOUT_PVD
+ mActors.setupForPvd(static_cast<ApexResourceInterface*>(this), "ClothingActors", "ClothingActor");
+#endif
+
+ // wrong name?
+ if (params != NULL && ::strcmp(params->className(), ClothingAssetParameters::staticClassName()) != 0)
+ {
+ APEX_INTERNAL_ERROR(
+ "The parameterized interface is of type <%s> instead of <%s>. "
+ "This object will be initialized by an empty one instead!",
+ params->className(),
+ ClothingAssetParameters::staticClassName());
+
+ params->destroy();
+ params = NULL;
+ }
+ else if (params != NULL)
+ {
+ ClothingAssetParameters* checkParams = DYNAMIC_CAST(ClothingAssetParameters*)(params);
+
+ uint32_t boneRefsMesh = 0, boneRefsRB = 0;
+ for (int i = 0; i < checkParams->bones.arraySizes[0]; i++)
+ {
+ boneRefsMesh += checkParams->bones.buf[i].numMeshReferenced;
+ boneRefsRB += checkParams->bones.buf[i].numRigidBodiesReferenced;
+ }
+
+ if (checkParams->bones.arraySizes[0] > 0 && (boneRefsRB + boneRefsMesh == 0))
+ {
+ APEX_INTERNAL_ERROR(
+ "This parameterized object has not been prepared before serialization. "
+ "It will not be able to work and has been replaced by an empty one instead. "
+ "See NvParameterized::Interface::callPreSerializeCallback()");
+
+ params->destroy();
+ params = NULL;
+ }
+ }
+
+ if (params == NULL)
+ {
+ params = DYNAMIC_CAST(ClothingAssetParameters*)(GetInternalApexSDK()->getParameterizedTraits()->createNvParameterized(ClothingAssetParameters::staticClassName()));
+ }
+
+
+ PX_ASSERT(nvidia::strcmp(params->className(), ClothingAssetParameters::staticClassName()) == 0);
+ if (::strcmp(params->className(), ClothingAssetParameters::staticClassName()) == 0)
+ {
+ mParams = static_cast<ClothingAssetParameters*>(params);
+ mParams->setSerializationCallback(this, NULL);
+
+ bool ok = false;
+ PX_UNUSED(ok);
+
+ ok = mPhysicalMeshes.init(mParams, "physicalMeshes", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->physicalMeshes));
+ PX_ASSERT(ok);
+ ok = mGraphicalLods.init(mParams, "graphicalLods", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->graphicalLods));
+ PX_ASSERT(ok);
+ ok = mBones.init(mParams, "bones", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->bones));
+ PX_ASSERT(ok);
+ ok = mBoneSpheres.init(mParams, "boneSpheres", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->boneSpheres));
+ PX_ASSERT(ok);
+ ok = mSpherePairs.init(mParams, "boneSphereConnections", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->boneSphereConnections));
+ PX_ASSERT(ok);
+ ok = mBoneActors.init(mParams, "boneActors", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->boneActors));
+ PX_ASSERT(ok);
+ ok = mBoneVertices.init(mParams, "boneVertices", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->boneVertices));
+ PX_ASSERT(ok);
+ ok = mBonePlanes.init(mParams, "bonePlanes", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->bonePlanes));
+ PX_ASSERT(ok);
+ ok = mCollisionConvexes.init(mParams, "collisionConvexes", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->collisionConvexes));
+ PX_ASSERT(ok);
+
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ if (mGraphicalLods[i]->renderMeshAsset == NULL)
+ continue;
+
+ char buf[128];
+ size_t len = PxMin(mName.len(), 120u);
+ buf[0] = 0;
+ nvidia::strlcat(buf, len + 1, mName.c_str());
+ buf[len] = '_';
+ nvidia::snprintf(buf + len + 1, 128 - len - 1, "%d", i);
+ Asset* asset = GetApexSDK()->createAsset(mGraphicalLods[i]->renderMeshAsset, buf);
+ PX_ASSERT(::strcmp(asset->getObjTypeName(), RENDER_MESH_AUTHORING_TYPE_NAME) == 0);
+
+ RenderMeshAssetIntl* rma = static_cast<RenderMeshAssetIntl*>(asset);
+ if (rma->mergeBinormalsIntoTangents())
+ {
+ mDirty = true;
+ APEX_DEBUG_INFO("Performance warning. This asset <%s> has to be re-saved to speed up loading", name);
+ }
+
+ mGraphicalLods[i]->renderMeshAssetPointer = rma;
+ mDirty |= reorderGraphicsVertices(i, i == 0); // only warn the first time
+ }
+
+ bool cookingInvalid = false;
+
+ for (uint32_t i = 0; i < mPhysicalMeshes.size(); i++)
+ {
+ bool reorderVerts = false;
+ if (mPhysicalMeshes[i]->physicalMesh.numMaxDistance0Vertices == 0)
+ {
+ reorderVerts = true;
+ }
+
+ if (reorderVerts)
+ {
+ ClothingPhysicalMeshImpl* mesh = mModule->createPhysicalMeshInternal(mPhysicalMeshes[i]);
+
+ if (mesh != NULL)
+ {
+ const bool changed = reorderDeformableVertices(*mesh);
+
+ mesh->release();
+
+ cookingInvalid |= changed;
+ mDirty |= changed;
+ }
+ }
+ }
+
+ if (mParams->materialLibrary != NULL && cookingInvalid)
+ {
+ // So, if we turn on zerostretch also for the new solver, we should make sure the values are set soft enough not to introduce too much ghost forces
+ ClothingMaterialLibraryParameters* matLib = static_cast<ClothingMaterialLibraryParameters*>(mParams->materialLibrary);
+
+ for (int32_t i = 0; i < matLib->materials.arraySizes[0]; i++)
+ {
+ float& limit = matLib->materials.buf[i].hardStretchLimitation;
+
+ if (limit >= 1.0f)
+ {
+ limit = PxMax(limit, 1.1f); // must be either 0 (disabled) or > 1.1 for stability
+ }
+ }
+ }
+
+ if (mParams->boundingBox.minimum.isZero() && mParams->boundingBox.maximum.isZero())
+ {
+ updateBoundingBox();
+ }
+
+ uint32_t cookNow = 0;
+ const char* cookedDataClass = "Embedded";
+
+ ParamArray<ClothingAssetParametersNS::CookedEntry_Type> cookedEntries(mParams, "cookedData", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->cookedData));
+ for (uint32_t i = 0; i < cookedEntries.size(); i++)
+ {
+ if (cookedEntries[i].cookedData != NULL)
+ {
+ BackendFactory* cookedDataBackend = mModule->getBackendFactory(cookedEntries[i].cookedData->className());
+ PX_ASSERT(cookedDataBackend);
+ if (cookedDataBackend != NULL)
+ {
+ // compare data version with current version of the data backend
+ uint32_t cookedDataVersion = cookedDataBackend->getCookedDataVersion(cookedEntries[i].cookedData);
+ uint32_t cookingVersion = cookedDataBackend->getCookingVersion();
+
+ if (cookingVersion != cookedDataVersion || cookingInvalid
+#if PX_PHYSICS_VERSION_MAJOR == 3
+ // don't use native CookingPhysX, only use embedded solver
+ || cookedDataVersion == CookingPhysX::getCookingVersion()
+#endif
+ )
+ {
+ cookNow = cookedDataVersion;
+ cookedEntries[i].cookedData->destroy();
+ cookedEntries[i].cookedData = NULL;
+ }
+ }
+ }
+ }
+ if (cookNow != 0)
+ {
+ APEX_DEBUG_WARNING("Asset (%s) cooked data version (%d/0x%08x) does not match the current sdk version. Recooking.", name, cookNow, cookNow);
+ }
+
+ if (cookedEntries.isEmpty())
+ {
+ ClothingAssetParametersNS::CookedEntry_Type entry;
+ entry.scale = 1.0f;
+ entry.cookedData = NULL;
+ cookedEntries.pushBack(entry);
+ APEX_DEBUG_INFO("Asset (%s) has no cooked data and will be re-cooked every time it's loaded, asset needs to be resaved!", name);
+ cookNow = 1;
+ }
+
+ if (cookNow != 0)
+ {
+ BackendFactory* cookingBackend = mModule->getBackendFactory(cookedDataClass);
+
+ PX_ASSERT(cookingBackend != NULL);
+
+ for (uint32_t i = 0; i < cookedEntries.size(); i++)
+ {
+ if (cookedEntries[i].cookedData == NULL && cookingBackend != NULL)
+ {
+ ClothingAssetParametersNS::CookedEntry_Type& entry = cookedEntries[i];
+
+ CookingAbstract* cookingJob = cookingBackend->createCookingJob();
+ prepareCookingJob(*cookingJob, entry.scale, NULL, NULL);
+
+ if (cookingJob->isValid())
+ {
+ entry.cookedData = cookingJob->execute();
+ }
+ PX_DELETE_AND_RESET(cookingJob);
+ }
+ }
+
+ mDirty = true;
+ }
+ }
+
+ list.add(*this);
+}
+
+
+
+uint32_t ClothingAssetImpl::forceLoadAssets()
+{
+ uint32_t assetLoadedCount = 0;
+
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ if (mGraphicalLods[i]->renderMeshAssetPointer == NULL)
+ continue;
+
+ RenderMeshAssetIntl* rma = reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[i]->renderMeshAssetPointer);
+ assetLoadedCount += rma->forceLoadAssets();
+ }
+
+ return assetLoadedCount;
+
+}
+
+
+
+NvParameterized::Interface* ClothingAssetImpl::getDefaultActorDesc()
+{
+ NvParameterized::Interface* ret = NULL;
+
+ if (mModule != NULL)
+ {
+ ret = mModule->getApexClothingActorParams();
+
+ if (ret != NULL)
+ {
+ ret->initDefaults();
+
+ // need to customize it per asset
+ PX_ASSERT(nvidia::strcmp(ret->className(), ClothingActorParam::staticClassName()) == 0);
+ ClothingActorParam* actorDesc = static_cast<ClothingActorParam*>(ret);
+ actorDesc->clothingMaterialIndex = mParams->materialIndex;
+ }
+ }
+
+ return ret;
+}
+
+
+
+NvParameterized::Interface* ClothingAssetImpl::getDefaultAssetPreviewDesc()
+{
+ NvParameterized::Interface* ret = NULL;
+
+ if (mModule != NULL)
+ {
+ ret = mModule->getApexClothingPreviewParams();
+
+ if (ret != NULL)
+ {
+ ret->initDefaults();
+ }
+ }
+
+ return ret;
+}
+
+
+
+Actor* ClothingAssetImpl::createApexActor(const NvParameterized::Interface& params, Scene& apexScene)
+{
+ if (!isValidForActorCreation(params, apexScene))
+ {
+ return NULL;
+ }
+ ClothingActorProxy* proxy = NULL;
+ ClothingScene* clothingScene = mModule->getClothingScene(apexScene);
+ proxy = PX_NEW(ClothingActorProxy)(params, this, *clothingScene, &mActors);
+ PX_ASSERT(proxy != NULL);
+ return proxy;
+}
+
+
+NvParameterized::Interface* ClothingAssetImpl::releaseAndReturnNvParameterizedInterface()
+{
+ NvParameterized::Interface* ret = mParams;
+ mParams->setSerializationCallback(NULL, NULL);
+ mParams = NULL;
+ release();
+ return ret;
+}
+
+
+
+bool ClothingAssetImpl::isValidForActorCreation(const NvParameterized::Interface& params, Scene& apexScene) const
+{
+ bool ret = false;
+
+ if (ClothingActorImpl::isValidDesc(params))
+ {
+ ClothingScene* clothingScene = mModule->getClothingScene(apexScene);
+ if (clothingScene)
+ {
+ if (!clothingScene->isSimulating())
+ {
+ ret = true;
+ }
+ else
+ {
+ APEX_INTERNAL_ERROR("Cannot create ClothingActor while simulation is running");
+ }
+ }
+ }
+ else
+ {
+ APEX_INVALID_PARAMETER("ClothingActorDesc is invalid");
+ }
+ return ret;
+}
+
+
+bool ClothingAssetImpl::isDirty() const
+{
+ return mDirty;
+}
+
+
+
+void ClothingAssetImpl::release()
+{
+ mModule->mSdk->releaseAsset(*this);
+}
+
+
+
+ClothingActor* ClothingAssetImpl::getActor(uint32_t index)
+{
+ READ_ZONE();
+ if (index < mActors.getSize())
+ {
+ return DYNAMIC_CAST(ClothingActorProxy*)(mActors.getResource(index));
+ }
+ return NULL;
+}
+
+
+
+float ClothingAssetImpl::getMaximumSimulationBudget(uint32_t solverIterations) const
+{
+ uint32_t maxCost = 0;
+
+ for (uint32_t i = 0; i < mPhysicalMeshes.size(); i++)
+ {
+ uint32_t iterations = (uint32_t)(mPhysicalMeshes[i]->physicalMesh.numSimulatedVertices * solverIterations);
+ maxCost = PxMax(maxCost, iterations);
+ }
+
+ return static_cast<float>(maxCost);
+}
+
+
+
+uint32_t ClothingAssetImpl::getNumGraphicalLodLevels() const
+{
+ READ_ZONE();
+ return mGraphicalLods.size();
+}
+
+
+
+uint32_t ClothingAssetImpl::getGraphicalLodValue(uint32_t lodLevel) const
+{
+ READ_ZONE();
+ if (lodLevel < mGraphicalLods.size())
+ {
+ return mGraphicalLods[lodLevel]->lod;
+ }
+
+ return uint32_t(-1);
+}
+
+
+
+float ClothingAssetImpl::getBiggestMaxDistance() const
+{
+ READ_ZONE();
+ float maxValue = 0.0f;
+ for (uint32_t i = 0; i < mPhysicalMeshes.size(); i++)
+ {
+ maxValue = PxMax(maxValue, mPhysicalMeshes[i]->physicalMesh.maximumMaxDistance);
+ }
+
+ return maxValue;
+}
+
+
+
+bool ClothingAssetImpl::remapBoneIndex(const char* name, uint32_t newIndex)
+{
+ WRITE_ZONE();
+ uint32_t found = 0;
+ const uint32_t numBones = mBones.size();
+ for (uint32_t i = 0; i < numBones; i++)
+ {
+ if (mBones[i].name != NULL && (::strcmp(mBones[i].name, name) == 0))
+ {
+ mBones[i].externalIndex = (int32_t)newIndex;
+ found++;
+ }
+ }
+
+ if (found > 1)
+ {
+ APEX_DEBUG_WARNING("The asset contains %i bones with name %s. All occurences were mapped.", found, name);
+ }
+ else if (found == 0)
+ {
+ APEX_DEBUG_INFO("The asset does not contain a bone with name %s", name);
+ }
+
+ return (found == 1); // sanity
+}
+
+
+
+const char* ClothingAssetImpl::getBoneName(uint32_t internalIndex) const
+{
+ READ_ZONE();
+ if (internalIndex >= mBones.size())
+ {
+ return "";
+ }
+
+ return mBones[internalIndex].name;
+}
+
+
+
+bool ClothingAssetImpl::getBoneBasePose(uint32_t internalIndex, PxMat44& result) const
+{
+ READ_ZONE();
+ if (internalIndex < mBones.size())
+ {
+ result = mBones[internalIndex].bindPose;
+ return true;
+ }
+ return false;
+}
+
+
+
+void ClothingAssetImpl::getBoneMapping(uint32_t* internal2externalMap) const
+{
+ READ_ZONE();
+ for (uint32_t i = 0; i < mBones.size(); i++)
+ {
+ internal2externalMap[(uint32_t)mBones[i].internalIndex] = (uint32_t)mBones[i].externalIndex;
+ }
+}
+
+
+
+uint32_t ClothingAssetImpl::prepareMorphTargetMapping(const PxVec3* originalPositions, uint32_t numPositions, float epsilon)
+{
+ WRITE_ZONE();
+ uint32_t numInternalVertices = 0;
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ RenderMeshAssetIntl* rma = getGraphicalMesh(i);
+ if (rma == NULL)
+ continue;
+
+ for (uint32_t s = 0; s < rma->getSubmeshCount(); s++)
+ {
+ numInternalVertices += rma->getSubmesh(s).getVertexCount(0);
+ }
+ }
+ numInternalVertices += mBoneVertices.size();
+
+ mExt2IntMorphMapping.resize(numInternalVertices);
+ uint32_t indexWritten = 0;
+
+ uint32_t numLarger = 0;
+ float epsilon2 = epsilon * epsilon;
+
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ RenderMeshAssetIntl* rma = getGraphicalMesh(i);
+ if (rma == NULL)
+ continue;
+
+ for (uint32_t s = 0; s < rma->getSubmeshCount(); s++)
+ {
+ const uint32_t numVertices = rma->getSubmesh(s).getVertexCount(0);
+ const VertexFormat& format = rma->getSubmesh(s).getVertexBuffer().getFormat();
+ const uint32_t positionIndex = (uint32_t)format.getBufferIndexFromID(format.getSemanticID(RenderVertexSemantic::POSITION));
+ if (format.getBufferFormat(positionIndex) == RenderDataFormat::FLOAT3)
+ {
+ PxVec3* positions = (PxVec3*)rma->getSubmesh(s).getVertexBuffer().getBuffer(positionIndex);
+ for (uint32_t v = 0; v < numVertices; v++)
+ {
+ float closestDist2 = PX_MAX_F32;
+ uint32_t closestIndex = (uint32_t) - 1;
+ for (uint32_t iv = 0; iv < numPositions; iv++)
+ {
+ float dist2 = (originalPositions[iv] - positions[v]).magnitudeSquared();
+ if (dist2 < closestDist2)
+ {
+ closestDist2 = dist2;
+ closestIndex = iv;
+ }
+ }
+ PX_ASSERT(closestIndex != (uint32_t) - 1);
+ mExt2IntMorphMapping[indexWritten++] = closestIndex;
+ numLarger += closestDist2 < epsilon2 ? 0 : 1;
+ }
+ }
+ else
+ {
+ PX_ALWAYS_ASSERT();
+ }
+ }
+ }
+
+ for (uint32_t i = 0; i < mBoneVertices.size(); i++)
+ {
+ float closestDist2 = PX_MAX_F32;
+ uint32_t closestIndex = (uint32_t) - 1;
+ for (uint32_t iv = 0; iv < numPositions; iv++)
+ {
+ float dist2 = (originalPositions[iv] - mBoneVertices[i]).magnitudeSquared();
+ if (dist2 < closestDist2)
+ {
+ closestDist2 = dist2;
+ closestIndex = iv;
+ }
+ }
+ PX_ASSERT(closestIndex != (uint32_t) - 1);
+ mExt2IntMorphMapping[indexWritten++] = closestIndex;
+ numLarger += closestDist2 < epsilon2 ? 0 : 1;
+ }
+
+ PX_ASSERT(indexWritten == numInternalVertices);
+ mExt2IntMorphMappingMaxValue = numPositions;
+
+ return numLarger;
+}
+
+
+
+void ClothingAssetImpl::preSerialize(void* /*userData*/)
+{
+ mDirty = false;
+}
+
+
+
+RenderMeshAssetIntl* ClothingAssetImpl::getGraphicalMesh(uint32_t index)
+{
+ if (index < mGraphicalLods.size())
+ {
+ return reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[index]->renderMeshAssetPointer);
+ }
+
+ return NULL;
+}
+
+
+
+const ClothingGraphicalLodParameters* ClothingAssetImpl::getGraphicalLod(uint32_t index) const
+{
+ if (index < mGraphicalLods.size())
+ {
+ return mGraphicalLods[index];
+ }
+
+ return NULL;
+}
+
+
+void ClothingAssetImpl::releaseClothingActor(ClothingActor& actor)
+{
+ ClothingActorProxy* proxy = DYNAMIC_CAST(ClothingActorProxy*)(&actor);
+ proxy->destroy();
+}
+
+
+
+void ClothingAssetImpl::releaseClothingPreview(ClothingPreview& preview)
+{
+ ClothingPreviewProxy* proxy = DYNAMIC_CAST(ClothingPreviewProxy*)(&preview);
+ proxy->destroy();
+}
+
+
+
+bool ClothingAssetImpl::writeBoneMatrices(PxMat44 localPose, const PxMat44* newBoneMatrices, const uint32_t byteStride,
+ const uint32_t numBones, PxMat44* dest, bool isInternalOrder, bool multInvBindPose)
+{
+ PX_PROFILE_ZONE("ClothingAssetImpl::writeBoneMatrices", GetInternalApexSDK()->getContextId());
+
+ PX_ASSERT(byteStride >= sizeof(PxMat44));
+
+ bool changed = false;
+
+ if (mBones.isEmpty())
+ {
+ APEX_INTERNAL_ERROR("bone map is empty, this is a error condition");
+ }
+ else
+ {
+ // PH: if bones are present, but not set, we just have to write them with global pose
+ const uint8_t* src = (const uint8_t*)newBoneMatrices;
+ const uint32_t numBonesReferenced = mParams->bonesReferenced;
+ for (uint32_t i = 0; i < mBones.size(); i++)
+ {
+ PX_ASSERT(mBones[i].internalIndex < (int32_t)mBones.size());
+ PX_ASSERT(isInternalOrder || mBones[i].externalIndex >= 0);
+ const uint32_t internalIndex = i;
+ const uint32_t externalIndex = isInternalOrder ? i : mBones[i].externalIndex;
+ if (internalIndex < numBonesReferenced && mBones[i].internalIndex >= 0)
+ {
+ PxMat44& oldMat = dest[internalIndex];
+ PX_ALIGN(16, PxMat44) newMat;
+
+ if (src != NULL && externalIndex < numBones)
+ {
+ PxMat44 skinningTransform = *(const PxMat44*)(src + byteStride * externalIndex);
+ if (multInvBindPose)
+ {
+ skinningTransform = skinningTransform * mInvBindPoses[internalIndex];
+ }
+ newMat = localPose * skinningTransform;
+ }
+ else
+ {
+ newMat = localPose;
+ }
+
+ if (newMat != oldMat) // PH: let's hope this comparison is not too slow
+ {
+ changed |= (i < numBonesReferenced);
+ oldMat = newMat;
+ }
+ }
+ }
+ }
+ return changed;
+}
+
+
+
+ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* ClothingAssetImpl::getPhysicalMeshFromLod(uint32_t graphicalLodId) const
+{
+ const uint32_t physicalMeshId = mGraphicalLods[graphicalLodId]->physicalMeshId;
+
+ // -1 is also bigger than mPhysicalMeshes.size() for an unsigned
+ if (physicalMeshId >= mPhysicalMeshes.size())
+ {
+ return NULL;
+ }
+
+ return &mPhysicalMeshes[physicalMeshId]->physicalMesh;
+}
+
+
+ClothingPhysicalMeshParametersNS::SkinClothMapB_Type* ClothingAssetImpl::getTransitionMapB(uint32_t dstPhysicalMeshId, uint32_t srcPhysicalMeshId, float& thickness, float& offset)
+{
+ if (srcPhysicalMeshId + 1 == dstPhysicalMeshId)
+ {
+ thickness = mPhysicalMeshes[dstPhysicalMeshId]->transitionDownThickness;
+ offset = mPhysicalMeshes[dstPhysicalMeshId]->transitionDownOffset;
+ return mPhysicalMeshes[dstPhysicalMeshId]->transitionDownB.buf;
+ }
+ else if (srcPhysicalMeshId == dstPhysicalMeshId + 1)
+ {
+ thickness = mPhysicalMeshes[dstPhysicalMeshId]->transitionUpThickness;
+ offset = mPhysicalMeshes[dstPhysicalMeshId]->transitionUpOffset;
+ return mPhysicalMeshes[dstPhysicalMeshId]->transitionUpB.buf;
+ }
+
+ thickness = 0.0f;
+ offset = 0.0f;
+ return NULL;
+}
+
+
+
+ClothingPhysicalMeshParametersNS::SkinClothMapD_Type* ClothingAssetImpl::getTransitionMap(uint32_t dstPhysicalMeshId, uint32_t srcPhysicalMeshId, float& thickness, float& offset)
+{
+ if (srcPhysicalMeshId + 1 == dstPhysicalMeshId)
+ {
+ thickness = mPhysicalMeshes[dstPhysicalMeshId]->transitionDownThickness;
+ offset = mPhysicalMeshes[dstPhysicalMeshId]->transitionDownOffset;
+ return mPhysicalMeshes[dstPhysicalMeshId]->transitionDown.buf;
+ }
+ else if (srcPhysicalMeshId == dstPhysicalMeshId + 1)
+ {
+ thickness = mPhysicalMeshes[dstPhysicalMeshId]->transitionUpThickness;
+ offset = mPhysicalMeshes[dstPhysicalMeshId]->transitionUpOffset;
+ return mPhysicalMeshes[dstPhysicalMeshId]->transitionUp.buf;
+ }
+
+ thickness = 0.0f;
+ offset = 0.0f;
+ return NULL;
+}
+
+
+
+NvParameterized::Interface* ClothingAssetImpl::getCookedData(float actorScale)
+{
+ NvParameterized::Interface* closest = NULL;
+ float closestDiff = PX_MAX_F32;
+
+ for (int32_t i = 0; i < mParams->cookedData.arraySizes[0]; i++)
+ {
+ NvParameterized::Interface* cookedData = mParams->cookedData.buf[i].cookedData;
+ const float cookedDataScale = mParams->cookedData.buf[i].scale;
+
+ if (cookedData == NULL)
+ {
+ continue;
+ }
+
+#ifdef _DEBUG
+ if (::strcmp(cookedData->className(), ClothingCookedParam::staticClassName()) == 0)
+ {
+ // silly debug verification
+ PX_ASSERT(cookedDataScale == ((ClothingCookedParam*)cookedData)->actorScale);
+ }
+#endif
+
+ const float scaleDiff = PxAbs(actorScale - cookedDataScale);
+ if (scaleDiff < closestDiff)
+ {
+ closest = cookedData;
+ closestDiff = scaleDiff;
+ }
+ }
+
+ if (closest != NULL && closestDiff < 0.01f)
+ {
+ return closest;
+ }
+
+ return NULL;
+}
+
+
+
+uint32_t ClothingAssetImpl::getCookedPhysXVersion() const
+{
+ uint32_t version = 0;
+
+ for (int32_t i = 0; i < mParams->cookedData.arraySizes[0]; i++)
+ {
+ const NvParameterized::Interface* cookedData = mParams->cookedData.buf[i].cookedData;
+ if (cookedData != NULL)
+ {
+ const char* className = cookedData->className();
+ BackendFactory* factory = mModule->getBackendFactory(className);
+
+ uint32_t v = factory->getCookedDataVersion(cookedData);
+ PX_ASSERT(version == 0 || version == v);
+ version = v;
+ }
+ }
+
+ // version == 0 usually means that there is no maxdistance > 0 at all!
+ //PX_ASSERT(version != 0);
+ return version;
+}
+
+
+
+ClothSolverMode::Enum ClothingAssetImpl::getClothSolverMode() const
+{
+ return ClothSolverMode::v3;
+}
+
+
+
+SimulationAbstract* ClothingAssetImpl::getSimulation(uint32_t physicalMeshId, NvParameterized::Interface* cookedParam, ClothingScene* clothingScene)
+{
+ SimulationAbstract* result = NULL;
+
+ mUnusedSimulationMutex.lock();
+
+ for (uint32_t i = 0; i < mUnusedSimulation.size(); i++)
+ {
+ PX_ASSERT(mUnusedSimulation[i] != NULL);
+ if (mUnusedSimulation[i]->physicalMeshId != physicalMeshId)
+ {
+ continue;
+ }
+
+ if (mUnusedSimulation[i]->getCookedData() != cookedParam)
+ {
+ continue;
+ }
+
+ if (mUnusedSimulation[i]->getClothingScene() != clothingScene)
+ {
+ continue;
+ }
+
+ // we found one
+ result = mUnusedSimulation[i];
+ for (uint32_t j = i + 1; j < mUnusedSimulation.size(); j++)
+ {
+ mUnusedSimulation[j - 1] = mUnusedSimulation[j];
+ }
+
+ mUnusedSimulation.popBack();
+ break;
+ }
+
+ mUnusedSimulationMutex.unlock();
+
+ return result;
+}
+
+
+
+void ClothingAssetImpl::returnSimulation(SimulationAbstract* simulation)
+{
+ PX_ASSERT(simulation != NULL);
+
+ bool isAssetParam = false;
+ for (int32_t i = 0; i < mParams->cookedData.arraySizes[0]; i++)
+ {
+ isAssetParam |= mParams->cookedData.buf[i].cookedData == simulation->getCookedData();
+ }
+
+ nvidia::Mutex::ScopedLock scopeLock(mUnusedSimulationMutex);
+
+ if (mModule->getMaxUnusedPhysXResources() == 0 || !isAssetParam || !simulation->needsExpensiveCreation())
+ {
+ destroySimulation(simulation);
+ return;
+ }
+
+ if (mUnusedSimulation.size() > mModule->getMaxUnusedPhysXResources())
+ {
+ destroySimulation(mUnusedSimulation[0]);
+
+ for (uint32_t i = 1; i < mUnusedSimulation.size(); i++)
+ {
+ mUnusedSimulation[i - 1] = mUnusedSimulation[i];
+ }
+
+ mUnusedSimulation[mUnusedSimulation.size() - 1] = simulation;
+ }
+ else
+ {
+ mUnusedSimulation.pushBack(simulation);
+ }
+
+ simulation->disablePhysX(mModule->getDummyActor());
+}
+
+
+
+void ClothingAssetImpl::destroySimulation(SimulationAbstract* simulation)
+{
+ PX_ASSERT(simulation != NULL);
+
+ simulation->unregisterPhysX();
+ PX_DELETE_AND_RESET(simulation);
+}
+
+
+
+void ClothingAssetImpl::initCollision(SimulationAbstract* simulation, const PxMat44* boneTansformations,
+ ResourceList& actorPlanes,
+ ResourceList& actorConvexes,
+ ResourceList& actorSpheres,
+ ResourceList& actorCapsules,
+ ResourceList& actorTriangleMeshes,
+ const ClothingActorParam* actorParam,
+ const PxMat44& globalPose, bool localSpaceSim)
+{
+ simulation->initCollision( mBoneActors.begin(), mBoneActors.size(), mBoneSpheres.begin(), mBoneSpheres.size(), mSpherePairs.begin(), mSpherePairs.size(), mBonePlanes.begin(), mBonePlanes.size(), mCollisionConvexes.begin(), mCollisionConvexes.size(), mBones.begin(), boneTansformations,
+ actorPlanes, actorConvexes, actorSpheres, actorCapsules, actorTriangleMeshes,
+ actorParam->actorDescTemplate, actorParam->shapeDescTemplate, actorParam->actorScale,
+ globalPose, localSpaceSim);
+}
+
+
+
+void ClothingAssetImpl::updateCollision(SimulationAbstract* simulation, const PxMat44* boneTansformations,
+ ResourceList& actorPlanes,
+ ResourceList& actorConvexes,
+ ResourceList& actorSpheres,
+ ResourceList& actorCapsules,
+ ResourceList& actorTriangleMeshes,
+ bool teleport)
+{
+ simulation->updateCollision(mBoneActors.begin(), mBoneActors.size(), mBoneSpheres.begin(), mBoneSpheres.size(), mBonePlanes.begin(), mBonePlanes.size(), mBones.begin(), boneTansformations,
+ actorPlanes, actorConvexes, actorSpheres, actorCapsules, actorTriangleMeshes, teleport);
+}
+
+
+
+uint32_t ClothingAssetImpl::getPhysicalMeshID(uint32_t graphicalLodId) const
+{
+ if (graphicalLodId >= mGraphicalLods.size())
+ {
+ return (uint32_t) - 1;
+ }
+
+ return mGraphicalLods[graphicalLodId]->physicalMeshId;
+}
+
+
+
+void ClothingAssetImpl::visualizeSkinCloth(RenderDebugInterface& renderDebug, AbstractMeshDescription& srcPM, bool showTets, float actorScale) const
+{
+#ifdef WITHOUT_DEBUG_VISUALIZE
+ PX_UNUSED(renderDebug);
+ PX_UNUSED(srcPM);
+ PX_UNUSED(showTets);
+ PX_UNUSED(actorScale);
+#else
+ using RENDER_DEBUG::DebugColors;
+ using RENDER_DEBUG::DebugRenderState;
+
+ if ((srcPM.pPosition != NULL) && (srcPM.pIndices != NULL) && (srcPM.pNormal != NULL))
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->pushRenderState();
+
+ RENDER_DEBUG_IFACE(&renderDebug)->removeFromCurrentState(DebugRenderState::SolidShaded);
+
+ const uint32_t colorWhite = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::White);
+ const uint32_t colorRed = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Red);
+ const uint32_t colorDarkRed = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::DarkRed);
+ const uint32_t colorGreen = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Green);
+ const uint32_t colorPurple = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Purple);
+
+ const float meshThickness = srcPM.avgEdgeLength * actorScale;
+ // for each triangle in the Physical Mesh draw lines delimiting all the tetras
+ for (uint32_t i = 0; i < srcPM.numIndices; i += 3)
+ {
+ if (showTets)
+ {
+ PxVec3 vtx[3], nrm[3];
+ getNormalsAndVerticesForFace(vtx, nrm, i, srcPM);
+
+ // draw lines for all edges of each tetrahedron (sure, there are redundant lines, but this is for debugging purposes)
+ for (uint32_t tIdx = 0; tIdx < TETRA_LUT_SIZE; tIdx++)
+ {
+ // compute the tetra vertices based on the index
+ const TetraEncoding& tetEnc = tetraTable[tIdx];
+ PxVec3 tv0 = vtx[0] + (tetEnc.sign[0] * nrm[0] * meshThickness);
+ PxVec3 tv1 = vtx[1] + (tetEnc.sign[1] * nrm[1] * meshThickness);
+ PxVec3 tv2 = vtx[2] + (tetEnc.sign[2] * nrm[2] * meshThickness);
+ PxVec3 tv3 = vtx[tetEnc.lastVtxIdx] + (tetEnc.sign[3] * nrm[tetEnc.lastVtxIdx] * meshThickness);
+
+ uint32_t color = tIdx < 3 ? colorGreen : colorPurple;
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(color);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(tv1, tv2);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(tv2, tv3);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(tv3, tv1);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(tv0, tv1);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(tv0, tv2);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(tv0, tv3);
+ }
+ }
+ else
+ {
+ uint32_t idx[3] =
+ {
+ srcPM.pIndices[i + 0],
+ srcPM.pIndices[i + 1],
+ srcPM.pIndices[i + 2],
+ };
+
+ PxVec3 vtx[3], nrm[3];
+ for (uint32_t u = 0; u < 3; u++)
+ {
+ vtx[u] = srcPM.pPosition[idx[u]];
+ nrm[u] = srcPM.pNormal[idx[u]] * meshThickness;
+ }
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorWhite);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(vtx[0], vtx[1], vtx[2]);
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorGreen);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(vtx[0] + nrm[0], vtx[1] + nrm[1], vtx[2] + nrm[2]);
+ for (uint32_t u = 0; u < 3; u++)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(vtx[u], vtx[u] + nrm[u]);
+ }
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorPurple);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(vtx[0] - nrm[0], vtx[1] - nrm[1], vtx[2] - nrm[2]);
+ for (uint32_t u = 0; u < 3; u++)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(vtx[u], vtx[u] - nrm[u]);
+ }
+ }
+ }
+
+#if 1
+ // display some features of the physical mesh as it's updated at runtime
+
+ srcPM.UpdateDerivedInformation(&renderDebug);
+
+ // draw the mesh's bounding box
+ PxBounds3 bounds(srcPM.pMin, srcPM.pMax);
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorRed);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugBound(bounds);
+
+ // draw line from the centroid to the top-most corner of the AABB
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorDarkRed);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(srcPM.centroid, srcPM.pMax);
+
+ // draw white line along the same direction (but negated) to display the avgEdgeLength
+ PxVec3 dirToPMax = (srcPM.pMax - srcPM.centroid);
+ dirToPMax.normalize();
+ PxVec3 pEdgeLengthAway = srcPM.centroid - (dirToPMax * srcPM.avgEdgeLength);
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorWhite);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(srcPM.centroid, pEdgeLengthAway);
+
+ // draw green line along the same direction to display the physical mesh thickness
+ PxVec3 pPmThicknessAway = srcPM.centroid + (dirToPMax * meshThickness);
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorGreen);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(srcPM.centroid, pPmThicknessAway);
+#endif
+
+ RENDER_DEBUG_IFACE(&renderDebug)->popRenderState();
+ }
+#endif
+}
+
+
+
+void ClothingAssetImpl::visualizeSkinClothMap(RenderDebugInterface& renderDebug, AbstractMeshDescription& srcPM,
+ SkinClothMapB* skinClothMapB, uint32_t skinClothMapBSize,
+ SkinClothMap* skinClothMap, uint32_t skinClothMapSize,
+ float actorScale, bool onlyBad, bool invalidBary) const
+{
+#ifdef WITHOUT_DEBUG_VISUALIZE
+ PX_UNUSED(renderDebug);
+ PX_UNUSED(srcPM);
+ PX_UNUSED(skinClothMapB);
+ PX_UNUSED(skinClothMapBSize);
+ PX_UNUSED(skinClothMap);
+ PX_UNUSED(skinClothMapSize);
+ PX_UNUSED(actorScale);
+ PX_UNUSED(onlyBad);
+ PX_UNUSED(invalidBary);
+#else
+ using RENDER_DEBUG::DebugColors;
+ using RENDER_DEBUG::DebugRenderState;
+
+ RENDER_DEBUG_IFACE(&renderDebug)->pushRenderState();
+
+ RENDER_DEBUG_IFACE(&renderDebug)->removeFromCurrentState(DebugRenderState::SolidShaded);
+ const float meshThickness = srcPM.avgEdgeLength * actorScale;
+
+ if ((skinClothMapB != NULL) && (srcPM.pPosition != NULL) && (srcPM.pIndices != NULL) && (srcPM.pNormal != NULL))
+ {
+ const uint32_t colorRed = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Red);
+ const uint32_t colorDarkRed = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::DarkRed);
+ const uint32_t colorBlue = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Blue);
+ const uint32_t colorYellow = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Yellow);
+ const uint32_t colorGreen = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Green);
+ const uint32_t colorPurple = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Purple);
+
+ for (uint32_t i = 0; i < skinClothMapBSize; i++)
+ {
+ const SkinClothMapB& mapping = skinClothMapB[i];
+
+ if (mapping.faceIndex0 >= srcPM.numIndices)
+ {
+ break;
+ }
+
+ const PxVec3 vtb = mapping.vtxTetraBary;
+ const float vtb_w = 1.0f - vtb.x - vtb.y - vtb.z;
+ const bool badVtx =
+ vtb.x < 0.0f || vtb.x > 1.0f ||
+ vtb.y < 0.0f || vtb.y > 1.0f ||
+ vtb.z < 0.0f || vtb.z > 1.0f ||
+ vtb_w < 0.0f || vtb_w > 1.0f;
+
+ const PxVec3 ntb = mapping.nrmTetraBary;
+ const float ntb_w = 1.0f - ntb.x - ntb.y - ntb.z;
+
+ const bool badNrm =
+ ntb.x < 0.0f || ntb.x > 1.0f ||
+ ntb.y < 0.0f || ntb.y > 1.0f ||
+ ntb.z < 0.0f || ntb.z > 1.0f ||
+ ntb_w < 0.0f || ntb_w > 1.0f;
+
+ if (!onlyBad || badVtx || badNrm)
+ {
+ PxVec3 vtx[3], nrm[3];
+ getNormalsAndVerticesForFace(vtx, nrm, mapping.faceIndex0, srcPM);
+
+ const TetraEncoding& tetEnc = tetraTable[mapping.tetraIndex];
+
+ const PxVec3 tv0 = vtx[0] + (tetEnc.sign[0] * nrm[0] * meshThickness);
+ const PxVec3 tv1 = vtx[1] + (tetEnc.sign[1] * nrm[1] * meshThickness);
+ const PxVec3 tv2 = vtx[2] + (tetEnc.sign[2] * nrm[2] * meshThickness);
+ const PxVec3 tv3 = vtx[tetEnc.lastVtxIdx] + (tetEnc.sign[3] * nrm[tetEnc.lastVtxIdx] * meshThickness);
+
+ const PxVec3 centroid = (tv0 + tv1 + tv2 + tv3) * 0.25f;
+ const PxVec3 graphicsPos = (vtb.x * tv0) + (vtb.y * tv1) + (vtb.z * tv2) + (vtb_w * tv3);
+ const PxVec3 graphicsNrm = (ntb.x * tv0) + (ntb.y * tv1) + (ntb.z * tv2) + (ntb_w * tv3);
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorYellow);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugPoint(graphicsPos, meshThickness * 0.1f);
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorBlue);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(graphicsPos, graphicsNrm);
+
+ if (badVtx && onlyBad)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorRed);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(centroid, graphicsPos);
+ }
+
+ if (badNrm && onlyBad)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorDarkRed);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(centroid, graphicsPos);
+ }
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(mapping.tetraIndex < 3 ? colorGreen : colorPurple);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(tv1, tv2);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(tv2, tv3);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(tv3, tv1);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(tv0, tv1);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(tv0, tv2);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(tv0, tv3);
+ }
+ }
+ }
+ else if ((skinClothMap != NULL) && (srcPM.pPosition != NULL) && (srcPM.pIndices != NULL) && (srcPM.pNormal != NULL))
+ {
+ const uint32_t colorWhite = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::White);
+ const uint32_t colorRed = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Red);
+ const uint32_t colorDarkRed = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::DarkRed);
+ const uint32_t colorBlue = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Blue);
+ const uint32_t colorYellow = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Yellow);
+ const uint32_t colorGreen = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Green);
+ const uint32_t colorPurple = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Purple);
+
+ for (uint32_t i = 0; i < skinClothMapSize; i++)
+ {
+ const SkinClothMap& mapping = skinClothMap[i];
+
+ if (mapping.vertexIndex0 >= srcPM.numVertices || mapping.vertexIndex1 >= srcPM.numVertices || mapping.vertexIndex2 >= srcPM.numVertices)
+ {
+ continue;
+ }
+
+ PxVec3 baryVtx = mapping.vertexBary;
+ const float heightVtx = baryVtx.z;
+ baryVtx.z = 1.0f - baryVtx.x - baryVtx.y;
+
+ PxVec3 baryNrm = mapping.normalBary;
+ const float heightNrm = baryNrm.z;
+ baryNrm.z = 1.0f - baryNrm.x - baryNrm.y;
+
+ bool badVtx =
+ baryVtx.x < 0.0f || baryVtx.x > 1.0f ||
+ baryVtx.y < 0.0f || baryVtx.y > 1.0f ||
+ baryVtx.z < 0.0f || baryVtx.z > 1.0f ||
+ heightVtx < -1.0f || heightVtx > 1.0f;
+
+ bool badNrm =
+ baryNrm.x < 0.0f || baryNrm.x > 1.0f ||
+ baryNrm.y < 0.0f || baryNrm.y > 1.0f ||
+ baryNrm.z < 0.0f || baryNrm.z > 1.0f ||
+ heightNrm < -1.0f || heightNrm > 1.0f;
+
+ if (!onlyBad || badVtx || badNrm)
+ {
+ uint32_t idx[3] =
+ {
+ mapping.vertexIndex0,
+ mapping.vertexIndex1,
+ mapping.vertexIndex2,
+ };
+
+ PxVec3 vtx[3], nrm[3];
+ PxVec3 centroid(0.0f);
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ vtx[j] = srcPM.pPosition[idx[j]];
+ nrm[j] = srcPM.pNormal[idx[j]] * meshThickness;
+ centroid += vtx[j];
+ }
+ centroid /= 3.0f;
+
+
+ uint32_t b = (uint32_t)(255 * i / skinClothMapSize);
+ uint32_t color = (b << 16) + (b << 8) + b;
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(color);
+
+ PxVec3 vertexBary = mapping.vertexBary;
+ float vertexHeight = vertexBary.z;
+ vertexBary.z = 1.0f - vertexBary.x - vertexBary.y;
+ const PxVec3 vertexPos = vertexBary.x * vtx[0] + vertexBary.y * vtx[1] + vertexBary.z * vtx[2];
+ const PxVec3 vertexNrm = vertexBary.x * nrm[0] + vertexBary.y * nrm[1] + vertexBary.z * nrm[2]; // meshThickness is already in
+ const PxVec3 graphicsPos = vertexPos + vertexNrm * vertexHeight;
+
+ if (invalidBary)
+ {
+ uint32_t invalidColor = 0;
+ invalidColor = vertexBary == PxVec3(PX_MAX_F32) ? colorRed : invalidColor;
+ invalidColor = mapping.normalBary == PxVec3(PX_MAX_F32) ? colorPurple : invalidColor;
+ invalidColor = mapping.tangentBary == PxVec3(PX_MAX_F32) ? colorBlue : invalidColor;
+
+ if (invalidColor != 0)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(invalidColor);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(vtx[0], vtx[1], vtx[2]);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugPoint(graphicsPos, meshThickness * 0.1f);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(centroid, graphicsPos);
+ }
+ continue;
+ }
+
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(centroid, graphicsPos);
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorYellow);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugPoint(graphicsPos, meshThickness * 0.1f);
+
+ if (badVtx && onlyBad)
+ {
+ // draw the projected position as well
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorRed);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(vertexPos, graphicsPos);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(vertexPos, centroid);
+ }
+
+ PxVec3 normalBary = mapping.normalBary;
+ float normalHeight = normalBary.z;
+ normalBary.z = 1.0f - normalBary.x - normalBary.y;
+ const PxVec3 normalPos = normalBary.x * vtx[0] + normalBary.y * vtx[1] + normalBary.z * vtx[2];
+ const PxVec3 normalNrm = normalBary.x * nrm[0] + normalBary.y * nrm[1] + normalBary.z * nrm[2]; // meshThickness is already in
+ const PxVec3 graphicsNrm = normalPos + normalNrm * normalHeight;
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorBlue);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(graphicsNrm, graphicsPos);
+#if 0
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Black));
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(graphicsNrm, centroid);
+#endif
+
+ if (badNrm && onlyBad)
+ {
+ // draw the projected normal as well
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorDarkRed);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(normalPos, graphicsNrm);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(normalPos, centroid);
+ }
+
+ // turn the rendering on for the rest
+ badVtx = badNrm = true;
+
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorWhite);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(vtx[0], vtx[1], vtx[2]);
+ if ((badVtx && heightVtx > 0.0f) || (badNrm && heightNrm > 0.0f))
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorGreen);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(vtx[0] + nrm[0], vtx[1] + nrm[1], vtx[2] + nrm[2]);
+ for (uint32_t u = 0; u < 3; u++)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(vtx[u], vtx[u] + nrm[u]);
+ }
+ }
+ else if ((badVtx && heightVtx < 0.0f) || (badNrm && heightNrm < 0.0f))
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorPurple);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugTri(vtx[0] - nrm[0], vtx[1] - nrm[1], vtx[2] - nrm[2]);
+ for (uint32_t u = 0; u < 3; u++)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(vtx[u], vtx[u] - nrm[u]);
+ }
+ }
+ }
+ }
+ }
+
+ RENDER_DEBUG_IFACE(&renderDebug)->popRenderState();
+#endif
+}
+
+
+
+void ClothingAssetImpl::visualizeBones(RenderDebugInterface& renderDebug, const PxMat44* matrices, bool skeleton, float boneFramesScale, float boneNamesScale)
+{
+#ifdef WITHOUT_DEBUG_VISUALIZE
+ PX_UNUSED(renderDebug);
+ PX_UNUSED(matrices);
+ PX_UNUSED(skeleton);
+ PX_UNUSED(boneFramesScale);
+ PX_UNUSED(boneNamesScale);
+#else
+
+ using RENDER_DEBUG::DebugColors;
+ using RENDER_DEBUG::DebugRenderState;
+
+ RENDER_DEBUG_IFACE(&renderDebug)->pushRenderState();
+
+ const uint32_t activeBoneColor = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Purple);
+ const uint32_t passiveBoneColor = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Blue);
+
+ const uint32_t colorWhite = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::White);
+ const uint32_t colorRed = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Red);
+ const uint32_t colorGreen = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Green);
+ const uint32_t colorBlue = RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::Blue);
+
+ RENDER_DEBUG_IFACE(&renderDebug)->addToCurrentState(RENDER_DEBUG::DebugRenderState::CenterText);
+ RENDER_DEBUG_IFACE(&renderDebug)->addToCurrentState(RENDER_DEBUG::DebugRenderState::CameraFacing);
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentTextScale(boneNamesScale);
+
+ if ((skeleton || boneFramesScale > 0.0f || boneNamesScale > 0.0f) && mPhysicalMeshes.size() > 0)
+ {
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type& physicalMesh = mPhysicalMeshes[0]->physicalMesh;
+ float sphereSize = 0.3f * physicalMesh.averageEdgeLength;
+ uint32_t rootIdx = mParams->rootBoneIndex;
+ PxMat44 absPose = matrices[rootIdx] * mBones[rootIdx].bindPose;
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::DarkRed));
+ RENDER_DEBUG_IFACE(&renderDebug)->debugSphere(absPose.getPosition(), sphereSize);
+ }
+
+ for (uint32_t i = 0; i < getNumUsedBones(); i++)
+ {
+ const int32_t parent = mBones[i].parentIndex;
+
+ PxMat44 absPose = matrices[i] * mBones[i].bindPose;
+
+ if (skeleton && parent >= 0 && parent < (int32_t)getNumUsedBones())
+ {
+ PX_ASSERT((uint32_t)parent != i);
+ PxMat44 absPoseParent = matrices[(uint32_t)parent] * mBones[(uint32_t)parent].bindPose;
+ if ((mBones[(uint32_t)parent].numMeshReferenced + mBones[(uint32_t)parent].numRigidBodiesReferenced) == 0)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(passiveBoneColor);
+ }
+ else
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(activeBoneColor);
+ }
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(absPose.getPosition(), absPoseParent.getPosition());
+ }
+
+ if (boneFramesScale > 0.0f)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorRed);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(absPose.getPosition(), absPose.getPosition() + absPose.column0.getXYZ() * boneFramesScale);
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorGreen);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(absPose.getPosition(), absPose.getPosition() + absPose.column1.getXYZ() * boneFramesScale);
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorBlue);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugLine(absPose.getPosition(), absPose.getPosition() + absPose.column2.getXYZ() * boneFramesScale);
+ }
+
+ if (boneNamesScale > 0.0f)
+ {
+ RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(colorWhite);
+ RENDER_DEBUG_IFACE(&renderDebug)->debugText(absPose.getPosition(), mBones[i].name.buf);
+ }
+ }
+
+ RENDER_DEBUG_IFACE(&renderDebug)->popRenderState();
+#endif
+}
+
+
+
+uint32_t ClothingAssetImpl::initializeAssetData(ClothingAssetData& assetData, const uint32_t uvChannel)
+{
+ //OK. Stage 1 - need to calculate the sizes required...
+
+ const uint32_t numLods = mGraphicalLods.size();
+ uint32_t numSubMeshes = 0;
+
+ for (uint32_t a = 0; a < numLods; ++a)
+ {
+ ClothingGraphicalMeshAssetWrapper meshAsset(reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[a]->renderMeshAssetPointer));
+ numSubMeshes += meshAsset.getSubmeshCount();
+ }
+
+ const uint32_t numPhysicalMeshes = mPhysicalMeshes.size();
+
+ const uint32_t requiredSize = ((sizeof(ClothingMeshAssetData) * numLods + sizeof(ClothingAssetSubMesh) * numSubMeshes
+ + sizeof(ClothingPhysicalMeshData) * numPhysicalMeshes) + 15) & 0xfffffff0;
+
+ void* data = PX_ALLOC(requiredSize, PX_DEBUG_EXP("ClothingAssetData"));
+ memset(data, 0, requiredSize);
+
+ assetData.mData = (uint8_t*)data;
+ assetData.mAssetSize = requiredSize;
+
+ //assetData.m_pLods = (ClothingMeshAssetData*)data;
+
+ assetData.mGraphicalLodsCount = numLods;
+
+ assetData.mRootBoneIndex = mParams->rootBoneIndex;
+
+ ClothingAssetSubMesh* pMeshes = (ClothingAssetSubMesh*)(((uint8_t*)data) + sizeof(ClothingMeshAssetData) * numLods);
+
+ uint32_t maxVertices = 0;
+
+ for (uint32_t a = 0; a < numLods; ++a)
+ {
+ ClothingGraphicalMeshAssetWrapper meshAsset(reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[a]->renderMeshAssetPointer));
+
+ const ClothingGraphicalLodParameters* graphicalLod = mGraphicalLods[a];
+
+ const uint32_t subMeshCount = meshAsset.getSubmeshCount();
+ ClothingMeshAssetData* pAsset = assetData.GetLod(a);
+ PX_PLACEMENT_NEW(pAsset, ClothingMeshAssetData());
+ //pAsset->m_pMeshes = pMeshes;
+ pAsset->mSubMeshCount = subMeshCount;
+
+ //Params to set
+ pAsset->mImmediateClothMap = graphicalLod->immediateClothMap.buf;
+ pAsset->mImmediateClothMapCount = (uint32_t)graphicalLod->immediateClothMap.arraySizes[0];
+
+
+ pAsset->mSkinClothMap = graphicalLod->skinClothMap.buf;
+ pAsset->mSkinClothMapCount = (uint32_t)graphicalLod->skinClothMap.arraySizes[0];
+
+ pAsset->mSkinClothMapB = graphicalLod->skinClothMapB.buf;
+ pAsset->mSkinClothMapBCount = (uint32_t)graphicalLod->skinClothMapB.arraySizes[0];
+
+ pAsset->mTetraMap = graphicalLod->tetraMap.buf;
+ pAsset->mTetraMapCount = (uint32_t)graphicalLod->tetraMap.arraySizes[0];
+
+ pAsset->mPhysicalMeshId = graphicalLod->physicalMeshId;
+
+ pAsset->mSkinClothMapThickness = graphicalLod->skinClothMapThickness;
+ pAsset->mSkinClothMapOffset = graphicalLod->skinClothMapOffset;
+
+ pAsset->mBounds = mParams->boundingBox;
+
+ //For now - we'll set this outside again
+ pAsset->bActive = true;
+
+ pAsset->mSubmeshOffset = (uint32_t)((uint8_t*)pMeshes - assetData.mData);
+
+ for (uint32_t b = 0; b < subMeshCount; ++b)
+ {
+ PX_PLACEMENT_NEW(&pMeshes[b], ClothingAssetSubMesh());
+
+ RenderDataFormat::Enum outFormat;
+ pMeshes[b].mPositions = (const PxVec3*)meshAsset.getVertexBuffer(b, RenderVertexSemantic::POSITION, outFormat);
+ pMeshes[b].mPositionOutFormat = outFormat;
+ pMeshes[b].mNormals = (const PxVec3*)meshAsset.getVertexBuffer(b, RenderVertexSemantic::NORMAL, outFormat);
+ pMeshes[b].mNormalOutFormat = outFormat;
+
+ pMeshes[b].mTangents = (const PxVec4*)meshAsset.getVertexBuffer(b, RenderVertexSemantic::TANGENT, outFormat);
+ pMeshes[b].mTangentOutFormat = outFormat;
+ PX_ASSERT(((size_t)pMeshes[b].mTangents & 0xf) == 0);
+
+ pMeshes[b].mBoneWeights = (const float*)meshAsset.getVertexBuffer(b, RenderVertexSemantic::BONE_WEIGHT, outFormat);
+ pMeshes[b].mBoneWeightOutFormat = outFormat;
+ pMeshes[b].mBoneIndices = (const uint16_t*)meshAsset.getVertexBuffer(b, RenderVertexSemantic::BONE_INDEX, outFormat);
+ pMeshes[b].mVertexCount = meshAsset.getNumVertices(b);
+ pMeshes[b].mNumBonesPerVertex = meshAsset.getNumBonesPerVertex(b);
+
+ maxVertices = PxMax(maxVertices, meshAsset.getNumVertices(b));
+
+ pMeshes[b].mIndices = (const uint32_t*)meshAsset.getIndexBuffer(b);
+ pMeshes[b].mIndicesCount = meshAsset.getNumIndices(b);
+
+ const VertexUV* PX_RESTRICT uvs = NULL;
+ RenderDataFormat::Enum uvFormat = RenderDataFormat::UNSPECIFIED;
+ switch (uvChannel)
+ {
+ case 0:
+ uvs = (const VertexUV*)meshAsset.getVertexBuffer(b, RenderVertexSemantic::TEXCOORD0, uvFormat);
+ break;
+ case 1:
+ uvs = (const VertexUV*)meshAsset.getVertexBuffer(b, RenderVertexSemantic::TEXCOORD1, uvFormat);
+ break;
+ case 2:
+ uvs = (const VertexUV*)meshAsset.getVertexBuffer(b, RenderVertexSemantic::TEXCOORD2, uvFormat);
+ break;
+ case 3:
+ uvs = (const VertexUV*)meshAsset.getVertexBuffer(b, RenderVertexSemantic::TEXCOORD3, uvFormat);
+ break;
+ }
+
+ pMeshes[b].mUvs = (VertexUVLocal*)uvs;
+ pMeshes[b].mUvFormat = uvFormat;
+ }
+ pMeshes += subMeshCount;
+ }
+
+
+ ClothingPhysicalMeshData* pPhysicalMeshes = (ClothingPhysicalMeshData*)pMeshes;
+
+ assetData.mPhysicalMeshOffset = (uint32_t)((uint8_t*)pMeshes - assetData.mData);
+
+ for (uint32_t a = 0; a < numPhysicalMeshes; ++a)
+ {
+ ClothingPhysicalMeshData* pPhysicalMesh = &pPhysicalMeshes[a];
+ PX_PLACEMENT_NEW(pPhysicalMesh, ClothingPhysicalMeshData);
+
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = getPhysicalMeshFromLod(a);
+ ClothingPhysicalMeshParameters* pPhysicalMeshParams = mPhysicalMeshes[a];
+ PX_UNUSED(pPhysicalMeshParams);
+
+ pPhysicalMesh->mVertices = physicalMesh->vertices.buf;
+ pPhysicalMesh->mVertexCount = physicalMesh->numVertices;
+ pPhysicalMesh->mSimulatedVertexCount = physicalMesh->numSimulatedVertices;
+ pPhysicalMesh->mMaxDistance0VerticesCount = physicalMesh->numMaxDistance0Vertices;
+
+ pPhysicalMesh->mNormals = physicalMesh->normals.buf;
+ pPhysicalMesh->mSkinningNormals = physicalMesh->skinningNormals.buf;
+ pPhysicalMesh->mSkinningNormalsCount = (uint32_t)physicalMesh->skinningNormals.arraySizes[0];
+ pPhysicalMesh->mNumBonesPerVertex = physicalMesh->numBonesPerVertex;
+
+ pPhysicalMesh->mBoneIndices = physicalMesh->boneIndices.buf;
+ pPhysicalMesh->mBoneWeights = physicalMesh->boneWeights.buf;
+ PX_ASSERT(physicalMesh->boneIndices.arraySizes[0] == physicalMesh->boneWeights.arraySizes[0]);
+ pPhysicalMesh->mBoneWeightsCount = (uint32_t)physicalMesh->boneWeights.arraySizes[0];
+
+ pPhysicalMesh->mOptimizationData = physicalMesh->optimizationData.buf;
+ pPhysicalMesh->mOptimizationDataCount = (uint32_t)physicalMesh->optimizationData.arraySizes[0];
+
+ pPhysicalMesh->mIndices = physicalMesh->indices.buf;
+ pPhysicalMesh->mIndicesCount = (uint32_t)physicalMesh->indices.arraySizes[0];
+ pPhysicalMesh->mSimulatedIndicesCount = physicalMesh->numSimulatedIndices;
+ }
+
+ //Initialized compressed num bones per vertex...
+ mCompressedNumBonesPerVertexMutex.lock();
+ if (mCompressedNumBonesPerVertex.empty())
+ {
+ initializeCompressedNumBonesPerVertex();
+ }
+ mCompressedNumBonesPerVertexMutex.unlock();
+
+ assetData.mCompressedNumBonesPerVertexCount = mCompressedNumBonesPerVertex.size();
+ assetData.mCompressedNumBonesPerVertex = assetData.mCompressedNumBonesPerVertexCount > 0 ? &(mCompressedNumBonesPerVertex.front()) : NULL;
+
+ assetData.mCompressedTangentWCount = mCompressedTangentW.size();
+ assetData.mCompressedTangentW = assetData.mCompressedTangentWCount > 0 ? &(mCompressedTangentW.front()) : NULL;
+
+ assetData.mPhysicalMeshesCount = mPhysicalMeshes.size();
+ assetData.mExt2IntMorphMappingCount = mExt2IntMorphMapping.size();
+ if (mExt2IntMorphMapping.size())
+ {
+ assetData.mExt2IntMorphMapping = &(mExt2IntMorphMapping.front());
+ }
+ else
+ {
+ assetData.mExt2IntMorphMapping = NULL;
+ }
+
+ assetData.mBoneCount = mBones.size();
+
+ return maxVertices;
+
+}
+
+
+
+const RenderMeshAsset* ClothingAssetImpl::getRenderMeshAsset(uint32_t lodLevel) const
+{
+ READ_ZONE();
+
+ if (lodLevel < mGraphicalLods.size())
+ {
+ return reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[lodLevel]->renderMeshAssetPointer);
+ }
+
+ return NULL;
+}
+
+
+
+uint32_t ClothingAssetImpl::getMeshSkinningMapSize(uint32_t lod)
+{
+ WRITE_ZONE();
+ if (lod >= mGraphicalLods.size())
+ {
+ APEX_INVALID_PARAMETER("lod %i not a valid lod level. There are only %i graphical lods.", lod, mGraphicalLods.size());
+ return 0;
+ }
+ ClothingGraphicalLodParameters* graphicalLod = mGraphicalLods[lod];
+
+ // make sure everything can be skinned using the skinClothMap,
+ // so the user doesn't have to care about immediate skinning as well
+ mergeMapping(graphicalLod);
+
+ return (uint32_t)mGraphicalLods[lod]->skinClothMap.arraySizes[0];
+}
+
+
+
+void ClothingAssetImpl::getMeshSkinningMap(uint32_t lod, ClothingMeshSkinningMap* map)
+{
+ WRITE_ZONE();
+
+ if (lod >= mGraphicalLods.size())
+ {
+ APEX_INVALID_PARAMETER("lod %i not a valid lod level. There are only %i graphical lods.", lod, mGraphicalLods.size());
+ return;
+ }
+ ClothingGraphicalLodParameters* graphicalLod = mGraphicalLods[lod];
+
+ // make sure everything can be skinned using the skinClothMap,
+ // so the user doesn't have to care about immediate skinning as well
+ mergeMapping(graphicalLod);
+
+ PX_ASSERT(graphicalLod->skinClothMapOffset > 0.0f); // skinClothMapOffset would only be needed if it's negative, but it's not expected to be
+
+ // copy the values
+ int32_t size = mGraphicalLods[lod]->skinClothMap.arraySizes[0];
+ for (int32_t i = 0; i < size; ++i)
+ {
+ const SkinClothMap& skinMap = mGraphicalLods[lod]->skinClothMap.buf[i];
+ map[i].positionBary = skinMap.vertexBary;
+ map[i].vertexIndex0 = skinMap.vertexIndex0;
+ map[i].normalBary = skinMap.normalBary;
+ map[i].vertexIndex1 = skinMap.vertexIndex1;
+ map[i].tangentBary = skinMap.tangentBary;
+ map[i].vertexIndex2 = skinMap.vertexIndex2;
+ }
+}
+
+
+
+bool ClothingAssetImpl::releaseGraphicalData()
+{
+ WRITE_ZONE();
+ bool ok = true;
+ for (uint32_t i = 0; i < mGraphicalLods.size(); ++i)
+ {
+ if (mGraphicalLods[i]->skinClothMapB.arraySizes[0] > 0 || mGraphicalLods[i]->tetraMap.arraySizes[0] > 0)
+ {
+ APEX_DEBUG_WARNING("Asset contains data that is not supported for external skinning, graphical data cannot be released. Reexport the asset with a newer APEX version.");
+ ok = false;
+ }
+
+ if (mGraphicalLods[i]->immediateClothMap.arraySizes[0] > 0)
+ {
+ APEX_DEBUG_WARNING("Asset contains immediate map data, graphical data cannot be released. Call getMeshSkinningMap first.");
+ ok = false;
+ }
+ }
+
+ if (mActors.getSize() > 0)
+ {
+ APEX_DEBUG_WARNING("Graphical data in asset cannot be released while there are actors of this asset.");
+ ok = false;
+ }
+
+ if (ok)
+ {
+ mModule->notifyReleaseGraphicalData(this);
+
+ for (uint32_t i = 0; i < mGraphicalLods.size(); ++i)
+ {
+ if (mGraphicalLods[i]->renderMeshAssetPointer != NULL)
+ {
+ RenderMeshAssetIntl* rma = reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[i]->renderMeshAssetPointer);
+ rma->release();
+ mGraphicalLods[i]->renderMeshAssetPointer = NULL;
+
+ mGraphicalLods[i]->renderMeshAsset->destroy();
+ mGraphicalLods[i]->renderMeshAsset = NULL;
+ }
+
+ ParamArray<SkinClothMap> skinClothMap(mGraphicalLods[i], "skinClothMap",
+ reinterpret_cast<ParamDynamicArrayStruct*>(&mGraphicalLods[i]->skinClothMap));
+ skinClothMap.clear();
+ }
+ }
+
+ return ok;
+}
+
+
+
+void ClothingAssetImpl::setupInvBindMatrices()
+{
+ if (mInvBindPoses.size() == mBones.size())
+ {
+ return;
+ }
+
+ mInvBindPoses.resize(mBones.size());
+ for (uint32_t i = 0; i < mBones.size(); i++)
+ {
+ mInvBindPoses[i] = mBones[i].bindPose.inverseRT();
+ }
+}
+
+
+
+void ClothingAssetImpl::prepareCookingJob(CookingAbstract& job, float scale, PxVec3* gravityDirection, PxVec3* morphedPhysicalMesh)
+{
+ PxVec3* tempVerticesForScale = NULL;
+ uint32_t tempVerticesOffset = 0;
+ if (scale != 1.0f || morphedPhysicalMesh != NULL)
+ {
+ uint32_t numMaxVertices = 0;
+ for (uint32_t physicalMeshId = 0; physicalMeshId < mPhysicalMeshes.size(); physicalMeshId++)
+ {
+ numMaxVertices += mPhysicalMeshes[physicalMeshId]->physicalMesh.numVertices;
+ }
+ numMaxVertices += mBoneVertices.size();
+
+ tempVerticesForScale = (PxVec3*)PX_ALLOC(sizeof(PxVec3) * numMaxVertices, PX_DEBUG_EXP("tempVerticesForScale"));
+ PX_ASSERT(tempVerticesForScale != NULL);
+
+ for (uint32_t physicalMeshId = 0; physicalMeshId < mPhysicalMeshes.size(); physicalMeshId++)
+ {
+ const uint32_t numVertices = mPhysicalMeshes[physicalMeshId]->physicalMesh.numVertices;
+ PxVec3* origVertices = morphedPhysicalMesh != NULL ? morphedPhysicalMesh + tempVerticesOffset : mPhysicalMeshes[physicalMeshId]->physicalMesh.vertices.buf;
+ PxVec3* tempVertices = tempVerticesForScale + tempVerticesOffset;
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ tempVertices[i] = origVertices[i] * scale;
+ }
+ tempVerticesOffset += numVertices;
+ }
+ }
+
+ tempVerticesOffset = 0;
+
+ for (uint32_t physicalMeshId = 0; physicalMeshId < mPhysicalMeshes.size(); physicalMeshId++)
+ {
+ CookingAbstract::PhysicalMesh physicalMesh;
+ physicalMesh.meshID = physicalMeshId;
+ if (tempVerticesForScale != NULL)
+ {
+ physicalMesh.vertices = tempVerticesForScale + tempVerticesOffset;
+ }
+ else
+ {
+ physicalMesh.vertices = mPhysicalMeshes[physicalMeshId]->physicalMesh.vertices.buf;
+ }
+ physicalMesh.numVertices = mPhysicalMeshes[physicalMeshId]->physicalMesh.numVertices;
+ physicalMesh.numSimulatedVertices = mPhysicalMeshes[physicalMeshId]->physicalMesh.numSimulatedVertices;
+ physicalMesh.numMaxDistance0Vertices = mPhysicalMeshes[physicalMeshId]->physicalMesh.numMaxDistance0Vertices;
+ physicalMesh.indices = mPhysicalMeshes[physicalMeshId]->physicalMesh.indices.buf;
+ physicalMesh.numIndices = mPhysicalMeshes[physicalMeshId]->physicalMesh.numIndices;
+ physicalMesh.numSimulatedIndices = mPhysicalMeshes[physicalMeshId]->physicalMesh.numSimulatedIndices;
+ physicalMesh.isTetrahedral = mPhysicalMeshes[physicalMeshId]->physicalMesh.isTetrahedralMesh;
+
+ job.addPhysicalMesh(physicalMesh);
+
+ tempVerticesOffset += physicalMesh.numVertices;
+ }
+
+ if (tempVerticesForScale == NULL)
+ {
+ // verify that there are no invalid matrices
+ for (uint32_t i = 0; i < mBoneActors.size(); i++)
+ {
+ if (mBoneActors[i].capsuleRadius > 0.0f || mBoneActors[i].convexVerticesCount == 0)
+ {
+ continue;
+ }
+
+ uint32_t boneIndex = (uint32_t)mBoneActors[i].boneIndex;
+
+ const PxMat44& bpm44 = mBones[boneIndex].bindPose;
+ const PxMat44& lpm44 = mBoneActors[i].localPose;
+ const PxMat33 bpm33(bpm44.column0.getXYZ(),
+ bpm44.column1.getXYZ(),
+ bpm44.column2.getXYZ()),
+ lpm33(lpm44.column0.getXYZ(),
+ lpm44.column1.getXYZ(),
+ lpm44.column2.getXYZ());
+
+ const float det = bpm33.getDeterminant() * lpm33.getDeterminant();
+ if (det < 0.0f)
+ {
+ // invalid matrices found, need to use temporary buffer only for bone vertices now
+ tempVerticesForScale = (PxVec3*)GetInternalApexSDK()->getTempMemory(sizeof(PxVec3) * mBoneVertices.size());
+ PX_ASSERT(tempVerticesOffset == 0);
+ break;
+ }
+ }
+ }
+
+ if (tempVerticesForScale != NULL)
+ {
+ memset(tempVerticesForScale + tempVerticesOffset, 0xff, sizeof(PxVec3) * mBoneVertices.size());
+
+ PxVec3* boneVertices = morphedPhysicalMesh != NULL ? morphedPhysicalMesh + tempVerticesOffset : mBoneVertices.begin();
+
+ for (uint32_t i = 0; i < mBoneActors.size(); i++)
+ {
+ uint32_t boneIndex = (uint32_t)mBoneActors[i].boneIndex;
+ const PxMat44 bpm44(mBones[boneIndex].bindPose),
+ lpm44(mBoneActors[i].localPose);
+ const PxMat33 bpm33(bpm44.column0.getXYZ(),
+ bpm44.column1.getXYZ(),
+ bpm44.column2.getXYZ()),
+ lpm33(lpm44.column0.getXYZ(),
+ lpm44.column1.getXYZ(),
+ lpm44.column2.getXYZ());
+
+ const float det = bpm33.getDeterminant() * lpm33.getDeterminant();
+ for (uint32_t j = 0; j < mBoneActors[i].convexVerticesCount; j++)
+ {
+ uint32_t boneVertexIndex = mBoneActors[i].convexVerticesStart + j;
+ PxVec3 val = boneVertices[boneVertexIndex] * scale;
+ if (det < 0.0f)
+ {
+ val.z = -val.z;
+ }
+
+ tempVerticesForScale[boneVertexIndex + tempVerticesOffset] = val;
+ }
+ }
+
+ for (uint32_t i = 0; i < mBoneVertices.size(); i++)
+ {
+ PX_ASSERT(tempVerticesForScale[i + tempVerticesOffset].isFinite());
+ }
+ }
+
+ PxVec3* boneVertices = tempVerticesForScale != NULL ? tempVerticesForScale + tempVerticesOffset : mBoneVertices.begin();
+ job.setConvexBones(mBoneActors.begin(), mBoneActors.size(), mBones.begin(), mBones.size(), boneVertices, 256);
+
+ job.setScale(scale);
+ job.setVirtualParticleDensity(mParams->simulation.virtualParticleDensity);
+
+ if (mParams->materialLibrary != NULL)
+ {
+ ClothingMaterialLibraryParameters* matLib = static_cast<ClothingMaterialLibraryParameters*>(mParams->materialLibrary);
+ float selfcollisionThickness = matLib->materials.buf[mParams->materialIndex].selfcollisionThickness;
+ job.setSelfcollisionRadius(selfcollisionThickness);
+ }
+
+ PxVec3 gravityDir = mParams->simulation.gravityDirection;
+ if (gravityDir.isZero() && gravityDirection != NULL)
+ {
+ gravityDir = *gravityDirection;
+ }
+ if (gravityDir.isZero())
+ {
+ APEX_DEBUG_WARNING("(%s) Gravity direction is zero. Impossible to extract vertical- and zero-stretch fibers.", mName.c_str());
+ }
+ job.setGravityDirection(gravityDir);
+
+ job.freeTempMemoryWhenDone(tempVerticesForScale);
+}
+
+
+
+uint32_t* ClothingAssetImpl::getMorphMapping(uint32_t graphicalLod, uint32_t submeshIndex)
+{
+ if (mExt2IntMorphMapping.empty())
+ {
+ if (!mMorphMappingWarning)
+ {
+ APEX_INVALID_OPERATION("A clothing actor with morph displacements was specified, but the Asset <%s> was not prepared for morph displacements", mName.c_str());
+ mMorphMappingWarning = true;
+ }
+ return NULL;
+ }
+
+ if (graphicalLod == (uint32_t) - 1 || graphicalLod > mGraphicalLods.size())
+ {
+ graphicalLod = mGraphicalLods.size();
+ }
+
+ uint32_t offset = 0;
+ for (uint32_t i = 0; i < graphicalLod; i++)
+ {
+ RenderMeshAssetIntl* rma = getGraphicalMesh(i);
+ if (rma == NULL)
+ continue;
+
+ for (uint32_t s = 0; s < rma->getSubmeshCount(); s++)
+ {
+ offset += rma->getSubmesh(s).getVertexCount(0);
+ }
+ }
+
+
+ RenderMeshAssetIntl* rma = getGraphicalMesh(graphicalLod);
+ if (rma != NULL)
+ {
+ PX_ASSERT(submeshIndex < rma->getSubmeshCount());
+ submeshIndex = PxMin(submeshIndex, rma->getSubmeshCount());
+
+ for (uint32_t i = 0; i < submeshIndex; ++i)
+ {
+ offset += rma->getSubmesh(i).getVertexCount(0);
+ }
+ }
+
+ return mExt2IntMorphMapping.begin() + offset;
+}
+
+
+
+uint32_t ClothingAssetImpl::getPhysicalMeshOffset(uint32_t physicalMeshId)
+{
+ physicalMeshId = PxMin(physicalMeshId, mPhysicalMeshes.size());
+
+ uint32_t result = 0;
+
+ for (uint32_t i = 0; i < physicalMeshId; i++)
+ {
+ result += mPhysicalMeshes[i]->physicalMesh.numVertices;
+ }
+
+ return result;
+}
+
+
+
+class SkinClothMapFacePredicate
+{
+public:
+ bool operator()(const SkinClothMapB& map1, const SkinClothMapB& map2) const
+ {
+ if (map1.submeshIndex < map2.submeshIndex)
+ {
+ return true;
+ }
+ else if (map1.submeshIndex > map2.submeshIndex)
+ {
+ return false;
+ }
+
+ return map1.faceIndex0 < map2.faceIndex0;
+ }
+};
+
+
+
+class SkinClothMapBVertexPredicate
+{
+public:
+ bool operator()(const SkinClothMapB& map1, const SkinClothMapB& map2) const
+ {
+ return map1.vertexIndexPlusOffset < map2.vertexIndexPlusOffset;
+ }
+};
+
+
+
+void ClothingAssetImpl::getDisplacedPhysicalMeshPositions(PxVec3* morphDisplacements, ParamArray<PxVec3> displacedMeshPositions)
+{
+ uint32_t numPhysicalVertices = getPhysicalMeshOffset((uint32_t) - 1);
+ numPhysicalVertices += mBoneVertices.size();
+
+ if (numPhysicalVertices == 0)
+ {
+ displacedMeshPositions.clear();
+ return;
+ }
+
+ displacedMeshPositions.resize(numPhysicalVertices);
+ memset(displacedMeshPositions.begin(), 0, sizeof(PxVec3) * numPhysicalVertices);
+ float* resultWeights = (float*)PX_ALLOC(sizeof(float) * numPhysicalVertices, PX_DEBUG_EXP("ClothingAssetImpl::getDisplacedPhysicalMeshPositions"));
+ memset(resultWeights, 0, sizeof(float) * numPhysicalVertices);
+
+ uint32_t resultOffset = 0;
+ for (uint32_t pm = 0; pm < mPhysicalMeshes.size(); pm++)
+ {
+ uint32_t gm = 0;
+ for (; gm < mGraphicalLods.size(); gm++)
+ {
+ if (mGraphicalLods[gm]->physicalMeshId == pm)
+ {
+ break;
+ }
+ }
+
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type& physicalMesh = mPhysicalMeshes[pm]->physicalMesh;
+
+ if (gm < mGraphicalLods.size())
+ {
+ const ClothingGraphicalLodParameters* graphicalLod = mGraphicalLods[gm];
+
+ const RenderMeshAsset* rma = getRenderMeshAsset(gm);
+ uint32_t* morphMapping = getMorphMapping(gm, 0);
+ uint32_t morphOffset = 0;
+
+ AbstractMeshDescription pMesh;
+ pMesh.pIndices = physicalMesh.indices.buf;
+ pMesh.numIndices = physicalMesh.numIndices;
+ pMesh.pPosition = physicalMesh.vertices.buf;
+
+ if (graphicalLod->immediateClothMap.buf == NULL && graphicalLod->skinClothMapB.buf != NULL)
+ {
+ // PH: Need to resort the skinMapB buffer to vertex order, will resort back to face order just below
+ sort<SkinClothMapB, SkinClothMapBVertexPredicate>(graphicalLod->skinClothMapB.buf, (uint32_t)graphicalLod->skinClothMapB.arraySizes[0], SkinClothMapBVertexPredicate());
+ }
+
+ for (uint32_t submeshIndex = 0; submeshIndex < rma->getSubmeshCount(); submeshIndex++)
+ {
+ const RenderSubmesh& submesh = rma->getSubmesh(submeshIndex);
+
+ const uint32_t vertexCount = submesh.getVertexCount(0);
+ for (uint32_t vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++)
+ {
+ const PxVec3 displacement = morphMapping != NULL ? morphDisplacements[morphMapping[morphOffset + vertexIndex]] : PxVec3(0.0f);
+
+ uint32_t indices[4];
+ float weight[4];
+
+ uint32_t numIndices = getCorrespondingPhysicalVertices(*graphicalLod, submeshIndex, vertexIndex, pMesh, morphOffset, indices, weight);
+
+ for (uint32_t i = 0; i < numIndices; i++)
+ {
+ weight[i] += 0.001f; // none of the weights is 0!
+ PX_ASSERT(weight[i] > 0.0f);
+ PX_ASSERT(indices[i] < pMesh.numIndices);
+ displacedMeshPositions[resultOffset + indices[i]] += (displacement + pMesh.pPosition[indices[i]]) * weight[i];
+ resultWeights[resultOffset + indices[i]] += weight[i];
+ }
+ }
+
+ morphOffset += vertexCount;
+ }
+
+ if (graphicalLod->immediateClothMap.buf == NULL && graphicalLod->skinClothMapB.buf != NULL)
+ {
+ nvidia::sort<SkinClothMapB, SkinClothMapFacePredicate>(graphicalLod->skinClothMapB.buf, (uint32_t)graphicalLod->skinClothMapB.arraySizes[0], SkinClothMapFacePredicate());
+ }
+
+ for (uint32_t i = 0; i < physicalMesh.numVertices; i++)
+ {
+ const uint32_t resultIndex = i + resultOffset;
+ if (resultWeights[resultIndex] > 0.0f)
+ {
+ displacedMeshPositions[resultIndex] /= resultWeights[resultIndex];
+ }
+ else
+ {
+ morphOffset = 0;
+ const PxVec3 physicsPosition = pMesh.pPosition[i];
+ float shortestDistance = PX_MAX_F32;
+ for (uint32_t submeshIndex = 0; submeshIndex < rma->getSubmeshCount() && shortestDistance > 0.0f; submeshIndex++)
+ {
+ const RenderSubmesh& submesh = rma->getSubmesh(submeshIndex);
+
+ const VertexFormat& format = submesh.getVertexBuffer().getFormat();
+ uint32_t positionIndex = (uint32_t)format.getBufferIndexFromID(format.getSemanticID(RenderVertexSemantic::POSITION));
+ PX_ASSERT(format.getBufferFormat(positionIndex) == RenderDataFormat::FLOAT3);
+ PxVec3* positions = (PxVec3*)submesh.getVertexBuffer().getBuffer(positionIndex);
+
+
+ const uint32_t vertexCount = submesh.getVertexCount(0);
+ for (uint32_t vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++)
+ {
+ float dist2 = (physicsPosition - positions[vertexIndex]).magnitudeSquared();
+ if (dist2 < shortestDistance)
+ {
+ shortestDistance = dist2;
+ displacedMeshPositions[resultIndex] = physicsPosition + morphDisplacements[morphMapping[morphOffset + vertexIndex]];
+ if (dist2 == 0.0f)
+ {
+ break;
+ }
+ }
+ }
+ morphOffset += submesh.getVertexCount(0);
+ }
+ }
+ }
+ }
+
+ resultOffset += physicalMesh.numVertices;
+ }
+
+ PX_FREE(resultWeights);
+ resultWeights = NULL;
+
+ for (uint32_t ba = 0; ba < mBoneActors.size(); ba++)
+ {
+
+ for (uint32_t bi = 0; bi < mBoneActors[ba].convexVerticesCount; bi++)
+ {
+ uint32_t boneIndex = bi + mBoneActors[ba].convexVerticesStart;
+ PX_ASSERT(mBoneActors[ba].localPose == PxMat44(PxIdentity));
+ const PxMat44 bindPose = mBones[(uint32_t)mBoneActors[ba].boneIndex].bindPose;
+ const PxVec3 physicsPosition = bindPose.transform(mBoneVertices[boneIndex]);
+ PxVec3 resultPosition(0.0f);
+
+ float shortestDistance = PX_MAX_F32;
+ for (uint32_t gm = 0; gm < mGraphicalLods.size() && shortestDistance > 0.0f; gm++)
+ {
+ const RenderMeshAsset* rma = getRenderMeshAsset(gm);
+ uint32_t* morphMapping = getMorphMapping(gm, 0);
+ uint32_t morphOffset = 0;
+
+ for (uint32_t submeshIndex = 0; submeshIndex < rma->getSubmeshCount() && shortestDistance > 0.0f; submeshIndex++)
+ {
+ const RenderSubmesh& submesh = rma->getSubmesh(submeshIndex);
+
+ const VertexFormat& format = submesh.getVertexBuffer().getFormat();
+ uint32_t positionIndex = (uint32_t)format.getBufferIndexFromID(format.getSemanticID(RenderVertexSemantic::POSITION));
+ PX_ASSERT(format.getBufferFormat(positionIndex) == RenderDataFormat::FLOAT3);
+ PxVec3* positions = (PxVec3*)submesh.getVertexBuffer().getBuffer(positionIndex);
+
+
+ const uint32_t vertexCount = submesh.getVertexCount(0);
+ for (uint32_t vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++)
+ {
+ float dist2 = (physicsPosition - positions[vertexIndex]).magnitudeSquared();
+ if (dist2 < shortestDistance)
+ {
+ shortestDistance = dist2;
+ resultPosition = physicsPosition + morphDisplacements[morphMapping[morphOffset + vertexIndex]];
+ if (dist2 == 0.0f)
+ {
+ break;
+ }
+ }
+ }
+ morphOffset += submesh.getVertexCount(0);
+ }
+ }
+
+ PxMat33 invBindPose(bindPose.column0.getXYZ(), bindPose.column1.getXYZ(), bindPose.column2.getXYZ());
+ invBindPose = invBindPose.getInverse();
+ displacedMeshPositions[resultOffset + boneIndex] = invBindPose.transform(resultPosition) + invBindPose.transform(-bindPose.getPosition());
+ }
+ }
+ resultOffset += mBoneVertices.size();
+
+
+ PX_ASSERT(resultOffset == numPhysicalVertices);
+}
+
+
+
+void ClothingAssetImpl::initializeCompressedNumBonesPerVertex()
+{
+ // PH: Merged the tangent w into this code, can be done at the same time
+ uint32_t numBonesElementCount = 0;
+ uint32_t numTangentElementCount = 0;
+ for (uint32_t lodIndex = 0; lodIndex < mGraphicalLods.size(); lodIndex++)
+ {
+ ClothingGraphicalMeshAssetWrapper meshAsset(reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[lodIndex]->renderMeshAssetPointer));
+
+ for (uint32_t submeshIdx = 0; submeshIdx < meshAsset.getSubmeshCount(); submeshIdx++)
+ {
+ const uint32_t numVertices = meshAsset.getNumVertices(submeshIdx);
+
+ // 3 bits per entry, 10 entries per U32
+ uint32_t numBoneEntries = (numVertices + 15) / 16;
+
+ RenderDataFormat::Enum outFormat = RenderDataFormat::UNSPECIFIED;
+ const PxVec4* PX_RESTRICT tangents = (const PxVec4*)meshAsset.getVertexBuffer(submeshIdx, RenderVertexSemantic::TANGENT, outFormat);
+ PX_ASSERT(tangents == NULL || outFormat == RenderDataFormat::FLOAT4);
+
+ uint32_t numTangentEntries = tangents != NULL ? (numVertices + 31) / 32 : 0;
+
+ // Round up such that map for all submeshes is 16 byte aligned
+ while ((numBoneEntries & 0x3) != 0) // this is a numEntries % 4
+ {
+ numBoneEntries++;
+ }
+
+ while ((numTangentEntries & 0x3) != 0)
+ {
+ numTangentEntries++;
+ }
+
+ numBonesElementCount += numBoneEntries;
+ numTangentElementCount += numTangentEntries;
+ }
+ }
+
+ if (numBonesElementCount > 0)
+ {
+ mCompressedNumBonesPerVertex.resize(numBonesElementCount, 0);
+
+ uint32_t numNonNormalizedVertices = 0;
+ uint32_t numInefficientVertices = 0;
+
+ uint32_t* bonesPerVertex = mCompressedNumBonesPerVertex.begin();
+ for (uint32_t lodIndex = 0; lodIndex < mGraphicalLods.size(); lodIndex++)
+ {
+ ClothingGraphicalMeshAssetWrapper meshAsset(reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[lodIndex]->renderMeshAssetPointer));
+
+ for (uint32_t submeshIdx = 0; submeshIdx < meshAsset.getSubmeshCount(); submeshIdx++)
+ {
+ uint32_t numVerticesWritten = 0;
+
+ RenderDataFormat::Enum outFormat = RenderDataFormat::UNSPECIFIED;
+ const float* PX_RESTRICT boneWeights = (const float*)meshAsset.getVertexBuffer(submeshIdx, RenderVertexSemantic::BONE_WEIGHT, outFormat);
+
+ const uint32_t numVertices = meshAsset.getNumVertices(submeshIdx);
+ const uint32_t numBonesPerVertex = meshAsset.getNumBonesPerVertex(submeshIdx);
+ PX_ASSERT((numBonesPerVertex > 0) == (boneWeights != NULL));
+
+ PX_ASSERT(((size_t)bonesPerVertex & 0xf) == 0); // make sure we start 16 byte aligned
+ for (uint32_t vertexIndex = 0; vertexIndex < numVertices; vertexIndex++)
+ {
+ uint32_t firstZeroBoneAfter = 0;
+ if (boneWeights != NULL)
+ {
+ const float* PX_RESTRICT vertexBoneWeights = boneWeights + (vertexIndex * numBonesPerVertex);
+ uint32_t firstZeroBone = numBonesPerVertex;
+ float sumWeights = 0.0f;
+ for (uint32_t k = 0; k < numBonesPerVertex; k++)
+ {
+ sumWeights += vertexBoneWeights[k];
+ if (vertexBoneWeights[k] == 0.0f)
+ {
+ firstZeroBone = PxMin(firstZeroBone, k);
+ }
+ else
+ {
+ firstZeroBoneAfter = k + 1;
+ }
+ }
+ PX_ASSERT(firstZeroBoneAfter <= numBonesPerVertex);
+
+ numNonNormalizedVertices += PxAbs(sumWeights - 1.0f) > 0.001f ? 1 : 0;
+ numInefficientVertices += firstZeroBone < firstZeroBoneAfter ? 1 : 0;
+ }
+ else
+ {
+ firstZeroBoneAfter = 1;
+ }
+
+ // write the value
+ if (numVerticesWritten == 16)
+ {
+ bonesPerVertex++;
+ numVerticesWritten = 0;
+ }
+
+ PX_ASSERT(firstZeroBoneAfter > 0);
+ PX_ASSERT(firstZeroBoneAfter < 5); // or else it doesn't fit
+ (*bonesPerVertex) |= ((firstZeroBoneAfter - 1) & 0x3) << (numVerticesWritten * 2);
+ numVerticesWritten++;
+ }
+
+ // if *bonesPerVertex contains data, advance
+ if (numVerticesWritten > 0)
+ {
+ bonesPerVertex++;
+ }
+
+ // advance until 16 byte aligned
+ while (((size_t)bonesPerVertex & 0xf) != 0)
+ {
+ bonesPerVertex++;
+ }
+ }
+ }
+
+ if (numNonNormalizedVertices > 0)
+ {
+ APEX_DEBUG_WARNING("The Clothing Asset <%s> has %d vertices with non-normalized bone weights. This may lead to wrongly displayed meshes.", mName.c_str(), numNonNormalizedVertices);
+ }
+
+ if (numInefficientVertices > 0)
+ {
+ APEX_DEBUG_WARNING("The Clothing Asset <%s> has %d vertices with non-sorted bone weights. This can decrease performance of the skinning. Resave the asset!", mName.c_str(), numInefficientVertices);
+ }
+ }
+
+ if (numTangentElementCount > 0)
+ {
+ mCompressedTangentW.resize(numTangentElementCount, 0);
+
+ uint32_t* tangentW = mCompressedTangentW.begin();
+ for (uint32_t lodIndex = 0; lodIndex < mGraphicalLods.size(); lodIndex++)
+ {
+ ClothingGraphicalMeshAssetWrapper meshAsset(reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[lodIndex]->renderMeshAssetPointer));
+
+ for (uint32_t submeshIdx = 0; submeshIdx < meshAsset.getSubmeshCount(); submeshIdx++)
+ {
+ uint32_t numVerticesWritten = 0;
+
+ RenderDataFormat::Enum outFormat = RenderDataFormat::UNSPECIFIED;
+ const PxVec4* PX_RESTRICT tangents = (const PxVec4*)meshAsset.getVertexBuffer(submeshIdx, RenderVertexSemantic::TANGENT, outFormat);
+ PX_ASSERT(outFormat == RenderDataFormat::FLOAT4);
+
+ PX_ASSERT(((size_t)tangentW & 0xf) == 0); // make sure we start 16 byte aligned
+
+ const uint32_t numVertices = meshAsset.getNumVertices(submeshIdx);
+ for (uint32_t vertexIndex = 0; vertexIndex < numVertices; vertexIndex++)
+ {
+ PX_ASSERT(PxAbs(tangents[vertexIndex].w) == 1.0f);
+ const uint32_t tangentWpositive = tangents[vertexIndex].w > 0.0f ? 1u : 0u;
+
+ // write the value
+ if (numVerticesWritten == 32)
+ {
+ tangentW++;
+ numVerticesWritten = 0;
+ }
+
+ (*tangentW) |= tangentWpositive << numVerticesWritten;
+ numVerticesWritten++;
+ }
+
+ // if *bonesPerVertex contains data, advance
+ if (numVerticesWritten > 0)
+ {
+ tangentW++;
+ }
+
+ // advance until 16 byte aligned
+ while (((size_t)tangentW & 0xf) != 0)
+ {
+ tangentW++;
+ }
+ }
+ }
+ }
+}
+
+
+
+uint32_t ClothingAssetImpl::getRootBoneIndex()
+{
+ PX_ASSERT(mParams->rootBoneIndex < getNumUsedBones());
+ return mParams->rootBoneIndex;
+}
+
+
+
+uint32_t ClothingAssetImpl::getInterCollisionChannels()
+{
+ return mParams->interCollisionChannels;
+}
+
+
+void ClothingAssetImpl::releaseCookedInstances()
+{
+ if (mParams != NULL && mActors.getSize() == 0)
+ {
+ for (int32_t i = 0; i < mParams->cookedData.arraySizes[0]; i++)
+ {
+ NvParameterized::Interface* cookedData = mParams->cookedData.buf[i].cookedData;
+ if (cookedData != NULL)
+ {
+ BackendFactory* factory = mModule->getBackendFactory(cookedData->className());
+ PX_ASSERT(factory != NULL);
+ if (factory != NULL)
+ {
+ factory->releaseCookedInstances(mParams->cookedData.buf[i].cookedData);
+ }
+ }
+ }
+ }
+}
+
+void ClothingAssetImpl::destroy()
+{
+ mActors.clear();
+
+ while (numCookingDependencies() > 0)
+ {
+ nvidia::Thread::sleep(0);
+ }
+
+ mModule->unregisterAssetWithScenes(this);
+
+ mUnusedSimulationMutex.lock();
+ for (uint32_t i = 0; i < mUnusedSimulation.size(); i++)
+ {
+ if (mUnusedSimulation[i] == NULL)
+ {
+ continue;
+ }
+
+ destroySimulation(mUnusedSimulation[i]);
+ mUnusedSimulation[i] = NULL;
+ }
+ mUnusedSimulation.clear();
+ mUnusedSimulationMutex.unlock();
+
+ releaseCookedInstances();
+
+ for (uint32_t i = 0; i < mPhysicalMeshes.size(); i++)
+ {
+ if (mParams != NULL)
+ {
+ // PH: we should only decrement if we don't use releaseAndReturnNvParameterizedInterface
+ mPhysicalMeshes[i]->referenceCount--;
+ }
+ }
+
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ if (mGraphicalLods[i]->renderMeshAssetPointer == NULL)
+ continue;
+
+ reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[i]->renderMeshAssetPointer)->release();
+ mGraphicalLods[i]->renderMeshAssetPointer = NULL;
+ }
+
+#ifndef WITHOUT_PVD
+ destroyPvdInstances();
+#endif
+ if (mParams != NULL)
+ {
+ // safety!
+ for (uint32_t i = 0; i < mPhysicalMeshes.size(); i++)
+ {
+ PX_ASSERT(mPhysicalMeshes[i]->referenceCount == 0);
+ }
+
+ mParams->setSerializationCallback(NULL, NULL);
+ mParams->destroy();
+ mParams = NULL;
+ }
+
+ mCompressedNumBonesPerVertex.reset();
+
+ delete this;
+}
+
+
+
+int32_t ClothingAssetImpl::getBoneInternalIndex(const char* boneName) const
+{
+ if (boneName == NULL)
+ {
+ return -1;
+ }
+
+ int32_t internalBoneIndex = -1;
+ for (uint32_t i = 0; i < mBones.size(); i++)
+ {
+ if (mBones[i].name != NULL && (::strcmp(mBones[i].name, boneName) == 0))
+ {
+ internalBoneIndex = (int32_t)i;
+ break;
+ }
+ }
+
+ return internalBoneIndex ;
+}
+
+
+
+int32_t ClothingAssetImpl::getBoneInternalIndex(uint32_t boneIndex) const
+{
+ if (boneIndex >= mBones.size())
+ {
+ return -1;
+ }
+
+ int32_t internalBoneIndex = -1;
+ for (uint32_t i = 0; i < mBones.size(); i++)
+ {
+ if (mBones[i].externalIndex == (int32_t)boneIndex)
+ {
+ internalBoneIndex = (int32_t)i;
+ break;
+ }
+ }
+
+ return internalBoneIndex;
+}
+
+
+
+class SortGraphicalVerts
+{
+public:
+ SortGraphicalVerts(uint32_t numVerts, uint32_t submeshOffset, const uint32_t* indices, uint32_t numIndices, ClothingGraphicalLodParameters* lodParameters,
+ ClothingPhysicalMeshParameters* physicsMesh, RenderMeshAssetIntl* renderMeshAsset = NULL) : mNumNotFoundVertices(0), mIndices(indices), mNumIndices(numIndices)
+ {
+ PX_UNUSED(physicsMesh);
+ mNew2Old.resize(numVerts, 0);
+ mOld2New.resize(numVerts, 0);
+ mVertexInfo.resize(numVerts);
+ for (uint32_t i = 0; i < numVerts; i++)
+ {
+ mNew2Old[i] = i;
+ mOld2New[i] = i;
+ mVertexInfo[i].idealPosition = (float)i;
+ }
+
+ // scale the max distance such that it gives a guess for the 'idealPosition'
+ // const float maxDistanceScale = (float)numVerts / physicsMesh->physicalMesh.maximumMaxDistance;
+ // ClothingPhysicalMeshParametersNS::ConstrainCoefficient_Type* coeffs = physicsMesh->physicalMesh.constrainCoefficients.buf;
+
+ if (lodParameters->immediateClothMap.arraySizes[0] > 0)
+ {
+ for (uint32_t i = 0; i < numVerts; i++)
+ {
+ const uint32_t immediateMap = lodParameters->immediateClothMap.buf[i + submeshOffset];
+ if (immediateMap != ClothingConstants::ImmediateClothingInvalidValue)
+ {
+ if ((immediateMap & ClothingConstants::ImmediateClothingInSkinFlag) == 0)
+ {
+ const uint32_t targetIndex = immediateMap & ClothingConstants::ImmediateClothingReadMask;
+ mVertexInfo[i].physicsMeshNumber = getMeshIndex(targetIndex, physicsMesh);
+ PX_UNUSED(targetIndex);
+ }
+ }
+ }
+ }
+
+ const uint32_t numSkins = (uint32_t)lodParameters->skinClothMap.arraySizes[0];
+ for (uint32_t i = 0; i < numSkins; i++)
+ {
+ const uint32_t vertexIndex = lodParameters->skinClothMap.buf[i].vertexIndexPlusOffset - submeshOffset;
+ if (vertexIndex < numVerts) // this also handles underflow
+ {
+ uint32_t physVertexIndex = PxMax(lodParameters->skinClothMap.buf[i].vertexIndex0, lodParameters->skinClothMap.buf[i].vertexIndex1);
+ physVertexIndex = PxMax(physVertexIndex, lodParameters->skinClothMap.buf[i].vertexIndex2);
+ const PxI32 submeshNumber = getMeshIndexMaxFromVert(physVertexIndex, physicsMesh);
+
+ mVertexInfo[vertexIndex].physicsMeshNumber = PxMax(submeshNumber, mVertexInfo[vertexIndex].physicsMeshNumber);
+ }
+ }
+
+ const uint32_t numSkinB = (uint32_t)lodParameters->skinClothMapB.arraySizes[0];
+ for (uint32_t i = 0; i < numSkinB; i++)
+ {
+ const uint32_t faceIndex0 = lodParameters->skinClothMapB.buf[i].faceIndex0;
+ PX_UNUSED(faceIndex0);
+ const uint32_t vertexIndex = lodParameters->skinClothMapB.buf[i].vertexIndexPlusOffset - submeshOffset;
+ if (vertexIndex < numVerts)
+ {
+ mVertexInfo[vertexIndex].physicsMeshNumber = PxMax(getMeshIndexMaxFromFace(faceIndex0, physicsMesh), mVertexInfo[vertexIndex].physicsMeshNumber);
+ }
+ }
+
+ const uint32_t numTetras = (uint32_t)lodParameters->tetraMap.arraySizes[0];
+ for (uint32_t i = 0; i < numTetras; i++)
+ {
+ const uint32_t tetraIndex0 = lodParameters->tetraMap.buf[i].tetraIndex0;
+ mVertexInfo[i].physicsMeshNumber = PxMax(getMeshIndexMaxFromFace(tetraIndex0, physicsMesh), mVertexInfo[i].physicsMeshNumber);
+ }
+
+ if (renderMeshAsset != NULL)
+ {
+ uint32_t numSkinClothMaps = (uint32_t)lodParameters->skinClothMap.arraySizes[0];
+ SkinClothMap* skinClothMaps = lodParameters->skinClothMap.buf;
+
+ uint32_t count = 0;
+ uint32_t targetOffset = 0;
+ for (uint32_t s = 0; s < renderMeshAsset->getSubmeshCount(); s++)
+ {
+ const VertexBuffer& vb = renderMeshAsset->getSubmesh(s).getVertexBuffer();
+ const VertexFormat& vf = vb.getFormat();
+
+ const uint32_t graphicalMaxDistanceIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID("MAX_DISTANCE"));
+ RenderDataFormat::Enum outFormat = vf.getBufferFormat(graphicalMaxDistanceIndex);
+ const float* graphicalMaxDistance = outFormat == RenderDataFormat::UNSPECIFIED ? NULL :
+ reinterpret_cast<const float*>(vb.getBuffer(graphicalMaxDistanceIndex));
+ PX_ASSERT(graphicalMaxDistance == NULL || outFormat == RenderDataFormat::FLOAT1);
+
+ const uint32_t numVertices = renderMeshAsset->getSubmesh(s).getVertexCount(0);
+ for (uint32_t vertexIndex = 0; vertexIndex < numVertices; vertexIndex++)
+ {
+ const uint32_t index = vertexIndex + targetOffset;
+ if (graphicalMaxDistance != NULL && graphicalMaxDistance[vertexIndex] == 0.0f)
+ {
+ for (uint32_t i = 0; i < numSkinClothMaps; i++)
+ {
+ uint32_t grIndex = skinClothMaps[i].vertexIndexPlusOffset;
+ if (grIndex == index)
+ {
+ count++;
+
+ const uint32_t vertexIndex = grIndex - submeshOffset;
+ if (vertexIndex < numVerts) // this also handles underflow
+ {
+ mVertexInfo[vertexIndex].physicsMeshNumber = -1;
+ }
+ }
+ }
+ }
+ }
+
+ targetOffset += numVertices;
+ }
+ }
+
+ for (uint32_t i = 0; i < numVerts; i++)
+ {
+ if (mVertexInfo[i].physicsMeshNumber == -1)
+ {
+ // give it the largest number, such that it gets sorted to the very end instead of the very beginning. Then at least it's cpu skinned.
+ mVertexInfo[i].physicsMeshNumber = PX_MAX_I32;
+ mNumNotFoundVertices++;
+ }
+ PX_ASSERT(mVertexInfo[i].idealPosition != -1);
+ }
+
+ // we only know the submesh number for each individual vertex, but we need to make sure that this is consistent for each
+ // triangle. So we define the submesh number for a triangle as the min of all the submesh numbers of its vertices.
+ // Then we set the vertex submesh number to the min of all its triangle's submesh numbers.
+
+ Array<int32_t> triangleMeshIndex(mNumIndices / 3, 0x7fffffff);
+ for (uint32_t i = 0; i < triangleMeshIndex.size(); i++)
+ {
+ PxU32 index = i * 3;
+ PxI32 meshNumber = PxMin(mVertexInfo[mIndices[index]].physicsMeshNumber, mVertexInfo[mIndices[index + 1]].physicsMeshNumber);
+ triangleMeshIndex[i] = PxMin(meshNumber, mVertexInfo[mIndices[index + 2]].physicsMeshNumber);
+ }
+
+ // now let's redistribute it
+ for (uint32_t i = 0; i < triangleMeshIndex.size(); i++)
+ {
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ uint32_t index = mIndices[i * 3 + j];
+ if (triangleMeshIndex[i] < mVertexInfo[index].physicsMeshNumber)
+ {
+ mVertexInfo[index].physicsMeshNumber = triangleMeshIndex[i];
+ // we need to distinguish the ones that naturally belong to a submesh, or the border ones that got added this late
+ mVertexInfo[index].pulledInThroughTriangle = true;
+ }
+ }
+ }
+ }
+
+ PxI32 getMeshIndex(PxU32 vertexIndex, const ClothingPhysicalMeshParameters* physicsMesh)
+ {
+ if (physicsMesh->physicalMesh.numSimulatedVertices > vertexIndex)
+ {
+ return 0;
+ }
+
+ return 1;
+ }
+
+ PxI32 getMeshIndexMaxFromFace(PxU32 faceIndex0, const ClothingPhysicalMeshParameters* physicsMesh)
+ {
+ if (physicsMesh->physicalMesh.numSimulatedIndices > faceIndex0)
+ {
+ return 0;
+ }
+
+ return 1;
+ }
+
+ PxI32 getMeshIndexMaxFromVert(PxU32 vertexIndex, const ClothingPhysicalMeshParameters* physicsMesh)
+ {
+
+ if (physicsMesh->physicalMesh.numSimulatedVertices > vertexIndex)
+ {
+ return 0;
+ }
+
+ return 1;
+ }
+
+ bool operator()(const uint32_t a, const uint32_t b) const
+ {
+ if (mVertexInfo[a].pulledInThroughTriangle != mVertexInfo[b].pulledInThroughTriangle)
+ {
+ return mVertexInfo[a].pulledInThroughTriangle < mVertexInfo[b].pulledInThroughTriangle;
+ }
+
+ return mVertexInfo[a].idealPosition < mVertexInfo[b].idealPosition;
+ }
+
+ void sortVertices()
+ {
+ nvidia::sort(mNew2Old.begin(), mNew2Old.size(), *this);
+
+ for (uint32_t i = 0; i < mNew2Old.size(); i++)
+ {
+ mOld2New[mNew2Old[i]] = i;
+ }
+ }
+
+ uint32_t computeCost()
+ {
+ uint32_t totalDist = 0;
+ // const uint32_t numVertsInCacheLine = 4096 / 12;
+ for (uint32_t i = 0; i < mNumIndices; i += 3)
+ {
+ // create 3 edges
+ const uint32_t edges[3] =
+ {
+ (uint32_t)PxAbs((int32_t)mOld2New[mIndices[i + 0]] - (int32_t)mOld2New[mIndices[i + 1]]),
+ (uint32_t)PxAbs((int32_t)mOld2New[mIndices[i + 1]] - (int32_t)mOld2New[mIndices[i + 2]]),
+ (uint32_t)PxAbs((int32_t)mOld2New[mIndices[i + 2]] - (int32_t)mOld2New[mIndices[i + 0]]),
+ };
+
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ totalDist += edges[j];
+ }
+
+ }
+
+ return totalDist;
+ }
+
+ PxI32 getMesh(PxU32 newVertexIndex)
+ {
+ return mVertexInfo[mNew2Old[newVertexIndex]].physicsMeshNumber;
+ }
+
+ bool isAdditional(uint32_t newVertexIndex)
+ {
+ return mVertexInfo[mNew2Old[newVertexIndex]].pulledInThroughTriangle;
+ }
+
+ nvidia::Array<uint32_t> mOld2New;
+ nvidia::Array<uint32_t> mNew2Old;
+
+ uint32_t mNumNotFoundVertices;
+
+private:
+ SortGraphicalVerts& operator=(const SortGraphicalVerts&);
+
+ struct InternalInfo
+ {
+ InternalInfo() : physicsMeshNumber(-1), idealPosition(-1), idealChange(0.0f), idealCount(0.0f), pulledInThroughTriangle(false) {}
+ int32_t physicsMeshNumber;
+ float idealPosition;
+ float idealChange;
+ float idealCount;
+ bool pulledInThroughTriangle;
+ };
+
+ nvidia::Array<InternalInfo> mVertexInfo;
+
+ const uint32_t* mIndices;
+ const uint32_t mNumIndices;
+};
+
+
+
+template <typename T>
+class SkinClothMapPredicate
+{
+public:
+ bool operator()(const T& map1, const T& map2) const
+ {
+ return map1.vertexIndexPlusOffset < map2.vertexIndexPlusOffset;
+ }
+};
+
+
+
+class SortGraphicalIndices
+{
+public:
+ SortGraphicalIndices(uint32_t numIndices, uint32_t* indices) : mIndices(indices)
+ {
+ mTriangleInfo.resize(numIndices / 3);
+ for (uint32_t i = 0; i < mTriangleInfo.size(); i++)
+ {
+ mTriangleInfo[i].mesh = -1;
+ mTriangleInfo[i].originalPosition = i;
+ }
+
+ mNew2Old.resize(numIndices / 3);
+ mOld2New.resize(numIndices / 3);
+ for (uint32_t i = 0; i < mNew2Old.size(); i++)
+ {
+ mNew2Old[i] = i;
+ mOld2New[i] = i;
+ }
+ }
+
+ void setTriangleMesh(PxU32 triangle, PxI32 mesh)
+ {
+ mTriangleInfo[triangle].mesh = mesh;
+ }
+
+ PxI32 getTriangleMesh(PxU32 newTriangleIndex) const
+ {
+ return mTriangleInfo[mNew2Old[newTriangleIndex]].mesh;
+ }
+
+ bool operator()(const uint32_t t1, const uint32_t t2) const
+ {
+ if (mTriangleInfo[t1].mesh != mTriangleInfo[t2].mesh)
+ {
+ return mTriangleInfo[t1].mesh < mTriangleInfo[t2].mesh;
+ }
+
+ return mTriangleInfo[t1].originalPosition < mTriangleInfo[t2].originalPosition;
+ }
+
+ void sort()
+ {
+ nvidia::sort(mNew2Old.begin(), mNew2Old.size(), *this);
+
+ for (uint32_t i = 0; i < mNew2Old.size(); i++)
+ {
+ mOld2New[mNew2Old[i]] = i;
+ }
+
+ ApexPermute(mIndices, mNew2Old.begin(), mNew2Old.size(), 3);
+ }
+
+private:
+ nvidia::Array<uint32_t> mNew2Old;
+ nvidia::Array<uint32_t> mOld2New;
+ uint32_t* mIndices;
+
+ struct TriangleInfo
+ {
+ int32_t mesh;
+ uint32_t originalPosition;
+ };
+ nvidia::Array<TriangleInfo> mTriangleInfo;
+};
+
+
+
+bool ClothingAssetImpl::reorderGraphicsVertices(uint32_t graphicalLodId, bool perfWarning)
+{
+ PX_ASSERT(mGraphicalLods[graphicalLodId] != NULL);
+
+ const uint32_t curSortingVersion = 2; // bump this number when the sorting changes!
+
+ if (mGraphicalLods[graphicalLodId]->renderMeshAssetSorting >= curSortingVersion)
+ {
+ // nothing needs to be done.
+ return false;
+ }
+
+ mGraphicalLods[graphicalLodId]->renderMeshAssetSorting = curSortingVersion;
+
+ if (perfWarning)
+ {
+ APEX_DEBUG_INFO("Performance warning. This asset <%s> has to be re-saved to speed up loading", mName.c_str());
+ }
+
+ RenderMeshAssetIntl* rma = static_cast<RenderMeshAssetIntl*>(mGraphicalLods[graphicalLodId]->renderMeshAssetPointer);
+ PX_ASSERT(rma != NULL);
+ if (rma == NULL)
+ return false;
+
+ const uint32_t numSubMeshes = rma->getSubmeshCount();
+ uint32_t submeshVertexOffset = 0;
+
+ const uint32_t numSkinClothMap = (uint32_t)mGraphicalLods[graphicalLodId]->skinClothMap.arraySizes[0];
+ ClothingGraphicalLodParametersNS::SkinClothMapD_Type* skinClothMap = mGraphicalLods[graphicalLodId]->skinClothMap.buf;
+
+ const uint32_t numSkinClothMapB = (uint32_t)mGraphicalLods[graphicalLodId]->skinClothMapB.arraySizes[0];
+ ClothingGraphicalLodParametersNS::SkinClothMapB_Type* skinClothMapB = mGraphicalLods[graphicalLodId]->skinClothMapB.buf;
+
+ // allocate enough space
+ {
+ if (mGraphicalLods[graphicalLodId]->physicsMeshPartitioning.arraySizes[0] != (int32_t)numSubMeshes)
+ {
+ NvParameterized::Handle handle(*mGraphicalLods[graphicalLodId], "physicsMeshPartitioning");
+ PX_ASSERT(handle.isValid());
+ PX_ASSERT(handle.parameterDefinition()->type() == NvParameterized::TYPE_ARRAY);
+ handle.resizeArray((int32_t)numSubMeshes);
+ }
+ }
+
+ uint32_t meshPartitioningIndex = 0;
+ for (uint32_t s = 0; s < numSubMeshes; s++)
+ {
+ const RenderSubmesh& submesh = rma->getSubmesh(s);
+ const uint32_t numVertices = submesh.getVertexCount(0);
+
+ const uint32_t numIters = 2;
+ uint32_t costs[numIters] = { 0 };
+
+ ClothingPhysicalMeshParameters* physicsMesh = mPhysicalMeshes[mGraphicalLods[graphicalLodId]->physicalMeshId];
+
+ SortGraphicalVerts sortedVertices(numVertices, submeshVertexOffset, submesh.getIndexBuffer(0), submesh.getIndexCount(0), mGraphicalLods[graphicalLodId], physicsMesh, rma);
+
+ costs[0] = sortedVertices.computeCost();
+ sortedVertices.sortVertices(); // same ordering as before, but grouped by submeshes now
+
+ costs[1] = costs[0]; // stupid warnings
+ costs[1] = sortedVertices.computeCost();
+
+
+#if 0
+ // reorder based on triangle distances (into the vertex buffer)
+ // disable for now...
+ // PH: On the PS3 perf is 30% better if this is not performed! Needs much more further investigation!
+ uint32_t numIncreases = 0;
+ for (uint32_t i = 2; i < numIters; i++)
+ {
+ sortedVertices.refineIdealPositions(1.0f);
+ sortedVertices.sortVertices();
+ costs[i] = sortedVertices.computeCost();
+ if (costs[i] >= costs[i - 1])
+ {
+ numIncreases++;
+ if (numIncreases > 40)
+ {
+ break;
+ }
+ }
+ else if (numIncreases > 0)
+ {
+ numIncreases--;
+ }
+ }
+#endif
+
+ rma->getInternalSubmesh(s).applyPermutation(sortedVertices.mOld2New, sortedVertices.mNew2Old);
+
+ {
+ uint32_t vertexCount = 0;
+ uint32_t vertexAdditionalCount = 0;
+
+ while (vertexAdditionalCount < sortedVertices.mNew2Old.size() && sortedVertices.getMesh(vertexAdditionalCount) <= 0)
+ {
+ if (!sortedVertices.isAdditional(vertexAdditionalCount))
+ {
+ vertexCount = vertexAdditionalCount + 1;
+ }
+ vertexAdditionalCount++;
+ }
+
+ mGraphicalLods[graphicalLodId]->physicsMeshPartitioning.buf[meshPartitioningIndex].graphicalSubmesh = s;
+ mGraphicalLods[graphicalLodId]->physicsMeshPartitioning.buf[meshPartitioningIndex].numSimulatedVertices = vertexCount;
+ mGraphicalLods[graphicalLodId]->physicsMeshPartitioning.buf[meshPartitioningIndex].numSimulatedVerticesAdditional = vertexAdditionalCount;
+ }
+
+ // also sort the index buffer accordingly
+ {
+ uint32_t* indices = rma->getInternalSubmesh(s).getIndexBufferWritable(0);
+
+ uint32_t indexCount = submesh.getIndexCount(0);
+ uint32_t triCount = indexCount / 3;
+ SortGraphicalIndices sortedIndices(indexCount, indices);
+
+ for (uint32_t i = 0; i < triCount; i++)
+ {
+ int32_t meshIndex = 0;
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ meshIndex = PxMax(meshIndex, sortedVertices.getMesh(indices[i * 3 + j]));
+ }
+ sortedIndices.setTriangleMesh(i, meshIndex);
+ }
+
+ sortedIndices.sort();
+
+ uint32_t startTriangle = 0;
+ while (startTriangle < triCount) // && sortedIndices.getTriangleSubmesh(startTriangle) <= i)
+ {
+ startTriangle++;
+ }
+ mGraphicalLods[graphicalLodId]->physicsMeshPartitioning.buf[meshPartitioningIndex].numSimulatedIndices = startTriangle * 3;
+ }
+
+ // also adapt all mesh-mesh skinning tables
+
+ uint32_t* immediateMap = mGraphicalLods[graphicalLodId]->immediateClothMap.buf;
+ if (immediateMap != NULL)
+ {
+ ApexPermute(immediateMap + submeshVertexOffset, sortedVertices.mNew2Old.begin(), numVertices);
+ }
+
+ for (uint32_t i = 0; i < numSkinClothMap; i++)
+ {
+ if (skinClothMap[i].vertexIndexPlusOffset < submeshVertexOffset)
+ {
+ continue;
+ }
+ else if (skinClothMap[i].vertexIndexPlusOffset >= submeshVertexOffset + numVertices)
+ {
+ break;
+ }
+
+ uint32_t oldVertexIndex = skinClothMap[i].vertexIndexPlusOffset - submeshVertexOffset;
+ skinClothMap[i].vertexIndexPlusOffset = submeshVertexOffset + sortedVertices.mOld2New[oldVertexIndex];
+ }
+
+ for (uint32_t i = 0; i < numSkinClothMapB; i++)
+ {
+ const uint32_t vertexIndex = skinClothMapB[i].vertexIndexPlusOffset;
+ if (vertexIndex >= submeshVertexOffset && vertexIndex < submeshVertexOffset + numVertices)
+ {
+ skinClothMapB[i].vertexIndexPlusOffset = submeshVertexOffset + sortedVertices.mOld2New[vertexIndex - submeshVertexOffset];
+ }
+ }
+
+ submeshVertexOffset += numVertices;
+ meshPartitioningIndex++;
+ }
+
+ // make sure all maps are sorted again, only mapC type!
+ nvidia::sort(skinClothMap, numSkinClothMap, SkinClothMapPredicate<ClothingGraphicalLodParametersNS::SkinClothMapD_Type>());
+
+ uint32_t* immediateMap = mGraphicalLods[graphicalLodId]->immediateClothMap.buf;
+ if (immediateMap != NULL)
+ {
+ for (uint32_t i = 0; i < numSkinClothMap; i++)
+ {
+ PX_ASSERT((immediateMap[skinClothMap[i].vertexIndexPlusOffset] & ClothingConstants::ImmediateClothingInSkinFlag) == ClothingConstants::ImmediateClothingInSkinFlag);
+ immediateMap[skinClothMap[i].vertexIndexPlusOffset] = i | ClothingConstants::ImmediateClothingInSkinFlag;
+ }
+
+#ifdef _DEBUG
+ // sanity check
+ for (uint32_t i = 0; i < submeshVertexOffset; i++)
+ {
+ uint32_t imm = immediateMap[i];
+ if (imm != ClothingConstants::ImmediateClothingInvalidValue)
+ {
+ if ((imm & ClothingConstants::ImmediateClothingInSkinFlag) == ClothingConstants::ImmediateClothingInSkinFlag)
+ {
+ imm &= ClothingConstants::ImmediateClothingReadMask;
+
+ if (numSkinClothMap > 0)
+ {
+ PX_ASSERT(imm < numSkinClothMap);
+ PX_ASSERT(skinClothMap[imm].vertexIndexPlusOffset == i);
+ }
+ else if (numSkinClothMapB > 0)
+ {
+ PX_ASSERT(imm < numSkinClothMapB);
+ PX_ASSERT(skinClothMapB[imm].vertexIndexPlusOffset == i);
+ }
+ }
+ }
+ }
+#endif
+ }
+
+ return true;
+}
+
+
+
+class DeformableVerticesMaxDistancePredicate
+{
+public:
+ DeformableVerticesMaxDistancePredicate(ClothingConstrainCoefficients* constrainCoefficients) : mConstrainCoefficients(constrainCoefficients) {}
+ bool operator()(uint32_t oldindex1, uint32_t oldIndex2) const
+ {
+ return mConstrainCoefficients[oldindex1].maxDistance > mConstrainCoefficients[oldIndex2].maxDistance;
+ }
+
+private:
+ ClothingConstrainCoefficients* mConstrainCoefficients;
+};
+
+
+
+bool ClothingAssetImpl::reorderDeformableVertices(ClothingPhysicalMeshImpl& physicalMesh)
+{
+ ClothingPhysicalMeshParameters* params = static_cast<ClothingPhysicalMeshParameters*>(physicalMesh.getNvParameterized());
+
+ const uint32_t curSortingVersion = 1; // bump this number when the sorting changes!
+
+ if (params->physicalMesh.physicalMeshSorting >= curSortingVersion)
+ {
+ // nothing needs to be done.
+ return false;
+ }
+
+ params->physicalMesh.physicalMeshSorting = curSortingVersion;
+
+ uint32_t* indices = physicalMesh.getIndicesBuffer();
+
+ // create mapping arrays
+ Array<uint32_t> newIndices(physicalMesh.getNumVertices(), (uint32_t) - 1);
+ Array<uint32_t> oldIndices(physicalMesh.getNumVertices(), (uint32_t) - 1);
+ uint32_t nextIndex = 0;
+ for (uint32_t i = 0; i < physicalMesh.getNumIndices(); i++)
+ {
+ const uint32_t vertexIndex = indices[i];
+ if (newIndices[vertexIndex] == (uint32_t) - 1)
+ {
+ newIndices[vertexIndex] = nextIndex;
+ oldIndices[nextIndex] = vertexIndex;
+ nextIndex++;
+ }
+ }
+
+ uint32_t maxVertexIndex = 0;
+ for (uint32_t j = 0; j < params->physicalMesh.numSimulatedIndices; j++)
+ {
+ const uint32_t newVertexIndex = newIndices[indices[j]];
+ maxVertexIndex = PxMax(maxVertexIndex, newVertexIndex);
+ }
+
+ maxVertexIndex++;
+ params->physicalMesh.numSimulatedVertices = maxVertexIndex;
+
+ DeformableVerticesMaxDistancePredicate predicate(physicalMesh.getConstrainCoefficientBuffer());
+
+ // Sort mesh.
+ nvidia::sort(oldIndices.begin(), maxVertexIndex, predicate);
+
+ // fix newIndices, the sort has destroyed them
+ for (uint32_t i = 0; i < nextIndex; i++)
+ {
+ PX_ASSERT(newIndices[oldIndices[i]] != (uint32_t) - 1);
+ newIndices[oldIndices[i]] = i;
+ }
+
+ // move unused vertices to the end
+ if (nextIndex < physicalMesh.getNumVertices())
+ {
+ // TODO check if ApexPermute works without this
+ for (uint32_t i = 0; i < newIndices.size(); i++)
+ {
+ if (newIndices[i] == (uint32_t) - 1)
+ {
+ newIndices[i] = nextIndex;
+ oldIndices[nextIndex] = i;
+ nextIndex++;
+ }
+ }
+ }
+
+ PX_ASSERT(physicalMesh.getNumVertices() == oldIndices.size());
+ PX_ASSERT(nextIndex == physicalMesh.getNumVertices()); // at this point we assume that all vertices are referenced
+
+ // do reordering
+ physicalMesh.applyPermutation(oldIndices);
+
+ // set max distance 0 vertices
+ ClothingConstrainCoefficients* coeffs = physicalMesh.getConstrainCoefficientBuffer();
+
+ const uint32_t numSimulatedVertices = params->physicalMesh.numSimulatedVertices;
+
+ uint32_t vertexIndex = 0;
+ float eps = 1e-8;
+ for (; vertexIndex < numSimulatedVertices; vertexIndex++)
+ {
+ if (coeffs[vertexIndex].maxDistance <= eps)
+ {
+ break;
+ }
+ }
+
+ params->physicalMesh.numMaxDistance0Vertices = numSimulatedVertices - vertexIndex;
+
+ // safety
+ for (; vertexIndex < numSimulatedVertices; vertexIndex++)
+ {
+ PX_ASSERT(coeffs[vertexIndex].maxDistance <= eps);
+ }
+
+
+ // clean up existing references
+ for (uint32_t i = 0; i < physicalMesh.getNumIndices(); i++)
+ {
+ indices[i] = newIndices[indices[i]];
+ }
+
+ // update mappings into deformable vertex buffer
+ for (uint32_t i = 0; i < mGraphicalLods.size(); i++)
+ {
+ if (mPhysicalMeshes[mGraphicalLods[i]->physicalMeshId] == physicalMesh.getNvParameterized())
+ {
+ ClothingGraphicalMeshAssetWrapper meshAsset(reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[i]->renderMeshAssetPointer));
+ ClothingGraphicalLodParameters& graphicalLod = *mGraphicalLods[i];
+
+ const uint32_t numGraphicalVertices = meshAsset.getNumTotalVertices();
+
+ if (graphicalLod.immediateClothMap.arraySizes[0] > 0)
+ {
+ for (uint32_t j = 0; j < numGraphicalVertices; j++)
+ {
+ if (graphicalLod.immediateClothMap.buf[j] != ClothingConstants::ImmediateClothingInvalidValue)
+ {
+ if ((graphicalLod.immediateClothMap.buf[j] & ClothingConstants::ImmediateClothingInSkinFlag) == 0)
+ {
+ const uint32_t flags = graphicalLod.immediateClothMap.buf[j] & ~ClothingConstants::ImmediateClothingReadMask;
+ graphicalLod.immediateClothMap.buf[j] =
+ newIndices[graphicalLod.immediateClothMap.buf[j] & ClothingConstants::ImmediateClothingReadMask] | flags;
+ }
+ }
+ }
+ }
+
+ for(int32_t j = 0; j < graphicalLod.skinClothMap.arraySizes[0]; ++j)
+ {
+ graphicalLod.skinClothMap.buf[j].vertexIndex0 = newIndices[graphicalLod.skinClothMap.buf[j].vertexIndex0];
+ graphicalLod.skinClothMap.buf[j].vertexIndex1 = newIndices[graphicalLod.skinClothMap.buf[j].vertexIndex1];
+ graphicalLod.skinClothMap.buf[j].vertexIndex2 = newIndices[graphicalLod.skinClothMap.buf[j].vertexIndex2];
+ }
+ }
+ }
+
+ // update transition maps
+
+ if (params->transitionDown.arraySizes[0] > 0)
+ {
+ for (int32_t i = 0; i < params->transitionDown.arraySizes[0]; i++)
+ {
+ uint32_t& vertexIndex = params->transitionDown.buf[i].vertexIndexPlusOffset;
+ PX_ASSERT(vertexIndex == (uint32_t)i);
+ vertexIndex = newIndices[vertexIndex];
+ }
+
+ nvidia::sort(params->transitionDown.buf, (uint32_t)params->transitionDown.arraySizes[0], SkinClothMapPredicate<ClothingPhysicalMeshParametersNS::SkinClothMapD_Type>());
+ }
+
+ if (params->transitionUp.arraySizes[0] > 0)
+ {
+ for (int32_t i = 0; i < params->transitionUp.arraySizes[0]; i++)
+ {
+ uint32_t& vertexIndex = params->transitionUp.buf[i].vertexIndexPlusOffset;
+ PX_ASSERT(vertexIndex == (uint32_t)i);
+ vertexIndex = newIndices[vertexIndex];
+ }
+ nvidia::sort(params->transitionUp.buf, (uint32_t)params->transitionUp.arraySizes[0], SkinClothMapPredicate<ClothingPhysicalMeshParametersNS::SkinClothMapD_Type>());
+ }
+
+ return true;
+}
+
+
+
+float ClothingAssetImpl::getMaxMaxDistance(ClothingPhysicalMeshParametersNS::PhysicalMesh_Type& physicalMesh, uint32_t index, uint32_t numIndices) const
+{
+ uint32_t* indices = physicalMesh.indices.buf;
+ ClothingPhysicalMeshParametersNS::ConstrainCoefficient_Type* coeffs = physicalMesh.constrainCoefficients.buf;
+
+ float maxDist = coeffs[indices[index]].maxDistance;
+ for (uint32_t i = 1; i < numIndices; i++)
+ {
+ maxDist = PxMax(maxDist, coeffs[indices[index + i]].maxDistance);
+ }
+
+ return maxDist;
+}
+
+
+
+uint32_t ClothingAssetImpl::getCorrespondingPhysicalVertices(const ClothingGraphicalLodParameters& graphLod, uint32_t submeshIndex,
+ uint32_t graphicalVertexIndex, const AbstractMeshDescription& pMesh,
+ uint32_t submeshVertexOffset, uint32_t indices[4], float trust[4]) const
+{
+ PX_UNUSED(submeshIndex); // stupid release mode
+
+ PX_ASSERT(pMesh.numIndices > 0);
+ PX_ASSERT(pMesh.pIndices != NULL);
+
+
+ uint32_t result = 0;
+
+ if (graphLod.immediateClothMap.arraySizes[0] > 0)
+ {
+ indices[0] = graphLod.immediateClothMap.buf[graphicalVertexIndex + submeshVertexOffset];
+ trust[0] = 1.0f;
+
+ if (indices[0] != ClothingConstants::ImmediateClothingInvalidValue)
+ {
+ if ((indices[0] & ClothingConstants::ImmediateClothingInSkinFlag) == 0)
+ {
+ indices[0] &= ClothingConstants::ImmediateClothingReadMask;
+ result = 1;
+ }
+ else if (graphLod.skinClothMapB.arraySizes[0] > 0)
+ {
+ const int32_t temp = int32_t(indices[0] & ClothingConstants::ImmediateClothingReadMask);
+ if (temp < graphLod.skinClothMapB.arraySizes[0])
+ {
+ for (uint32_t i = 0; i < 3; i++)
+ {
+ PX_ASSERT(graphLod.skinClothMapB.buf[temp].faceIndex0 + i < pMesh.numIndices);
+ indices[i] = pMesh.pIndices[graphLod.skinClothMapB.buf[temp].faceIndex0 + i];
+ trust[i] = 1.0f; // PH: This should be lower for some vertices!
+ }
+ result = 3;
+ }
+ }
+ else if (graphLod.skinClothMap.arraySizes[0] > 0)
+ {
+ const int32_t temp = int32_t(indices[0] & ClothingConstants::ImmediateClothingReadMask);
+ if (temp < graphLod.skinClothMap.arraySizes[0])
+ {
+ PxVec3 bary = graphLod.skinClothMap.buf[temp].vertexBary;
+ bary.x = PxClamp(bary.x, 0.0f, 1.0f);
+ bary.y = PxClamp(bary.y, 0.0f, 1.0f);
+ bary.z = PxClamp(1.0f - bary.x - bary.y, 0.0f, 1.0f);
+ uint32_t physVertIndex[3] =
+ {
+ graphLod.skinClothMap.buf[temp].vertexIndex0,
+ graphLod.skinClothMap.buf[temp].vertexIndex1,
+ graphLod.skinClothMap.buf[temp].vertexIndex2
+ };
+ for (uint32_t i = 0; i < 3; i++)
+ {
+ //PX_ASSERT(graphLod.skinClothMap.buf[temp].faceIndex0 + i < pMesh.numIndices);
+ indices[i] = physVertIndex[i];
+ trust[i] = bary[i];
+ }
+ result = 3;
+ }
+ }
+ }
+ }
+ else if (graphLod.skinClothMapB.arraySizes[0] > 0)
+ {
+ PX_ASSERT(graphLod.skinClothMapB.buf[graphicalVertexIndex + submeshVertexOffset].submeshIndex == submeshIndex);
+ PX_ASSERT(graphLod.skinClothMapB.buf[graphicalVertexIndex + submeshVertexOffset].vertexIndexPlusOffset == graphicalVertexIndex + submeshVertexOffset);
+
+ for (uint32_t i = 0; i < 3; i++)
+ {
+ PX_ASSERT(graphLod.skinClothMapB.buf[graphicalVertexIndex + submeshVertexOffset].faceIndex0 + i < pMesh.numIndices);
+ indices[i] = pMesh.pIndices[graphLod.skinClothMapB.buf[graphicalVertexIndex + submeshVertexOffset].faceIndex0 + i];
+ trust[i] = 1.0f;
+ }
+ result = 3;
+ }
+ else if (graphLod.skinClothMap.arraySizes[0] > 0)
+ {
+ // we need to do binary search here
+ uint32_t curMin = 0;
+ uint32_t curMax = (uint32_t)graphLod.skinClothMap.arraySizes[0];
+ const uint32_t searchFor = graphicalVertexIndex + submeshVertexOffset;
+ while (curMax > curMin)
+ {
+ uint32_t middle = (curMin + curMax) >> 1;
+ PX_ASSERT(middle == graphLod.skinClothMap.buf[middle].vertexIndexPlusOffset);
+ const uint32_t probeResult = middle;
+ if (probeResult < searchFor)
+ {
+ curMin = middle + 1;
+ }
+ else
+ {
+ curMax = middle;
+ }
+ }
+
+ PX_ASSERT(curMin == graphLod.skinClothMap.buf[curMin].vertexIndexPlusOffset);
+ if (curMin == searchFor)
+ {
+ PxVec3 bary = graphLod.skinClothMap.buf[curMin].vertexBary;
+ bary.x = PxClamp(bary.x, 0.0f, 1.0f);
+ bary.y = PxClamp(bary.y, 0.0f, 1.0f);
+ bary.z = PxClamp(1.0f - bary.x - bary.y, 0.0f, 1.0f);
+
+ uint32_t physVertIndex[3] =
+ {
+ graphLod.skinClothMap.buf[curMin].vertexIndex0,
+ graphLod.skinClothMap.buf[curMin].vertexIndex1,
+ graphLod.skinClothMap.buf[curMin].vertexIndex2
+ };
+ for (uint32_t i = 0; i < 3; i++)
+ {
+ // PX_ASSERT(graphLod.skinClothMap.buf[curMin].faceIndex0 + i < pMesh.numIndices);
+ indices[i] = physVertIndex[i];
+ trust[i] = bary[i];
+ }
+ result = 3;
+ }
+ }
+ else if (graphLod.tetraMap.arraySizes[0] > 0)
+ {
+ for (uint32_t i = 0; i < 4; i++)
+ {
+ PX_ASSERT(graphLod.tetraMap.buf[graphicalVertexIndex + submeshVertexOffset].tetraIndex0 + i < pMesh.numIndices);
+ indices[i] = pMesh.pIndices[graphLod.tetraMap.buf[graphicalVertexIndex + submeshVertexOffset].tetraIndex0 + i];
+ trust[i] = 1.0f;
+ }
+ result = 4;
+ }
+
+ for (uint32_t i = 0; i < result; i++)
+ {
+ PX_ASSERT(trust[i] >= 0.0f);
+ PX_ASSERT(trust[i] <= 1.0f);
+ }
+
+ return result;
+}
+
+
+
+void ClothingAssetImpl::getNormalsAndVerticesForFace(PxVec3* vtx, PxVec3* nrm, uint32_t i, const AbstractMeshDescription& srcPM) const
+{
+ // copy indices for convenience
+ PX_ASSERT(i < srcPM.numIndices);
+ uint32_t di[3];
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ di[j] = srcPM.pIndices[i + j];
+ }
+
+ // To guarantee consistency in our implicit tetrahedral mesh definition we must always order vertices
+ // idx[0,1,2] = min, max and mid
+ uint32_t idx[3];
+ idx[0] = PxMin(di[0], PxMin(di[1], di[2]));
+ idx[1] = PxMax(di[0], PxMax(di[1], di[2]));
+ idx[2] = idx[0];
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ if ((idx[0] != di[j]) && (idx[1] != di[j]))
+ {
+ idx[2] = di[j];
+ }
+ }
+
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ vtx[j] = srcPM.pPosition[idx[j]];
+ nrm[j] = srcPM.pNormal[idx[j]];
+#ifdef _DEBUG
+ // sanity
+ // PH: These normals 'should' always be normalized, maybe we can get rid of the normalize completely!
+ const float length = nrm[j].magnitudeSquared();
+ if (!(length >= 0.99f && length <= 1.01f))
+ {
+ static bool first = true;
+ if (first)
+ {
+ PX_ALWAYS_ASSERT();
+ first = false;
+ }
+ }
+#else
+ // PH: let's try and disable it in release mode...
+ //nrm[j].normalize();
+#endif
+ };
+}
+
+
+
+bool ClothingAssetImpl::setBoneName(uint32_t internalIndex, const char* name)
+{
+ NvParameterized::Handle bonesHandle(*mParams);
+ mParams->getParameterHandle("bones", bonesHandle);
+
+ if (bonesHandle.isValid())
+ {
+ NvParameterized::Handle boneHandle(*mParams);
+ bonesHandle.getChildHandle((int32_t)internalIndex, boneHandle);
+
+ if (boneHandle.isValid())
+ {
+ NvParameterized::Handle nameHandle(*mParams);
+ boneHandle.getChildHandle(mParams, "name", nameHandle);
+
+ if (nameHandle.isValid())
+ {
+ mParams->setParamString(nameHandle, name);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
+
+void ClothingAssetImpl::clearMapping(uint32_t graphicalLodIndex)
+{
+ if (mGraphicalLods[graphicalLodIndex]->immediateClothMap.buf != NULL)
+ {
+ ParamArray<uint32_t> immediateClothMap(mGraphicalLods[graphicalLodIndex], "immediateClothMap", reinterpret_cast<ParamDynamicArrayStruct*>(&mGraphicalLods[graphicalLodIndex]->immediateClothMap));
+ immediateClothMap.clear();
+ }
+ if (mGraphicalLods[graphicalLodIndex]->skinClothMapB.buf != NULL)
+ {
+ ParamArray<ClothingGraphicalLodParametersNS::SkinClothMapB_Type> skinClothMapB(mGraphicalLods[graphicalLodIndex], "skinClothMapB", reinterpret_cast<ParamDynamicArrayStruct*>(&mGraphicalLods[graphicalLodIndex]->skinClothMapB));
+ skinClothMapB.clear();
+ }
+ if (mGraphicalLods[graphicalLodIndex]->tetraMap.buf != NULL)
+ {
+ ParamArray<ClothingGraphicalLodParametersNS::TetraLink_Type> tetraMap(mGraphicalLods[graphicalLodIndex], "tetraMap", reinterpret_cast<ParamDynamicArrayStruct*>(&mGraphicalLods[graphicalLodIndex]->tetraMap));
+ tetraMap.clear();
+ }
+}
+
+
+
+bool ClothingAssetImpl::findTriangleForImmediateVertex(uint32_t& faceIndex, uint32_t& indexInTriangle, uint32_t physVertIndex, ClothingPhysicalMeshParametersNS::PhysicalMesh_Type& physicalMesh) const
+{
+ // find triangle with smallest faceIndex, indices have been sorted during authoring
+ // such that simulated triangles are first
+ for (uint32_t physIndex = 0; physIndex < (uint32_t)physicalMesh.indices.arraySizes[0]; physIndex++)
+ {
+ if (physicalMesh.indices.buf[physIndex] == physVertIndex)
+ {
+ // this is a triangle that contains the vertex from the immediate map)
+ uint32_t currentFaceIndex = physIndex - (physIndex%3);
+
+ faceIndex = currentFaceIndex;
+ indexInTriangle = physIndex - faceIndex;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+
+// we can't just regenerate the skinClothMap, because master/slave info is only available during authoring
+bool ClothingAssetImpl::mergeMapping(ClothingGraphicalLodParameters* graphicalLod)
+{
+ if (graphicalLod->immediateClothMap.buf == NULL)
+ return false;
+
+ ParamArray<uint32_t> immediateMap(graphicalLod, "immediateClothMap", reinterpret_cast<ParamDynamicArrayStruct*>(&graphicalLod->immediateClothMap));
+
+ // size of immediateMap (equals number of graphical vertices)
+ uint32_t immediateCount = (uint32_t)graphicalLod->immediateClothMap.arraySizes[0];
+
+ ParamArray<SkinClothMap> skinClothMap(graphicalLod, "skinClothMap",
+ reinterpret_cast<ParamDynamicArrayStruct*>(&graphicalLod->skinClothMap));
+
+ uint32_t oldSkinMapSize = skinClothMap.size();
+ skinClothMap.resize(immediateCount);
+
+ SkinClothMap* mapEntry = &skinClothMap[oldSkinMapSize];
+
+ // get RenderMeshAsset
+ ClothingGraphicalMeshAssetWrapper renderMesh(reinterpret_cast<RenderMeshAssetIntl*>(graphicalLod->renderMeshAssetPointer));
+ uint32_t numSubmeshes = renderMesh.getSubmeshCount();
+
+ ClothingPhysicalMeshParametersNS::PhysicalMesh_Type* physicalMesh = &mPhysicalMeshes[graphicalLod->physicalMeshId]->physicalMesh;
+ PX_ASSERT(physicalMesh != NULL);
+
+ // some updates for the case where we didn't have a skinClothMap yet
+ if (graphicalLod->skinClothMapThickness == 0.0f)
+ {
+ graphicalLod->skinClothMapThickness = 1.0f;
+ }
+ if (graphicalLod->skinClothMapOffset == 0.0f)
+ {
+ graphicalLod->skinClothMapOffset = DEFAULT_PM_OFFSET_ALONG_NORMAL_FACTOR * physicalMesh->averageEdgeLength;
+ }
+
+ uint32_t invalidCount = 0;
+
+ // iterate through immediate map, append verts to skinClothMap that are not yet in there
+ uint32_t mapVertIndex = 0;
+ for (uint32_t submeshIndex = 0; submeshIndex < numSubmeshes; ++submeshIndex)
+ {
+ RenderDataFormat::Enum outFormat;
+ const PxVec4* tangents = (const PxVec4*)renderMesh.getVertexBuffer(submeshIndex, RenderVertexSemantic::TANGENT, outFormat);
+ PX_ASSERT(tangents == NULL || outFormat == RenderDataFormat::FLOAT4);
+
+ const PxVec3* positions = (const PxVec3*)renderMesh.getVertexBuffer(submeshIndex, RenderVertexSemantic::POSITION, outFormat);
+ PX_ASSERT(positions == NULL || outFormat == RenderDataFormat::FLOAT3);
+
+ const PxVec3* normals = (const PxVec3*)renderMesh.getVertexBuffer(submeshIndex, RenderVertexSemantic::NORMAL, outFormat);
+ PX_ASSERT(normals == NULL || outFormat == RenderDataFormat::FLOAT3);
+
+ for (uint32_t submeshVertIndex = 0; submeshVertIndex < renderMesh.getNumVertices(submeshIndex); ++submeshVertIndex, ++mapVertIndex)
+ {
+ PX_ASSERT(mapVertIndex < immediateCount);
+
+ uint32_t physVertIndex = 0;
+ if (immediateMap[mapVertIndex] == ClothingConstants::ImmediateClothingInvalidValue)
+ {
+ ++invalidCount;
+ continue;
+ }
+
+ physVertIndex = immediateMap[mapVertIndex] & ClothingConstants::ImmediateClothingReadMask;
+
+ if ((immediateMap[mapVertIndex] & ClothingConstants::ImmediateClothingInSkinFlag) > 0)
+ {
+ // in that case physVertIndex is the index in the skinClothMap.
+ // set it to the current index, so we can sort it afterwards
+ skinClothMap[physVertIndex].vertexIndexPlusOffset = mapVertIndex;
+ continue;
+ }
+
+ // find triangle mapping
+ uint32_t faceIndex = UINT32_MAX;
+ uint32_t indexInTriangle = UINT32_MAX;
+ findTriangleForImmediateVertex(faceIndex, indexInTriangle, physVertIndex, *physicalMesh);
+
+ mapEntry->vertexIndex0 = physicalMesh->indices.buf[faceIndex + 0];
+ mapEntry->vertexIndex1 = physicalMesh->indices.buf[faceIndex + 1];
+ mapEntry->vertexIndex2 = physicalMesh->indices.buf[faceIndex + 2];
+
+ // for immediate skinned verts
+ // position, normal and tangent all have the same barycentric coord on the triangle
+ PxVec3 bary(0.0f);
+ if (indexInTriangle < 2)
+ {
+ bary[indexInTriangle] = 1.0f;
+ }
+
+ mapEntry->vertexBary = bary;
+ // mapEntry->vertexBary.z = 0 because it's on the triangle
+
+ // offset the normal
+ mapEntry->normalBary = bary;
+ mapEntry->normalBary.z = graphicalLod->skinClothMapOffset;
+
+ // we need to compute tangent bary's because there are no tangents on physical mesh
+ bary.x = bary.y = bary.z = UINT32_MAX;
+ if (positions != NULL && normals != NULL && tangents != NULL)
+ {
+ PxVec3 dummy(0.0f);
+ PxVec3 position = positions[submeshVertIndex];
+ PxVec3 tangent = tangents[submeshVertIndex].getXYZ();
+
+ // prepare triangle data
+ TriangleWithNormals triangle;
+ triangle.valid = 0;
+ triangle.faceIndex0 = faceIndex;
+ PxVec3* physNormals = physicalMesh->skinningNormals.buf;
+ if (physNormals == NULL)
+ {
+ physNormals = physicalMesh->normals.buf;
+ }
+ PX_ASSERT(physNormals != NULL);
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ uint32_t triVertIndex = physicalMesh->indices.buf[triangle.faceIndex0 + j];
+ triangle.vertices[j] = physicalMesh->vertices.buf[triVertIndex];
+ triangle.normals[j] = physNormals[triVertIndex];
+ }
+ triangle.init();
+
+ ModuleClothingHelpers::computeTriangleBarys(triangle, dummy, dummy, position + tangent, graphicalLod->skinClothMapOffset, 0, true);
+ mapEntry->tangentBary = triangle.tempBaryTangent;
+ }
+
+ mapEntry->vertexIndexPlusOffset = mapVertIndex;
+ mapEntry++;
+ }
+ }
+
+ skinClothMap.resize(skinClothMap.size() - invalidCount);
+
+ // make sure skinClothMap is sorted by graphical vertex order
+ nvidia::sort(graphicalLod->skinClothMap.buf, (uint32_t)graphicalLod->skinClothMap.arraySizes[0], SkinClothMapPredicate<ClothingGraphicalLodParametersNS::SkinClothMapD_Type>());
+
+ immediateMap.clear();
+
+ // notify actors of the asset change
+ for (uint32_t i = 0; i < getNumActors(); ++i)
+ {
+ ClothingActorImpl& actor = DYNAMIC_CAST(ClothingActorProxy*)(mActors.getResource(i))->impl;
+ actor.reinitActorData();
+ }
+
+ return true;
+}
+
+
+void ClothingAssetImpl::updateBoundingBox()
+{
+ PxBounds3 tempBounds;
+ tempBounds.setEmpty();
+
+ for (uint32_t graphicalMeshId = 0; graphicalMeshId < mGraphicalLods.size(); graphicalMeshId++)
+ {
+ if (mGraphicalLods[graphicalMeshId]->renderMeshAssetPointer == NULL)
+ continue;
+
+ RenderMeshAssetIntl* renderMeshAsset = reinterpret_cast<RenderMeshAssetIntl*>(mGraphicalLods[graphicalMeshId]->renderMeshAssetPointer);
+ for (uint32_t submeshIndex = 0; submeshIndex < renderMeshAsset->getSubmeshCount(); submeshIndex++)
+ {
+ const VertexBuffer& vb = renderMeshAsset->getInternalSubmesh(submeshIndex).getVertexBuffer();
+ const VertexFormat& vf = vb.getFormat();
+ uint32_t bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(nvidia::apex::RenderVertexSemantic::POSITION));
+ RenderDataFormat::Enum positionFormat;
+ const PxVec3* pos = (const PxVec3*)vb.getBufferAndFormat(positionFormat, bufferIndex);
+ PX_ASSERT(positionFormat == nvidia::RenderDataFormat::FLOAT3);
+ const uint32_t numVertices = renderMeshAsset->getInternalSubmesh(submeshIndex).getVertexCount(0);
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ tempBounds.include(pos[i]);
+ }
+ }
+ }
+ for (uint32_t i = 0; i < mPhysicalMeshes.size(); i++)
+ {
+ AbstractMeshDescription other;
+ other.pPosition = mPhysicalMeshes[i]->physicalMesh.vertices.buf;
+
+ for (uint32_t j = 0; j < other.numVertices; j++)
+ {
+ tempBounds.include(other.pPosition[j]);
+ }
+ }
+
+ mParams->boundingBox = tempBounds;
+}
+
+
+
+float ClothingAssetImpl::getMaxDistReduction(ClothingPhysicalMeshParameters& physicalMesh, float maxDistanceMultiplier) const
+{
+ return physicalMesh.physicalMesh.maximumMaxDistance * (1.0f - maxDistanceMultiplier);
+}
+
+
+
+#ifndef WITHOUT_PVD
+void ClothingAssetImpl::initPvdInstances(pvdsdk::PvdDataStream& pvdStream)
+{
+ ApexResourceInterface* pvdInstance = static_cast<ApexResourceInterface*>(this);
+
+ // Asset Params
+ pvdStream.createInstance(pvdsdk::NamespacedName(APEX_PVD_NAMESPACE, "ClothingAssetParameters"), mParams);
+ pvdStream.setPropertyValue(pvdInstance, "AssetParams", pvdsdk::DataRef<const uint8_t>((const uint8_t*)&mParams, sizeof(ClothingAssetParameters*)), pvdsdk::getPvdNamespacedNameForType<pvdsdk::ObjectRef>());
+
+ // update asset param properties (should we do this per frame? if so, how?)
+ pvdsdk::ApexPvdClient* client = GetInternalApexSDK()->getApexPvdClient();
+ PX_ASSERT(client != NULL);
+ client->updatePvd(mParams, *mParams);
+
+ mActors.initPvdInstances(pvdStream);
+}
+
+
+
+void ClothingAssetImpl::destroyPvdInstances()
+{
+ pvdsdk::ApexPvdClient* client = GetInternalApexSDK()->getApexPvdClient();
+ if (client != NULL)
+ {
+ if (client->isConnected() && client->getPxPvd().getInstrumentationFlags() & PxPvdInstrumentationFlag::eDEBUG)
+ {
+ pvdsdk::PvdDataStream* pvdStream = client->getDataStream();
+ {
+ if (pvdStream != NULL)
+ {
+ client->updatePvd(mParams, *mParams, pvdsdk::PvdAction::DESTROY);
+ pvdStream->destroyInstance(mParams);
+ }
+ }
+ }
+ }
+}
+#endif
+
+}
+} // namespace nvidia
+
+
diff --git a/APEX_1.4/module/clothing/src/ClothingCollisionImpl.cpp b/APEX_1.4/module/clothing/src/ClothingCollisionImpl.cpp
new file mode 100644
index 00000000..ea86b0d3
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/ClothingCollisionImpl.cpp
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+
+#include "ClothingCollisionImpl.h"
+#include "ClothingActorImpl.h"
+
+using namespace nvidia;
+using namespace apex;
+using namespace clothing;
+
+
+ClothingCollisionImpl::ClothingCollisionImpl(ResourceList& list, ClothingActorImpl& owner) :
+mOwner(owner),
+mInRelease(false),
+mId(-1)
+{
+ list.add(*this);
+}
+
+
+void ClothingCollisionImpl::release()
+{
+ if (mInRelease)
+ return;
+ mInRelease = true;
+ mOwner.releaseCollision(*this);
+}
+
+
+void ClothingCollisionImpl::destroy()
+{
+ delete this;
+}
+
+
+void ClothingPlaneImpl::setPlane(const PxPlane& plane)
+{
+ mPlane = plane;
+ mOwner.notifyCollisionChange();
+}
+
+
+void ClothingSphereImpl::setPosition(const PxVec3& position)
+{
+ mPosition = position;
+ mOwner.notifyCollisionChange();
+}
+
+
+void ClothingSphereImpl::setRadius(float radius)
+{
+ mRadius = radius;
+ mOwner.notifyCollisionChange();
+}
+
+
+uint32_t ClothingTriangleMeshImpl::lockTriangles(const uint32_t** ids, const PxVec3** triangles)
+{
+ mLock.lock();
+ uint32_t numTriangles = mIds.size();
+ if (ids != NULL)
+ {
+ *ids = (numTriangles > 0) ? &mIds[0] : NULL;
+ }
+ if (triangles != NULL)
+ {
+ *triangles = (numTriangles > 0) ? &mTriangles[0] : NULL;
+ }
+ return numTriangles;
+};
+
+
+uint32_t ClothingTriangleMeshImpl::lockTrianglesWrite(const uint32_t** ids, PxVec3** triangles)
+{
+ mLock.lock();
+ uint32_t numTriangles = mIds.size();
+ if (ids != NULL)
+ {
+ *ids = (numTriangles > 0) ? &mIds[0] : NULL;
+ }
+ if (triangles != NULL)
+ {
+ *triangles = (numTriangles > 0) ? &mTriangles[0] : NULL;
+ }
+
+ mOwner.notifyCollisionChange();
+ return numTriangles;
+};
+
+
+void ClothingTriangleMeshImpl::unlockTriangles()
+{
+ mLock.unlock();
+};
+
+
+void ClothingTriangleMeshImpl::addTriangle(uint32_t id, const PxVec3& v0, const PxVec3& v1, const PxVec3& v2)
+{
+ mLock.lock();
+ ClothingTriangle& tri = mAddedTriangles.insert();
+ tri.v[0] = v0;
+ tri.v[1] = v1;
+ tri.v[2] = v2;
+ tri.id = id;
+ mLock.unlock();
+
+ mOwner.notifyCollisionChange();
+}
+
+
+void ClothingTriangleMeshImpl::addTriangles(const uint32_t* ids, const PxVec3* triangleVertices, uint32_t numTriangles)
+{
+ mLock.lock();
+ for (uint32_t i = 0; i < numTriangles; ++i)
+ {
+ ClothingTriangle& tri = mAddedTriangles.insert();
+ tri.v[0] = triangleVertices[3*i+0];
+ tri.v[1] = triangleVertices[3*i+1];
+ tri.v[2] = triangleVertices[3*i+2];
+ tri.id = ids[i];
+ }
+ mLock.unlock();
+
+ mOwner.notifyCollisionChange();
+}
+
+
+void ClothingTriangleMeshImpl::removeTriangle(uint32_t id)
+{
+ mLock.lock();
+ mRemoved.pushBack(id);
+ mLock.unlock();
+
+ mOwner.notifyCollisionChange();
+}
+
+
+void ClothingTriangleMeshImpl::removeTriangles(const uint32_t* ids, uint32_t numTriangles)
+{
+ mLock.lock();
+ mRemoved.reserve(mRemoved.size() + numTriangles);
+ for (uint32_t i = 0; i < numTriangles; ++i)
+ {
+ mRemoved.pushBack(ids[i]);
+ }
+ mLock.unlock();
+
+ mOwner.notifyCollisionChange();
+}
+
+
+void ClothingTriangleMeshImpl::clearTriangles()
+{
+ mLock.lock();
+ mTriangles.clear();
+ mIds.clear();
+ mLock.unlock();
+
+ mOwner.notifyCollisionChange();
+}
+
+
+void ClothingTriangleMeshImpl::setPose(PxMat44 pose)
+{
+ mPose = pose;
+
+ mOwner.notifyCollisionChange();
+}
+
+
+void ClothingTriangleMeshImpl::sortAddAndRemoves()
+{
+ if (mRemoved.size() > 1)
+ {
+ nvidia::sort<uint32_t>(&mRemoved[0], mRemoved.size());
+ }
+
+ if (mAddedTriangles.size() > 1)
+ {
+ nvidia::sort<ClothingTriangle>(&mAddedTriangles[0], mAddedTriangles.size());
+ }
+}
+
+
+void ClothingTriangleMeshImpl::update(const PxTransform& tm, const nvidia::Array<PxVec3>& allTrianglesOld, nvidia::Array<PxVec3>& allTrianglesOldTemp, nvidia::Array<PxVec3>& allTriangles)
+{
+ Array<PxVec3> trianglesOldTemp;
+ Array<PxVec3> trianglesTemp;
+ Array<uint32_t> idsTemp;
+
+ mLock.lock();
+
+ // sort all arrays to keep increasing id order
+ sortAddAndRemoves();
+
+ uint32_t triIdx = 0;
+ uint32_t numTriangles = mIds.size();
+
+ uint32_t removedIdx = 0;
+ uint32_t numRemoved = mRemoved.size();
+
+ uint32_t addedIdx = 0;
+ uint32_t numAdded = mAddedTriangles.size();
+
+ while (triIdx < numTriangles || removedIdx < numRemoved || addedIdx < numAdded)
+ {
+ PX_ASSERT(allTriangles.size() % 3 == 0);
+ PX_ASSERT(allTrianglesOldTemp.size() % 3 == 0);
+
+ uint32_t triangleId = (triIdx < numTriangles) ? mIds[triIdx] : UINT32_MAX;
+ uint32_t removedId = (removedIdx < numRemoved) ? mRemoved[removedIdx] : UINT32_MAX;
+ uint32_t addedId = (addedIdx < numAdded) ? mAddedTriangles[addedIdx].id : UINT32_MAX;
+
+ if (triangleId < removedId && triangleId <= addedId)
+ {
+ // handle existing triangle
+
+ // when a triangle with an already existing id is added, just update the value
+ PxVec3* v[3];
+ if (addedId == triangleId)
+ {
+ // new values from addTriangle
+ v[0] = &mAddedTriangles[addedIdx].v[0];
+ v[1] = &mAddedTriangles[addedIdx].v[1];
+ v[2] = &mAddedTriangles[addedIdx].v[2];
+ ++addedIdx;
+ }
+ else
+ {
+ // old values or edited values from lockTrianglesWrite
+ v[0] = &mTriangles[3*triIdx+0];
+ v[1] = &mTriangles[3*triIdx+1];
+ v[2] = &mTriangles[3*triIdx+2];
+ }
+ PxVec3 vGlobal[3] = {tm.transform(*v[0]), tm.transform(*v[1]), tm.transform(*v[2])};
+
+ // update triangle collision object with local triangle position
+ trianglesTemp.pushBack(*v[0]);
+ trianglesTemp.pushBack(*v[1]);
+ trianglesTemp.pushBack(*v[2]);
+ idsTemp.pushBack(mIds[triIdx]);
+
+ // write global triangle pos from last frame.
+ // mId contains the offset in the global triangles array
+ if (mId >= 0 && mId < (int32_t)allTrianglesOld.size())
+ {
+ allTrianglesOldTemp.pushBack(allTrianglesOld[mId + 3*triIdx+0]);
+ allTrianglesOldTemp.pushBack(allTrianglesOld[mId + 3*triIdx+1]);
+ allTrianglesOldTemp.pushBack(allTrianglesOld[mId + 3*triIdx+2]);
+ }
+ else
+ {
+ // if we cannot access an old buffer (e.g. when the simulation has changed)
+ // we just use the current pos as old pos as well
+ allTrianglesOldTemp.pushBack(vGlobal[0]);
+ allTrianglesOldTemp.pushBack(vGlobal[1]);
+ allTrianglesOldTemp.pushBack(vGlobal[2]);
+ }
+
+ // update internal global array
+ allTriangles.pushBack(vGlobal[0]);
+ allTriangles.pushBack(vGlobal[1]);
+ allTriangles.pushBack(vGlobal[2]);
+ ++triIdx;
+ }
+ else if (addedId < removedId)
+ {
+ // handle new triangle
+
+ // update triangle collision object with local triangle position
+ trianglesTemp.pushBack(mAddedTriangles[addedIdx].v[0]);
+ trianglesTemp.pushBack(mAddedTriangles[addedIdx].v[1]);
+ trianglesTemp.pushBack(mAddedTriangles[addedIdx].v[2]);
+ idsTemp.pushBack(addedId);
+
+ // set old and new positions in global array
+ PxVec3 v[3] = {tm.transform(mAddedTriangles[addedIdx].v[0]), tm.transform(mAddedTriangles[addedIdx].v[1]), tm.transform(mAddedTriangles[addedIdx].v[2])};
+ allTrianglesOldTemp.pushBack(v[0]);
+ allTrianglesOldTemp.pushBack(v[1]);
+ allTrianglesOldTemp.pushBack(v[2]);
+ allTriangles.pushBack(v[0]);
+ allTriangles.pushBack(v[1]);
+ allTriangles.pushBack(v[2]);
+ ++addedIdx;
+ }
+ else
+ {
+ // handle removal
+
+ ++removedIdx;
+ if (removedId == triangleId)
+ {
+ // an existing triangle was removed
+ ++triIdx;
+ }
+ if (removedId == addedId)
+ {
+ // a newly added triangle is also removed
+ ++addedIdx;
+ }
+ }
+
+ }
+
+ mTriangles.swap(trianglesTemp);
+ mIds.swap(idsTemp);
+
+ mRemoved.clear();
+ mAddedTriangles.clear();
+
+ mLock.unlock();
+
+ // use id to store the offset in the global triangles arrays
+ PX_ASSERT(allTriangles.size() % 3 == 0);
+ mId = (int32_t)allTriangles.size() - (int32_t)mTriangles.size();
+} \ No newline at end of file
diff --git a/APEX_1.4/module/clothing/src/ClothingCooking.cpp b/APEX_1.4/module/clothing/src/ClothingCooking.cpp
new file mode 100644
index 00000000..00950e85
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/ClothingCooking.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+
+#include "ApexDefs.h"
+
+#include "ClothingCooking.h"
+#include "PsMemoryBuffer.h"
+#include "ParamArray.h"
+
+#include "CookingAbstract.h"
+
+#include "ClothingScene.h"
+
+#include "PsAtomic.h"
+
+namespace nvidia
+{
+namespace clothing
+{
+
+void ClothingCookingLock::lockCooking()
+{
+ atomicIncrement(&mNumCookingDependencies);
+}
+
+
+void ClothingCookingLock::unlockCooking()
+{
+ atomicDecrement(&mNumCookingDependencies);
+}
+
+
+ClothingCookingTask::ClothingCookingTask(ClothingScene* clothingScene, CookingAbstract& _job) : job(&_job), nextTask(NULL),
+ mState(Uninit), mClothingScene(clothingScene), mResult(NULL), mLockedObject(NULL)
+{
+ PX_ASSERT(((size_t)(void*)(&mState) & 0x00000003) == 0); // check alignment, mState must be aligned for the atomic exchange operations
+
+ PX_ASSERT(job != NULL);
+}
+
+
+ClothingCookingTask::~ClothingCookingTask()
+{
+ if (job != NULL)
+ {
+ PX_DELETE_AND_RESET(job);
+ }
+}
+
+
+void ClothingCookingTask::initCooking(PxTaskManager& tm, PxBaseTask* c)
+{
+ PxLightCpuTask::setContinuation(tm, c);
+
+ int32_t oldState = atomicCompareExchange((int32_t*)(&mState), WaitForRun, Uninit);
+ PX_ASSERT(oldState == Uninit);
+ PX_UNUSED(oldState);
+}
+
+
+void ClothingCookingTask::run()
+{
+ // run
+ NvParameterized::Interface* result = NULL;
+ int32_t oldState = atomicCompareExchange((int32_t*)(&mState), Running, WaitForRun);
+ PX_ASSERT(oldState != ReadyForRelease && oldState != Aborting && oldState != WaitForFetch);
+ if (oldState == WaitForRun) // the change was successful
+ {
+ result = job->execute();
+ }
+
+ unlockObject();
+
+ // try to run the next task. Must be called before in a state where it will be deleted
+ mClothingScene->submitCookingTask(NULL);
+
+ // finished
+ oldState = atomicCompareExchange((int32_t*)(&mState), WaitForFetch, Running);
+ if (oldState == Running)
+ {
+ mResult = result;
+ }
+ else
+ {
+ if (result != NULL)
+ {
+ result->destroy();
+ result = NULL;
+ }
+ atomicExchange((int32_t*)(&mState), ReadyForRelease);
+ PX_ASSERT(mResult == NULL);
+ }
+}
+
+NvParameterized::Interface* ClothingCookingTask::getResult()
+{
+ if (mResult != NULL)
+ {
+ int32_t oldState = atomicCompareExchange((int32_t*)(&mState), ReadyForRelease, WaitForFetch);
+ PX_ASSERT(oldState == WaitForFetch);
+ PX_UNUSED(oldState);
+ return mResult;
+ }
+ return NULL;
+}
+
+void ClothingCookingTask::lockObject(ClothingCookingLock* lockedObject)
+{
+ if (mLockedObject != NULL)
+ {
+ mLockedObject->unlockCooking();
+ }
+
+ mLockedObject = lockedObject;
+ if (mLockedObject != NULL)
+ {
+ mLockedObject->lockCooking();
+ }
+}
+
+void ClothingCookingTask::unlockObject()
+{
+ if (mLockedObject != NULL)
+ {
+ mLockedObject->unlockCooking();
+ mLockedObject = NULL;
+ }
+}
+
+void ClothingCookingTask::abort()
+{
+ int32_t oldState = atomicExchange((int32_t*)(&mState), Aborting);
+ PX_ASSERT(oldState >= WaitForRun);
+ if (oldState == WaitForFetch)
+ {
+ atomicExchange((int32_t*)(&mState), ReadyForRelease);
+ if (mResult != NULL)
+ {
+ NvParameterized::Interface* oldParam = mResult;
+ mResult = NULL;
+ oldParam->destroy();
+ }
+ unlockObject();
+ }
+ else if (oldState != Running)
+ {
+ PX_ASSERT(mResult == NULL);
+ atomicExchange((int32_t*)(&mState), ReadyForRelease);
+ unlockObject();
+ }
+}
+
+}
+}
+
diff --git a/APEX_1.4/module/clothing/src/ClothingPhysicalMeshImpl.cpp b/APEX_1.4/module/clothing/src/ClothingPhysicalMeshImpl.cpp
new file mode 100644
index 00000000..538a7e1a
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/ClothingPhysicalMeshImpl.cpp
@@ -0,0 +1,1576 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+
+#include "ApexDefs.h"
+
+#include "ClothingPhysicalMeshImpl.h"
+#include "ApexMeshHash.h"
+#include "ApexQuadricSimplifier.h"
+#include "ClothingAssetAuthoringImpl.h"
+#include "ModuleClothingImpl.h"
+
+#include "ApexPermute.h"
+#include "ApexSharedUtils.h"
+
+#include "PxStrideIterator.h"
+#include "PsMathUtils.h"
+#include "PsSort.h"
+
+namespace nvidia
+{
+namespace clothing
+{
+
+struct SortedEdge
+{
+ SortedEdge(uint32_t _i0, uint32_t _i1) : i0(PxMin(_i0, _i1)), i1(PxMax(_i0, _i1)) {}
+
+ bool operator==(const SortedEdge& other) const
+ {
+ return i0 == other.i0 && i1 == other.i1;
+ }
+ bool operator()(const SortedEdge& s1, const SortedEdge& s2) const
+ {
+ if (s1.i0 != s2.i0)
+ {
+ return s1.i0 < s2.i0;
+ }
+
+ return s1.i1 < s2.i1;
+ }
+
+ uint32_t i0, i1;
+};
+
+ClothingPhysicalMeshImpl::ClothingPhysicalMeshImpl(ModuleClothingImpl* module, ClothingPhysicalMeshParameters* params, ResourceList* list) :
+ mModule(module),
+ mParams(NULL),
+ ownsParams(false),
+ mSimplifier(NULL),
+ isDirty(false)
+{
+ if (params != NULL && nvidia::strcmp(params->className(), ClothingPhysicalMeshParameters::staticClassName()) != 0)
+ {
+ APEX_INTERNAL_ERROR(
+ "The parameterized interface is of type <%s> instead of <%s>. "
+ "An empty ClothingPhhsicalMesh has been created instead.",
+ params->className(),
+ ClothingPhysicalMeshParameters::staticClassName());
+
+ params = NULL;
+ }
+
+ if (params == NULL)
+ {
+ params = DYNAMIC_CAST(ClothingPhysicalMeshParameters*)(GetInternalApexSDK()->getParameterizedTraits()->createNvParameterized(ClothingPhysicalMeshParameters::staticClassName()));
+ ownsParams = true;
+ }
+ PX_ASSERT(params != NULL);
+
+ mParams = params;
+ mVertices.init(mParams, "physicalMesh.vertices", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->physicalMesh.vertices));
+ mNormals.init(mParams, "physicalMesh.normals", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->physicalMesh.normals));
+ mSkinningNormals.init(mParams, "physicalMesh.skinningNormals", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->physicalMesh.skinningNormals));
+ mConstrainCoefficients.init(mParams, "physicalMesh.constrainCoefficients", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->physicalMesh.constrainCoefficients));
+ mBoneIndices.init(mParams, "physicalMesh.boneIndices", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->physicalMesh.boneIndices));
+ mBoneWeights.init(mParams, "physicalMesh.boneWeights", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->physicalMesh.boneWeights));
+ mIndices.init(mParams, "physicalMesh.indices", reinterpret_cast<ParamDynamicArrayStruct*>(&mParams->physicalMesh.indices));
+
+ mNumSimulatedVertices = mParams->physicalMesh.numSimulatedVertices;
+ mNumMaxDistanc0Vertices = mParams->physicalMesh.numMaxDistance0Vertices;
+ mNumSimulatedIndices = mParams->physicalMesh.numSimulatedIndices;
+
+ mParams->referenceCount++;
+
+ mParams->setSerializationCallback(this);
+#if 0
+ // debugging only
+ char buf[32];
+ sprintf_s(buf, 32, "++ %p -> %d\n", mParams, mParams->referenceCount);
+ OutputDebugString(buf);
+#endif
+
+ if (mParams->physicalMesh.shortestEdgeLength == 0.0f)
+ {
+ computeEdgeLengths();
+ }
+
+ list->add(*this);
+}
+
+
+
+void ClothingPhysicalMeshImpl::release()
+{
+ PX_ASSERT(mParams != NULL);
+ if (mParams != NULL)
+ {
+ // make sure everything is set up correctly before we let the param object live on its own
+ preSerialize(NULL);
+
+ mParams->setSerializationCallback(NULL);
+ }
+ mModule->releasePhysicalMesh(this);
+}
+
+
+
+void ClothingPhysicalMeshImpl::destroy()
+{
+ if (mSimplifier != NULL)
+ {
+ delete mSimplifier;
+ mSimplifier = NULL;
+ }
+
+ if (mParams != NULL)
+ {
+ mParams->referenceCount--;
+#if 0
+ // debugging only
+ char buf[32];
+ sprintf_s(buf, 32, "-- %p -> %d\n", mParams, mParams->referenceCount);
+ OutputDebugString(buf);
+#endif
+ }
+
+ if (ownsParams && mParams)
+ {
+ PX_ASSERT(mParams->referenceCount == 0);
+ mParams->destroy();
+ }
+
+ delete this;
+}
+
+
+
+void ClothingPhysicalMeshImpl::makeCopy(ClothingPhysicalMeshParameters* params)
+{
+ PX_ASSERT(mParams != NULL);
+ params->copy(*mParams);
+}
+
+
+
+void ClothingPhysicalMeshImpl::allocateNormalBuffer()
+{
+ mNormals.resize(mParams->physicalMesh.numVertices);
+}
+
+
+
+void ClothingPhysicalMeshImpl::allocateSkinningNormalsBuffer()
+{
+ mSkinningNormals.resize(mParams->physicalMesh.numVertices);
+}
+
+
+void ClothingPhysicalMeshImpl::allocateMasterFlagsBuffer()
+{
+ uint32_t numVertices = mVertices.size();
+ mMasterFlags.resize(numVertices);
+
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ mMasterFlags[i] = 0xffffffff;
+ }
+}
+
+
+void ClothingPhysicalMeshImpl::allocateConstrainCoefficientBuffer()
+{
+ WRITE_ZONE();
+ const uint32_t numVertices = mParams->physicalMesh.numVertices;
+ mConstrainCoefficients.resize(numVertices);
+
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ mConstrainCoefficients[i].maxDistance = PX_MAX_F32;
+ mConstrainCoefficients[i].collisionSphereRadius = PX_MAX_F32;
+ mConstrainCoefficients[i].collisionSphereDistance = PX_MAX_F32;
+ }
+}
+
+
+
+void ClothingPhysicalMeshImpl::allocateBoneIndexAndWeightBuffers()
+{
+ const uint32_t numBonesPerVertex = mParams->physicalMesh.numBonesPerVertex;
+ if (numBonesPerVertex == 0)
+ {
+ APEX_DEBUG_WARNING("Number of bones per vertex is set to 0. Not allocating memory.");
+ return;
+ }
+ const uint32_t numVertices = mParams->physicalMesh.numVertices;
+
+ mBoneIndices.resize(numBonesPerVertex * numVertices);
+
+ // PH: At one point we can start trying to safe this buffer
+ //if (numBonesPerVertex > 1)
+ {
+ mBoneWeights.resize(numBonesPerVertex * numVertices);
+ }
+}
+
+
+
+void ClothingPhysicalMeshImpl::freeAdditionalBuffers()
+{
+
+ mNormals.resize(0);
+ mSkinningNormals.resize(0);
+ mConstrainCoefficients.resize(0);
+ mBoneIndices.resize(0);
+ mBoneWeights.resize(0);
+ mParams->physicalMesh.numBonesPerVertex = 0;
+}
+
+
+
+uint32_t ClothingPhysicalMeshImpl::getNumVertices() const
+{
+ READ_ZONE();
+ if (mSimplifier != NULL)
+ {
+ return mSimplifier->getNumVertices() - mSimplifier->getNumDeletedVertices();
+ }
+
+ return mParams->physicalMesh.numVertices;
+}
+
+
+
+uint32_t ClothingPhysicalMeshImpl::getNumSimulatedVertices() const
+{
+ READ_ZONE();
+ return mParams->physicalMesh.numSimulatedVertices;
+}
+
+
+
+uint32_t ClothingPhysicalMeshImpl::getNumMaxDistance0Vertices() const
+{
+ READ_ZONE();
+ return mParams->physicalMesh.numMaxDistance0Vertices;
+}
+
+
+
+uint32_t ClothingPhysicalMeshImpl::getNumIndices() const
+{
+ READ_ZONE();
+ if (mSimplifier != NULL)
+ {
+ return mSimplifier->getNumTriangles() * 3;
+ }
+
+ return mParams->physicalMesh.numIndices;
+}
+
+
+
+uint32_t ClothingPhysicalMeshImpl::getNumSimulatedIndices() const
+{
+ READ_ZONE();
+ if (mSimplifier != NULL)
+ {
+ return mSimplifier->getNumTriangles() * 3;
+ }
+
+ return mParams->physicalMesh.numSimulatedIndices;
+}
+
+
+
+void ClothingPhysicalMeshImpl::getIndices(void* indexDestination, uint32_t byteStride, uint32_t numIndices) const
+{
+ READ_ZONE();
+ numIndices = PxMin(numIndices, mParams->physicalMesh.numIndices);
+
+ if (byteStride == 0)
+ {
+ byteStride = sizeof(uint32_t);
+ }
+
+ if (byteStride < sizeof(uint32_t))
+ {
+ APEX_INTERNAL_ERROR("byte stride is too small (%d)", byteStride);
+ return;
+ }
+
+ const_cast<ClothingPhysicalMeshImpl*>(this)->writeBackData();
+
+ uint8_t* destPtr = (uint8_t*)indexDestination;
+ for (uint32_t i = 0; i < numIndices; i++)
+ {
+ (uint32_t&)(*(destPtr + byteStride * i)) = mIndices[i];
+ }
+}
+
+
+
+void ClothingPhysicalMeshImpl::simplify(uint32_t subdivisions, int32_t maxSteps, float maxError, IProgressListener* progressListener)
+{
+ WRITE_ZONE();
+ if (mParams->physicalMesh.isTetrahedralMesh)
+ {
+ APEX_INVALID_OPERATION("Cannot simplify a tetrahedral mesh");
+ return;
+ }
+
+ if (mParams->physicalMesh.boneIndices.buf != NULL || mParams->physicalMesh.boneWeights.buf != NULL)
+ {
+ APEX_INVALID_OPERATION("Cannot simplif a triangle mesh with additional bone data");
+ return;
+ }
+
+
+ const uint32_t numVertices = mParams->physicalMesh.numVertices;
+ const uint32_t numIndices = mParams->physicalMesh.numIndices;
+
+ if (numVertices == 0 || numIndices == 0)
+ {
+ return;
+ }
+
+ HierarchicalProgressListener progress(100, progressListener);
+
+ if (mSimplifier == NULL)
+ {
+ progress.setSubtaskWork(80, "Init simplificator");
+ mSimplifier = PX_NEW(ApexQuadricSimplifier);
+
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ mSimplifier->registerVertex(mVertices[i]);
+ }
+
+ for (uint32_t i = 0; i < numIndices; i += 3)
+ {
+ mSimplifier->registerTriangle(mIndices[i + 0], mIndices[i + 1], mIndices[i + 2]);
+ }
+
+ mSimplifier->endRegistration(false, &progress);
+ progress.completeSubtask();
+ }
+
+ progress.setSubtaskWork(-1, "Simplification steps");
+
+ uint32_t steps = mSimplifier->simplify(subdivisions, maxSteps, maxError, &progress);
+
+ if (!isDirty)
+ {
+ isDirty = steps > 0;
+ }
+
+ progress.completeSubtask();
+}
+
+
+
+void ClothingPhysicalMeshImpl::setGeometry(bool tetraMesh, uint32_t numVertices, uint32_t vertexByteStride, const void* vertices,
+ const uint32_t* masterFlags, uint32_t numIndices, uint32_t indexByteStride, const void* indices)
+{
+ WRITE_ZONE();
+ if (vertexByteStride < sizeof(PxVec3))
+ {
+ APEX_INTERNAL_ERROR("vertexByteStride is too small (%d)", vertexByteStride);
+ return;
+ }
+
+ if (indexByteStride < sizeof(uint32_t))
+ {
+ APEX_INTERNAL_ERROR("indexByteStride is too small (%d)", indexByteStride);
+ return;
+ }
+
+ if (numVertices > 0 && vertices == NULL)
+ {
+ APEX_INTERNAL_ERROR("vertex pointer is NULL");
+ return;
+ }
+
+ if (numIndices > 0 && indices == NULL)
+ {
+ APEX_INTERNAL_ERROR("index pointer is NULL");
+ return;
+ }
+
+ if (tetraMesh && (numIndices % 4 != 0))
+ {
+ APEX_INTERNAL_ERROR("Indices must be a multiple of 4 for physical tetrahedral meshes");
+ return;
+ }
+
+ if (!tetraMesh && (numIndices % 3 != 0))
+ {
+ APEX_INTERNAL_ERROR("Indices must be a multiple of 3 for physical meshes");
+ return;
+ }
+
+ mParams->physicalMesh.isTetrahedralMesh = tetraMesh;
+
+ mParams->physicalMesh.numVertices = numVertices;
+ mParams->physicalMesh.numSimulatedVertices = numVertices;
+ mParams->physicalMesh.numMaxDistance0Vertices = 0;
+
+ mVertices.resize(numVertices);
+ mMasterFlags.resize(numVertices);
+
+ mNormals.resize(0);
+ mSkinningNormals.resize(0);
+
+ const uint8_t* srcVertices = (const uint8_t*)vertices;
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ const PxVec3& currVec = *(const PxVec3*)(srcVertices + vertexByteStride * i);
+ mVertices[i] = currVec;
+
+ mMasterFlags[i] = masterFlags != NULL ? masterFlags[i] : 0xffffffff;
+ }
+
+
+ if (tetraMesh || !removeDuplicatedTriangles(numIndices, indexByteStride, indices))
+ {
+ mParams->physicalMesh.numIndices = numIndices;
+ mParams->physicalMesh.numSimulatedIndices = numIndices;
+ mIndices.resize(numIndices);
+
+ const uint8_t* srcIndices = (const uint8_t*)indices;
+ for (uint32_t i = 0; i < numIndices; i++)
+ {
+ const uint32_t currIndex = *(const uint32_t*)(srcIndices + indexByteStride * i);
+ mIndices[i] = currIndex;
+ }
+ }
+
+ if (mSimplifier != NULL)
+ {
+ delete mSimplifier;
+ mSimplifier = NULL;
+ }
+
+ clearMiscBuffers();
+ computeEdgeLengths();
+
+ if (!mParams->physicalMesh.isTetrahedralMesh)
+ {
+ mSkinningNormals.resize(numVertices);
+ updateSkinningNormals();
+ }
+}
+
+
+
+bool ClothingPhysicalMeshImpl::getIndices(uint32_t* indices, uint32_t byteStride) const
+{
+ READ_ZONE();
+ if (mIndices.size() == 0)
+ {
+ return false;
+ }
+
+ if (byteStride == 0)
+ {
+ byteStride = sizeof(uint32_t);
+ }
+
+ if (byteStride < sizeof(uint32_t))
+ {
+ APEX_INTERNAL_ERROR("bytestride too small (%d)", byteStride);
+ return false;
+ }
+
+ const_cast<ClothingPhysicalMeshImpl*>(this)->writeBackData();
+
+ const uint32_t numIndices = mParams->physicalMesh.numIndices;
+
+ PxStrideIterator<uint32_t> iterator(indices, byteStride);
+ for (uint32_t i = 0; i < numIndices; i++, ++iterator)
+ {
+ *iterator = mIndices[i];
+ }
+
+ return true;
+}
+
+
+
+bool ClothingPhysicalMeshImpl::getVertices(PxVec3* vertices, uint32_t byteStride) const
+{
+ READ_ZONE();
+ if (mVertices.size() == 0)
+ {
+ return false;
+ }
+
+ if (byteStride == 0)
+ {
+ byteStride = sizeof(PxVec3);
+ }
+
+ if (byteStride < sizeof(PxVec3))
+ {
+ APEX_INTERNAL_ERROR("bytestride too small (%d)", byteStride);
+ return false;
+ }
+
+ const_cast<ClothingPhysicalMeshImpl*>(this)->writeBackData();
+
+ const uint32_t numVertices = mParams->physicalMesh.numVertices;
+
+ PxStrideIterator<PxVec3> iterator(vertices, byteStride);
+ for (uint32_t i = 0; i < numVertices; i++, ++iterator)
+ {
+ *iterator = mVertices[i];
+ }
+
+ return true;
+}
+
+
+
+bool ClothingPhysicalMeshImpl::getNormals(PxVec3* normals, uint32_t byteStride) const
+{
+ READ_ZONE();
+ if (mNormals.size() == 0)
+ {
+ return false;
+ }
+
+ if (byteStride == 0)
+ {
+ byteStride = sizeof(PxVec3);
+ }
+
+ if (byteStride < sizeof(PxVec3))
+ {
+ APEX_INTERNAL_ERROR("bytestride too small (%d)", byteStride);
+ return false;
+ }
+
+ const_cast<ClothingPhysicalMeshImpl*>(this)->writeBackData();
+
+ const uint32_t numVertices = mParams->physicalMesh.numVertices;
+
+ PxStrideIterator<PxVec3> iterator(normals, byteStride);
+ for (uint32_t i = 0; i < numVertices; i++, ++iterator)
+ {
+ *iterator = mNormals[i];
+ }
+
+ return true;
+}
+
+
+
+bool ClothingPhysicalMeshImpl::getBoneIndices(uint16_t* boneIndices, uint32_t byteStride) const
+{
+ READ_ZONE();
+ if (mBoneIndices.size() == 0)
+ {
+ return false;
+ }
+
+ const uint32_t numBonesPerVertex = mParams->physicalMesh.numBonesPerVertex;
+ if (byteStride == 0)
+ {
+ byteStride = numBonesPerVertex * sizeof(uint16_t);
+ }
+
+ if (byteStride < numBonesPerVertex * sizeof(uint16_t))
+ {
+ APEX_INTERNAL_ERROR("bytestride too small (%d)", byteStride);
+ return false;
+ }
+
+ const uint32_t numElements = mParams->physicalMesh.numVertices * numBonesPerVertex;
+
+ PxStrideIterator<uint16_t> iterator(boneIndices, byteStride);
+ for (uint32_t i = 0; i < numElements; i += numBonesPerVertex, ++iterator)
+ {
+ for (uint32_t j = 0; j < numBonesPerVertex; j++)
+ {
+ uint16_t* current = iterator.ptr();
+ current[j] = mBoneIndices[i + j];
+ }
+ }
+
+ return true;
+}
+
+
+
+bool ClothingPhysicalMeshImpl::getBoneWeights(float* boneWeights, uint32_t byteStride) const
+{
+ READ_ZONE();
+ if (mBoneWeights.size() == 0)
+ {
+ return false;
+ }
+
+ const uint32_t numBonesPerVertex = mParams->physicalMesh.numBonesPerVertex;
+ if (byteStride == 0)
+ {
+ byteStride = numBonesPerVertex * sizeof(float);
+ }
+
+ if (byteStride < numBonesPerVertex * sizeof(float))
+ {
+ APEX_INTERNAL_ERROR("bytestride too small (%d)", byteStride);
+ return false;
+ }
+
+ const_cast<ClothingPhysicalMeshImpl*>(this)->writeBackData();
+
+ const uint32_t numElements = mParams->physicalMesh.numVertices * numBonesPerVertex;
+
+ PxStrideIterator<float> iterator(boneWeights, byteStride);
+ for (uint32_t i = 0; i < numElements; i += numBonesPerVertex, ++iterator)
+ {
+ for (uint32_t j = 0; j < numBonesPerVertex; j++)
+ {
+ float* current = iterator.ptr();
+ current[j] = mBoneWeights[i + j];
+ }
+ }
+
+
+ return true;
+}
+
+
+
+bool ClothingPhysicalMeshImpl::getConstrainCoefficients(ClothingConstrainCoefficients* coeffs, uint32_t byteStride) const
+{
+ READ_ZONE();
+ if (mConstrainCoefficients.size() == 0)
+ {
+ return false;
+ }
+
+ if (byteStride == 0)
+ {
+ byteStride = sizeof(ClothingConstrainCoefficients);
+ }
+
+ if (byteStride < sizeof(ClothingConstrainCoefficients))
+ {
+ APEX_INTERNAL_ERROR("bytestride too small (%d)", byteStride);
+ return false;
+ }
+
+ const_cast<ClothingPhysicalMeshImpl*>(this)->writeBackData();
+
+ const uint32_t numVertices = mParams->physicalMesh.numVertices;
+
+ PxStrideIterator<ClothingConstrainCoefficients> iterator(coeffs, byteStride);
+ for (uint32_t i = 0; i < numVertices; i++, ++iterator)
+ {
+ iterator->maxDistance = mConstrainCoefficients[i].maxDistance;
+ iterator->collisionSphereDistance = mConstrainCoefficients[i].collisionSphereDistance;
+ iterator->collisionSphereRadius = mConstrainCoefficients[i].collisionSphereRadius;
+ }
+
+ return true;
+}
+
+
+
+void ClothingPhysicalMeshImpl::getStats(ClothingPhysicalMeshStats& stats) const
+{
+ READ_ZONE();
+ memset(&stats, 0, sizeof(ClothingPhysicalMeshStats));
+
+ stats.totalBytes = sizeof(ClothingPhysicalMeshImpl);
+
+ /*
+
+ stats.numVertices = mNumVertices;
+ stats.numIndices = mNumIndices;
+
+ stats.totalBytes += (mVertices != NULL ? mNumVertices : 0) * sizeof(PxVec3);
+ stats.totalBytes += (mNormals != NULL ? mNumVertices : 0) * sizeof(PxVec3);
+ stats.totalBytes += (mSkinningNormals != NULL ? mNumVertices : 0) * sizeof(PxVec3);
+ stats.totalBytes += (mVertexFlags != NULL ? mNumVertices : 0) * sizeof(uint32_t);
+ stats.totalBytes += (mConstrainCoefficients != NULL ? mNumVertices : 0) * sizeof(ClothConstrainCoefficients);
+
+ stats.totalBytes += (mBoneIndices != NULL ? mNumVertices * mNumBonesPerVertex : 0) * sizeof(uint16_t);
+ stats.totalBytes += (mBoneWeights != NULL ? mNumVertices * mNumBonesPerVertex : 0) * sizeof(float);
+
+ stats.totalBytes += (mIndices != NULL ? mNumIndices : 0) * sizeof(uint32_t);
+ */
+}
+
+
+
+void ClothingPhysicalMeshImpl::writeBackData()
+{
+ if (!isDirty || mSimplifier == NULL)
+ {
+ return;
+ }
+
+ isDirty = false;
+
+ Array<int32_t> old2new(mSimplifier->getNumVertices());
+
+ PX_ASSERT(mSimplifier->getNumVertices() - mSimplifier->getNumDeletedVertices() < mParams->physicalMesh.numVertices);
+
+ uint32_t verticesWritten = 0;
+ for (uint32_t i = 0; i < mSimplifier->getNumVertices(); i++)
+ {
+ PxVec3 pos;
+ if (mSimplifier->getVertexPosition(i, pos))
+ {
+ old2new[i] = (int32_t)verticesWritten;
+ mVertices[verticesWritten++] = pos;
+ }
+ else
+ {
+ old2new[i] = -1;
+ }
+ }
+ PX_ASSERT(verticesWritten == (mSimplifier->getNumVertices() - mSimplifier->getNumDeletedVertices()));
+ mParams->physicalMesh.numVertices = verticesWritten;
+
+ PX_ASSERT(mSimplifier->getNumTriangles() * 3 < mParams->physicalMesh.numIndices);
+
+ uint32_t indicesWritten = 0;
+ uint32_t trianglesRead = 0;
+ while (indicesWritten < mSimplifier->getNumTriangles() * 3)
+ {
+ uint32_t v0, v1, v2;
+ if (mSimplifier->getTriangle(trianglesRead++, v0, v1, v2))
+ {
+ PX_ASSERT(old2new[v0] != -1);
+ PX_ASSERT(old2new[v1] != -1);
+ PX_ASSERT(old2new[v2] != -1);
+ mIndices[indicesWritten++] = (uint32_t)old2new[v0];
+ mIndices[indicesWritten++] = (uint32_t)old2new[v1];
+ mIndices[indicesWritten++] = (uint32_t)old2new[v2];
+ }
+ }
+ mParams->physicalMesh.numIndices = indicesWritten;
+
+ updateSkinningNormals();
+}
+
+
+void ClothingPhysicalMeshImpl::clearMiscBuffers()
+{
+ mConstrainCoefficients.resize(0);
+ mBoneIndices.resize(0);
+ mBoneWeights.resize(0);
+}
+
+
+
+void ClothingPhysicalMeshImpl::computeEdgeLengths() const
+{
+ const uint32_t numIndices = mParams->physicalMesh.numIndices;
+
+ float average = 0;
+ float shortest = PX_MAX_F32;
+
+ if (mParams->physicalMesh.isTetrahedralMesh)
+ {
+ for (uint32_t i = 0; i < numIndices; i += 4)
+ {
+ const float edge0 = (mVertices[mIndices[i + 0]] - mVertices[mIndices[i + 1]]).magnitudeSquared();
+ const float edge1 = (mVertices[mIndices[i + 0]] - mVertices[mIndices[i + 2]]).magnitudeSquared();
+ const float edge2 = (mVertices[mIndices[i + 0]] - mVertices[mIndices[i + 3]]).magnitudeSquared();
+ const float edge3 = (mVertices[mIndices[i + 1]] - mVertices[mIndices[i + 2]]).magnitudeSquared();
+ const float edge4 = (mVertices[mIndices[i + 1]] - mVertices[mIndices[i + 3]]).magnitudeSquared();
+ const float edge5 = (mVertices[mIndices[i + 2]] - mVertices[mIndices[i + 3]]).magnitudeSquared();
+ shortest = PxMin(shortest, edge0);
+ shortest = PxMin(shortest, edge1);
+ shortest = PxMin(shortest, edge2);
+ shortest = PxMin(shortest, edge3);
+ shortest = PxMin(shortest, edge4);
+ shortest = PxMin(shortest, edge5);
+
+ average += PxSqrt(edge0) + PxSqrt(edge1) + PxSqrt(edge2) + PxSqrt(edge3) + PxSqrt(edge4) + PxSqrt(edge5);
+ }
+ mParams->physicalMesh.isClosed = false;
+ }
+ else
+ {
+ // also check if the mesh is closed
+ nvidia::Array<SortedEdge> edges;
+
+ for (uint32_t i = 0; i < numIndices; i += 3)
+ {
+ const float edge0 = (mVertices[mIndices[i + 0]] - mVertices[mIndices[i + 1]]).magnitudeSquared();
+ const float edge1 = (mVertices[mIndices[i + 0]] - mVertices[mIndices[i + 2]]).magnitudeSquared();
+ const float edge2 = (mVertices[mIndices[i + 1]] - mVertices[mIndices[i + 2]]).magnitudeSquared();
+ shortest = PxMin(shortest, edge0);
+ shortest = PxMin(shortest, edge1);
+ shortest = PxMin(shortest, edge2);
+
+ average += PxSqrt(edge0) + PxSqrt(edge1) + PxSqrt(edge2);
+
+ edges.pushBack(SortedEdge(mIndices[i + 0], mIndices[i + 1]));
+ edges.pushBack(SortedEdge(mIndices[i + 1], mIndices[i + 2]));
+ edges.pushBack(SortedEdge(mIndices[i + 2], mIndices[i + 0]));
+ }
+
+ nvidia::sort(edges.begin(), edges.size(), SortedEdge(0, 0));
+
+ bool meshClosed = false;
+ if ((edges.size() & 0x1) == 0) // only works for even number of indices
+ {
+ meshClosed = true;
+ for (uint32_t i = 0; i < edges.size(); i += 2)
+ {
+ meshClosed &= edges[i] == edges[i + 1];
+
+ if (i > 0)
+ {
+ meshClosed &= !(edges[i - 1] == edges[i]);
+ }
+ }
+ }
+ mParams->physicalMesh.isClosed = meshClosed;
+ }
+
+ mParams->physicalMesh.shortestEdgeLength = PxSqrt(shortest);
+ if (numIndices > 0)
+ {
+ mParams->physicalMesh.averageEdgeLength = average / (float)numIndices;
+ }
+ else
+ {
+ mParams->physicalMesh.averageEdgeLength = 0.0f;
+ }
+}
+
+
+
+void ClothingPhysicalMeshImpl::addBoneToVertex(uint32_t vertexNumber, uint16_t boneIndex, float boneWeight)
+{
+ if (mBoneIndices.size() == 0 || mBoneWeights.size() == 0)
+ {
+ return;
+ }
+
+ const uint32_t numBonesPerVertex = mParams->physicalMesh.numBonesPerVertex;
+ for (uint32_t i = 0; i < numBonesPerVertex; i++)
+ {
+ if (mBoneIndices[vertexNumber * numBonesPerVertex + i] == boneIndex ||
+ mBoneWeights[vertexNumber * numBonesPerVertex + i] == 0.0f)
+ {
+ mBoneIndices[vertexNumber * numBonesPerVertex + i] = boneIndex;
+ mBoneWeights[vertexNumber * numBonesPerVertex + i] =
+ PxMax(mBoneWeights[vertexNumber * numBonesPerVertex + i], boneWeight);
+ sortBonesOfVertex(vertexNumber);
+ return;
+ }
+ }
+}
+
+
+
+void ClothingPhysicalMeshImpl::sortBonesOfVertex(uint32_t vertexNumber)
+{
+ const uint32_t numBonesPerVertex = mParams->physicalMesh.numBonesPerVertex;
+ if (mBoneIndices.size() == 0 || mBoneWeights.size() == 0 || numBonesPerVertex <= 1)
+ {
+ return;
+ }
+
+ // bubble sort
+ bool changed = true;
+ while (changed)
+ {
+ changed = false;
+ for (uint32_t i = 0; i < numBonesPerVertex - 1; i++)
+ {
+ const uint32_t index = vertexNumber * numBonesPerVertex + i;
+ if (mBoneWeights[index] < mBoneWeights[index + 1])
+ {
+ // swap
+ float tempF = mBoneWeights[index];
+ mBoneWeights[index] = mBoneWeights[index + 1];
+ mBoneWeights[index + 1] = tempF;
+
+ uint16_t tempI = mBoneIndices[index];
+ mBoneIndices[index] = mBoneIndices[index + 1];
+ mBoneIndices[index + 1] = tempI;
+
+ changed = true;
+ }
+ }
+ }
+}
+
+
+
+void ClothingPhysicalMeshImpl::normalizeBonesOfVertex(uint32_t vertexNumber)
+{
+ if (mBoneIndices.size() == 0 || mBoneWeights.size() == 0)
+ {
+ return;
+ }
+
+ const uint32_t numBonesPerVertex = mParams->physicalMesh.numBonesPerVertex;
+
+ float sum = 0;
+ float last = FLT_MAX;
+ for (uint32_t i = 0; i < numBonesPerVertex; i++)
+ {
+ sum += mBoneWeights[vertexNumber * numBonesPerVertex + i];
+
+ // make sure it is sorted!
+ PX_ASSERT(mBoneWeights[vertexNumber * numBonesPerVertex + i] <= last);
+ last = mBoneWeights[vertexNumber * numBonesPerVertex + i];
+ }
+
+ PX_UNUSED(last);
+
+ if (sum > 0)
+ {
+ float invSum = 1.0f / sum;
+ for (uint32_t i = 0; i < numBonesPerVertex; i++)
+ {
+ float& weight = mBoneWeights[vertexNumber * numBonesPerVertex + i];
+ if (weight > 0)
+ {
+ weight *= invSum;
+ }
+ else
+ {
+ mBoneIndices[vertexNumber * numBonesPerVertex + i] = 0;
+ }
+ }
+ }
+ else
+ {
+ for (uint32_t i = 0; i < numBonesPerVertex; i++)
+ {
+ mBoneIndices[vertexNumber * numBonesPerVertex + i] = 0;
+ mBoneWeights[vertexNumber * numBonesPerVertex + i] = 0.0f;
+ }
+ }
+}
+
+
+
+void ClothingPhysicalMeshImpl::updateSkinningNormals()
+{
+ // only for non-softbodies
+ if (isTetrahedralMesh())
+ {
+ return;
+ }
+
+ const uint32_t numVertices = mParams->physicalMesh.numVertices;
+ const uint32_t numIndices = mParams->physicalMesh.numIndices;
+
+ PX_ASSERT(mSkinningNormals.size() == mVertices.size());
+ memset(mSkinningNormals.begin(), 0, sizeof(PxVec3) * numVertices);
+
+ for (uint32_t i = 0; i < numIndices; i += 3)
+ {
+ PxVec3 normal;
+ normal = mVertices[mIndices[i + 1]] - mVertices[mIndices[i]];
+ normal = normal.cross(mVertices[mIndices[i + 2]] - mVertices[mIndices[i]]);
+ mSkinningNormals[mIndices[i]] += normal;
+ mSkinningNormals[mIndices[i + 1]] += normal;
+ mSkinningNormals[mIndices[i + 2]] += normal;
+ }
+
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ mSkinningNormals[i].normalize();
+ }
+}
+
+
+
+void ClothingPhysicalMeshImpl::smoothNormals(uint32_t numIterations)
+{
+ const uint32_t increment = mParams->physicalMesh.isTetrahedralMesh ? 4u : 3u;
+ const uint32_t numIndices = mParams->physicalMesh.numIndices;
+
+ for (uint32_t iters = 0; iters < numIterations; iters++)
+ {
+ for (uint32_t i = 0; i < numIndices; i += increment)
+ {
+ PxVec3& n0 = mNormals[mIndices[i + 0]];
+ PxVec3& n1 = mNormals[mIndices[i + 1]];
+ PxVec3& n2 = mNormals[mIndices[i + 2]];
+ PxVec3 n = n0 + n1 + n2;
+ n.normalize();
+ n0 = n;
+ n1 = n;
+ n2 = n;
+ }
+ }
+}
+
+
+
+void ClothingPhysicalMeshImpl::updateOptimizationData()
+{
+ PX_ASSERT(mParams != NULL);
+
+ const int32_t numVertices = mParams->physicalMesh.vertices.arraySizes[0];
+ const uint32_t numBonesPerVertex = mParams->physicalMesh.numBonesPerVertex;
+
+ const float* boneWeights = mParams->physicalMesh.boneWeights.buf;
+ PX_ASSERT(boneWeights == NULL || mParams->physicalMesh.boneWeights.arraySizes[0] == numVertices * (int32_t)numBonesPerVertex);
+
+ const ClothingPhysicalMeshParametersNS::ConstrainCoefficient_Type* constrainCoeffs = mParams->physicalMesh.constrainCoefficients.buf;
+ PX_ASSERT(constrainCoeffs == NULL || mParams->physicalMesh.constrainCoefficients.arraySizes[0] == numVertices);
+
+ if (boneWeights == NULL && constrainCoeffs == NULL)
+ {
+ return;
+ }
+
+ uint32_t allocNumVertices = ((uint32_t)physx::shdfnd::ceil((float)numVertices / NUM_VERTICES_PER_CACHE_BLOCK)) * NUM_VERTICES_PER_CACHE_BLOCK; // allocate more to have a multiple of numVerticesPerCachBlock
+
+ NvParameterized::Handle optimizationDataHandle(*mParams, "physicalMesh.optimizationData");
+ PX_ASSERT(optimizationDataHandle.isValid());
+ optimizationDataHandle.resizeArray((int32_t)(allocNumVertices + 1) / 2);
+ uint8_t* optimizationData = mParams->physicalMesh.optimizationData.buf;
+ memset(optimizationData, 0, sizeof(uint8_t) * mParams->physicalMesh.optimizationData.arraySizes[0]);
+
+ for (int32_t i = 0; i < numVertices; ++i)
+ {
+ uint8_t numBones = 0;
+ if (boneWeights != NULL)
+ {
+ for (; numBones < numBonesPerVertex; numBones++)
+ {
+ if (boneWeights[i * numBonesPerVertex + numBones] == 0.0f)
+ {
+ break;
+ }
+ }
+ }
+
+ uint8_t& data = optimizationData[i / 2];
+ PX_ASSERT(numBones < 8); // we use 3 bits
+
+ if (constrainCoeffs != NULL)
+ {
+ uint8_t bitShift = 0;
+ if (i % 2 == 0)
+ {
+ data = 0;
+ }
+ else
+ {
+ bitShift = 4;
+ }
+ data |= numBones << bitShift;
+
+ // store for each vertex if collisionSphereDistance is < 0
+ if (constrainCoeffs[i].collisionSphereDistance < 0.0f)
+ {
+ data |= 8 << bitShift;
+ mParams->physicalMesh.hasNegativeBackstop = true;
+ }
+ else
+ {
+ data &= ~(8 << bitShift);
+ }
+ }
+ }
+}
+
+
+
+void ClothingPhysicalMeshImpl::updateMaxMaxDistance()
+{
+ const uint32_t numVertices = mParams->physicalMesh.numVertices;
+
+ float maxMaxDistance = 0.0f;
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ maxMaxDistance = PxMax(maxMaxDistance, mConstrainCoefficients[i].maxDistance);
+ }
+
+ mParams->physicalMesh.maximumMaxDistance = maxMaxDistance;
+}
+
+
+
+void ClothingPhysicalMeshImpl::preSerialize(void* userData_)
+{
+ PX_UNUSED(userData_);
+
+ writeBackData();
+
+ // shrink the buffers
+
+ if (!mVertices.isEmpty() && mVertices.size() != mParams->physicalMesh.numVertices)
+ {
+ mVertices.resize(mParams->physicalMesh.numVertices);
+ }
+
+ if (!mNormals.isEmpty() && mNormals.size() != mParams->physicalMesh.numVertices)
+ {
+ mNormals.resize(mParams->physicalMesh.numVertices);
+ }
+
+ if (!mSkinningNormals.isEmpty() && mSkinningNormals.size() != mParams->physicalMesh.numVertices)
+ {
+ mSkinningNormals.resize(mParams->physicalMesh.numVertices);
+ }
+
+ if (!mConstrainCoefficients.isEmpty() && mConstrainCoefficients.size() != mParams->physicalMesh.numVertices)
+ {
+ mConstrainCoefficients.resize(mParams->physicalMesh.numVertices);
+ }
+
+ if (!mBoneIndices.isEmpty() && mBoneIndices.size() != mParams->physicalMesh.numVertices * mParams->physicalMesh.numBonesPerVertex)
+ {
+ mBoneIndices.resize(mParams->physicalMesh.numVertices * mParams->physicalMesh.numBonesPerVertex);
+ }
+
+ if (!mBoneWeights.isEmpty() && mBoneWeights.size() != mParams->physicalMesh.numVertices * mParams->physicalMesh.numBonesPerVertex)
+ {
+ mBoneWeights.resize(mParams->physicalMesh.numVertices * mParams->physicalMesh.numBonesPerVertex);
+ }
+
+ if (!mIndices.isEmpty() && mIndices.size() != mParams->physicalMesh.numIndices)
+ {
+ mIndices.resize(mParams->physicalMesh.numIndices);
+ }
+
+ updateOptimizationData();
+}
+
+
+
+void ClothingPhysicalMeshImpl::permuteBoneIndices(Array<int32_t>& old2newBoneIndices)
+{
+ if (mBoneIndices.size() == 0)
+ {
+ return;
+ }
+
+ const uint32_t numVertices = mParams->physicalMesh.numVertices;
+ const uint32_t numBonesPerVertex = mParams->physicalMesh.numBonesPerVertex;
+
+ for (uint32_t j = 0; j < numVertices; j++)
+ {
+ for (uint32_t k = 0; k < numBonesPerVertex; k++)
+ {
+ uint16_t& index = mBoneIndices[j * numBonesPerVertex + k];
+ PX_ASSERT(old2newBoneIndices[index] >= 0);
+ PX_ASSERT(old2newBoneIndices[index] <= 0xffff);
+ index = (uint16_t)old2newBoneIndices[index];
+ }
+ }
+}
+
+
+
+void ClothingPhysicalMeshImpl::applyTransformation(const PxMat44& transformation, float scale)
+{
+ const uint32_t numVertices = mParams->physicalMesh.numVertices;
+
+ PX_ASSERT(scale > 0.0f); // PH: negative scale won't work well here
+
+ for (uint32_t i = 0; i < numVertices; i++)
+ {
+ if (!mVertices.isEmpty())
+ {
+ mVertices[i] = (transformation.transform(mVertices[i])) * scale;
+ }
+ if (!mNormals.isEmpty())
+ {
+ mNormals[i] = transformation.transform(mNormals[i]);
+ }
+ if (!mSkinningNormals.isEmpty())
+ {
+ mSkinningNormals[i] = transformation.transform(mSkinningNormals[i]);
+ }
+ if (!mConstrainCoefficients.isEmpty())
+ {
+ mConstrainCoefficients[i].maxDistance *= scale;
+ mConstrainCoefficients[i].collisionSphereDistance *= scale;
+ mConstrainCoefficients[i].collisionSphereRadius *= scale;
+ }
+ }
+
+ PxMat33 t33(PxVec3(transformation.column0.x, transformation.column0.y, transformation.column0.z),
+ PxVec3(transformation.column1.x, transformation.column1.y, transformation.column1.z),
+ PxVec3(transformation.column2.x, transformation.column2.y, transformation.column2.z));
+
+ if (t33.getDeterminant() * scale < 0.0f)
+ {
+ const uint32_t numIndices = mParams->physicalMesh.numIndices;
+
+ if (mParams->physicalMesh.isTetrahedralMesh)
+ {
+ PX_ASSERT(numIndices % 4 == 0);
+ for (uint32_t i = 0; i < numIndices; i += 4)
+ {
+ nvidia::swap(mIndices[i + 2], mIndices[i + 3]);
+ }
+ }
+ else
+ {
+ // Flip the triangle indices to change winding (and thus normal generation in the PhysX SDK
+ PX_ASSERT(numIndices % 3 == 0);
+ for (uint32_t i = 0; i < numIndices; i += 3)
+ {
+ nvidia::swap(mIndices[i + 1], mIndices[i + 2]);
+ }
+ }
+
+ mParams->physicalMesh.flipNormals ^= true;
+
+ if (mParams->transitionDownB.buf != NULL || mParams->transitionUpB.buf != NULL)
+ {
+ APEX_DEBUG_WARNING("applyTransformation will not work with old assets, re-export from DCC tools");
+ }
+
+ const uint32_t numTransDown = (uint32_t)mParams->transitionDown.arraySizes[0];
+ for (uint32_t i = 0; i < numTransDown; i++)
+ {
+ mParams->transitionDown.buf[i].vertexBary.z *= scale;
+ mParams->transitionDown.buf[i].normalBary.z *= scale;
+ }
+
+ const uint32_t numTransUp = (uint32_t)mParams->transitionUp.arraySizes[0];
+ for (uint32_t i = 0; i < numTransUp; i++)
+ {
+ mParams->transitionUp.buf[i].vertexBary.z *= scale;
+ mParams->transitionUp.buf[i].normalBary.z *= scale;
+ }
+ }
+
+ mParams->physicalMesh.maximumMaxDistance *= scale;
+ mParams->physicalMesh.shortestEdgeLength *= scale;
+ mParams->physicalMesh.averageEdgeLength *= scale;
+}
+
+
+
+void ClothingPhysicalMeshImpl::applyPermutation(const Array<uint32_t>& permutation)
+{
+ const uint32_t numVertices = mParams->physicalMesh.numVertices;
+ const uint32_t numBonesPerVertex = mParams->physicalMesh.numBonesPerVertex;
+
+ if (!mVertices.isEmpty())
+ {
+ ApexPermute<PxVec3>(mVertices.begin(), &permutation[0], numVertices);
+ }
+
+ if (!mNormals.isEmpty())
+ {
+ ApexPermute<PxVec3>(mNormals.begin(), &permutation[0], numVertices);
+ }
+
+ if (!mSkinningNormals.isEmpty())
+ {
+ ApexPermute<PxVec3>(mSkinningNormals.begin(), &permutation[0], numVertices);
+ }
+
+ if (!mConstrainCoefficients.isEmpty())
+ {
+ ApexPermute<ClothingPhysicalMeshParametersNS::ConstrainCoefficient_Type>(mConstrainCoefficients.begin(), &permutation[0], numVertices);
+ }
+
+ if (!mBoneIndices.isEmpty())
+ {
+ ApexPermute<uint16_t>(mBoneIndices.begin(), &permutation[0], numVertices, numBonesPerVertex);
+ }
+
+ if (!mBoneWeights.isEmpty())
+ {
+ ApexPermute<float>(mBoneWeights.begin(), &permutation[0], numVertices, numBonesPerVertex);
+ }
+}
+
+
+
+struct OrderedTriangle
+{
+ void init(uint32_t _triNr, uint32_t _v0, uint32_t _v1, uint32_t _v2)
+ {
+ triNr = _triNr;
+ v0 = _v0;
+ v1 = _v1;
+ v2 = _v2;
+ // bubble sort
+ if (v0 > v1)
+ {
+ uint32_t v = v0;
+ v0 = v1;
+ v1 = v;
+ }
+ if (v1 > v2)
+ {
+ uint32_t v = v1;
+ v1 = v2;
+ v2 = v;
+ }
+ if (v0 > v1)
+ {
+ uint32_t v = v0;
+ v0 = v1;
+ v1 = v;
+ }
+ }
+ bool operator()(const OrderedTriangle& a, const OrderedTriangle& b) const
+ {
+ if (a.v0 < b.v0)
+ {
+ return true;
+ }
+ if (a.v0 > b.v0)
+ {
+ return false;
+ }
+ if (a.v1 < b.v1)
+ {
+ return true;
+ }
+ if (a.v1 > b.v1)
+ {
+ return false;
+ }
+ return (a.v2 < b.v2);
+ }
+ bool operator == (const OrderedTriangle& t) const
+ {
+ return v0 == t.v0 && v1 == t.v1 && v2 == t.v2;
+ }
+ uint32_t v0, v1, v2;
+ uint32_t triNr;
+};
+
+bool ClothingPhysicalMeshImpl::removeDuplicatedTriangles(uint32_t numIndices, uint32_t indexByteStride, const void* indices)
+{
+ uint32_t numTriangles = numIndices / 3;
+ Array<OrderedTriangle> triangles;
+ triangles.resize(numTriangles);
+
+ {
+ const uint8_t* srcIndices = (const uint8_t*)indices;
+ for (uint32_t i = 0; i < numTriangles; i++)
+ {
+ uint32_t i0 = *(const uint32_t*)(srcIndices);
+ srcIndices += indexByteStride;
+ uint32_t i1 = *(const uint32_t*)(srcIndices);
+ srcIndices += indexByteStride;
+ uint32_t i2 = *(const uint32_t*)(srcIndices);
+ srcIndices += indexByteStride;
+
+ triangles[i].init(i, i0, i1, i2);
+ }
+ }
+
+ nvidia::sort(triangles.begin(), triangles.size(), OrderedTriangle());
+
+ uint32_t fromPos = 0;
+ uint32_t toPos = 0;
+ while (fromPos < numTriangles)
+ {
+ OrderedTriangle& t = triangles[fromPos];
+ triangles[toPos] = t;
+ fromPos++;
+ toPos++;
+ while (fromPos < numTriangles && triangles[fromPos] == t)
+ {
+ fromPos++;
+ }
+ }
+ if (fromPos == toPos)
+ {
+ return false;
+ }
+
+ mParams->physicalMesh.numIndices = 3 * toPos;
+
+ mIndices.resize(mParams->physicalMesh.numIndices);
+ if (mParams->physicalMesh.numIndices > 0)
+ {
+ for (uint32_t i = 0; i < toPos; i++)
+ {
+ OrderedTriangle& t = triangles[i];
+ const uint8_t* srcIndices = (const uint8_t*)indices + 3 * t.triNr * indexByteStride;
+
+ mIndices[3 * i] = *(uint32_t*)srcIndices;
+ srcIndices += indexByteStride;
+ mIndices[3 * i + 1] = *(uint32_t*)srcIndices;
+ srcIndices += indexByteStride;
+ mIndices[3 * i + 2] = *(uint32_t*)srcIndices;
+ srcIndices += indexByteStride;
+ }
+ }
+
+ fixTriangleOrientations();
+ return true;
+}
+
+
+struct OrderedTriangleEdge
+{
+ void init(uint32_t _v0, uint32_t _v1, uint32_t _triNr, uint32_t _edgeNr)
+ {
+ if (_v0 < _v1)
+ {
+ v0 = _v0;
+ v1 = _v1;
+ }
+ else
+ {
+ v0 = _v1;
+ v1 = _v0;
+ }
+ triNr = _triNr;
+ edgeNr = _edgeNr;
+ }
+ bool operator()(const OrderedTriangleEdge& a, const OrderedTriangleEdge& b) const
+ {
+ if (a.v0 < b.v0)
+ {
+ return true;
+ }
+ if (a.v0 > b.v0)
+ {
+ return false;
+ }
+ return (a.v1 < b.v1);
+ }
+ bool operator == (const OrderedTriangleEdge& e) const
+ {
+ return v0 == e.v0 && v1 == e.v1;
+ }
+ uint32_t v0, v1;
+ uint32_t triNr, edgeNr;
+};
+
+void ClothingPhysicalMeshImpl::computeNeighborInformation(Array<int32_t> &neighbors)
+{
+ // compute neighbor information
+ const uint32_t numTriangles = mParams->physicalMesh.numIndices / 3;
+
+ Array<OrderedTriangleEdge> edges;
+ edges.resize(3 * numTriangles);
+
+ for (uint32_t i = 0; i < numTriangles; i++)
+ {
+ uint32_t i0 = mIndices[3 * i];
+ uint32_t i1 = mIndices[3 * i + 1];
+ uint32_t i2 = mIndices[3 * i + 2];
+ edges[3 * i ].init(i0, i1, i, 0);
+ edges[3 * i + 1].init(i1, i2, i, 1);
+ edges[3 * i + 2].init(i2, i0, i, 2);
+ }
+
+ nvidia::sort(edges.begin(), edges.size(), OrderedTriangleEdge());
+
+ neighbors.resize(3 * numTriangles, -1);
+
+ uint32_t i = 0;
+ while (i < edges.size())
+ {
+ OrderedTriangleEdge& e0 = edges[i];
+ i++;
+ while (i < edges.size() && edges[i] == e0)
+ {
+ OrderedTriangleEdge& e1 = edges[i];
+ neighbors[3 * e0.triNr + e0.edgeNr] = (int32_t)e1.triNr;
+ neighbors[3 * e1.triNr + e1.edgeNr] = (int32_t)e0.triNr;
+ i++;
+ }
+ }
+}
+
+
+void ClothingPhysicalMeshImpl::fixTriangleOrientations()
+{
+ PX_ASSERT(!mParams->physicalMesh.isTetrahedralMesh);
+ Array<int32_t> neighbors;
+ computeNeighborInformation(neighbors);
+
+ const uint32_t numTriangles = mParams->physicalMesh.numIndices / 3;
+
+ // 0 = non visited, 1 = visited, 2 = visited, to be flipped
+ Array<uint8_t> marks;
+ marks.resize(numTriangles, 0);
+
+ Array<uint32_t> queue;
+
+ for (uint32_t i = 0; i < numTriangles; i++)
+ {
+ if (marks[i] != 0)
+ {
+ continue;
+ }
+ queue.clear();
+ marks[i] = 1;
+ queue.pushBack(i);
+ while (!queue.empty())
+ {
+ uint32_t triNr = queue[queue.size() - 1];
+ queue.popBack();
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ int adjNr = neighbors[3 * triNr + j];
+ if (adjNr < 0 || marks[(uint32_t)adjNr] != 0)
+ {
+ continue;
+ }
+ queue.pushBack((uint32_t)adjNr);
+ uint32_t i0, i1;
+ if (marks[triNr] == 1)
+ {
+ i0 = mIndices[3 * triNr + j];
+ i1 = mIndices[3 * triNr + ((j + 1) % 3)];
+ }
+ else
+ {
+ i1 = mIndices[3 * triNr + j];
+ i0 = mIndices[3 * triNr + ((j + 1) % 3)];
+ }
+ // don't swap here because this would corrupt the neighbor information
+ marks[(uint32_t)adjNr] = 1;
+ if (mIndices[3 * (uint32_t)adjNr + 0] == i0 && mIndices[3 * (uint32_t)adjNr + 1] == i1)
+ {
+ marks[(uint32_t)adjNr] = 2;
+ }
+ if (mIndices[3 * (uint32_t)adjNr + 1] == i0 && mIndices[3 * (uint32_t)adjNr + 2] == i1)
+ {
+ marks[(uint32_t)adjNr] = 2;
+ }
+ if (mIndices[3 * (uint32_t)adjNr + 2] == i0 && mIndices[3 * (uint32_t)adjNr + 0] == i1)
+ {
+ marks[(uint32_t)adjNr] = 2;
+ }
+ }
+ }
+ }
+ for (uint32_t i = 0; i < numTriangles; i++)
+ {
+ if (marks[i] == 2)
+ {
+ uint32_t i0 = mIndices[3 * i];
+ mIndices[3 * i] = mIndices[3 * i + 1];
+ mIndices[3 * i + 1] = i0;
+ }
+ }
+}
+
+}
+} // namespace nvidia
+
+
diff --git a/APEX_1.4/module/clothing/src/ClothingRenderProxyImpl.cpp b/APEX_1.4/module/clothing/src/ClothingRenderProxyImpl.cpp
new file mode 100644
index 00000000..2576e8ef
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/ClothingRenderProxyImpl.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+
+#include "ApexDefs.h"
+
+#include "ClothingRenderProxyImpl.h"
+
+#include "ClothingAssetImpl.h"
+#include "ClothingActorParam.h"
+#include "RenderMeshActorDesc.h"
+#include "RenderMeshAssetIntl.h"
+#include "ClothingScene.h"
+
+namespace nvidia
+{
+namespace clothing
+{
+
+ClothingRenderProxyImpl::ClothingRenderProxyImpl(RenderMeshAssetIntl* rma, bool useFallbackSkinning, bool useCustomVertexBuffer, const HashMap<uint32_t, ApexSimpleString>& overrideMaterials, const PxVec3* morphTargetNewPositions, const uint32_t* morphTargetVertexOffsets, ClothingScene* scene) :
+renderingDataPosition(NULL),
+renderingDataNormal(NULL),
+renderingDataTangent(NULL),
+mBounds(),
+mPose(PxMat44(PxIdentity)),
+mRenderMeshActor(NULL),
+mRenderMeshAsset(rma),
+mScene(scene),
+mUseFallbackSkinning(useFallbackSkinning),
+mMorphTargetNewPositions(morphTargetNewPositions),
+mTimeInPool(0)
+{
+ // create renderMeshActor
+ RenderMeshActorDesc desc;
+ desc.keepVisibleBonesPacked = false;
+ desc.forceFallbackSkinning = mUseFallbackSkinning;
+
+ // prepare material names array and copy the map with override names
+ const uint32_t numSubmeshes = rma->getSubmeshCount();
+ Array<const char*> overrideMaterialNames;
+ for (uint32_t si = 0; si < numSubmeshes; ++si)
+ {
+ const Pair<const uint32_t, ApexSimpleString>* overrideMat = overrideMaterials.find(si);
+ if (overrideMat != NULL)
+ {
+ overrideMaterialNames.pushBack(overrideMat->second.c_str());
+ mOverrideMaterials[si] = overrideMat->second;
+ }
+ else
+ {
+ overrideMaterialNames.pushBack(rma->getMaterialName(si));
+ }
+ }
+
+ desc.overrideMaterialCount = numSubmeshes;
+ desc.overrideMaterials = &overrideMaterialNames[0];
+ mRenderMeshActor = DYNAMIC_CAST(RenderMeshActorIntl*)(mRenderMeshAsset->createActor(desc));
+
+ // Necessary for clothing
+ mRenderMeshActor->setSkinningMode(RenderMeshActorSkinningMode::AllBonesPerPart);
+
+ if (useCustomVertexBuffer)
+ {
+ // get num verts and check if we need tangents
+ ClothingGraphicalMeshAssetWrapper meshAsset(rma);
+ uint32_t numRenderVertices = meshAsset.getNumTotalVertices();
+ bool renderTangents = meshAsset.hasChannel(NULL, RenderVertexSemantic::TANGENT);
+
+ // allocate aligned buffers and init to 0
+ const uint32_t alignedNumRenderVertices = (numRenderVertices + 15) & 0xfffffff0;
+ const uint32_t renderingDataSize = sizeof(PxVec3) * alignedNumRenderVertices * 2 + sizeof(PxVec4) * alignedNumRenderVertices * (renderTangents ? 1 : 0);
+ renderingDataPosition = (PxVec3*)PX_ALLOC(renderingDataSize, PX_DEBUG_EXP("SimulationAbstract::renderingDataPositions"));
+ renderingDataNormal = renderingDataPosition + alignedNumRenderVertices;
+ if (renderTangents)
+ {
+ renderingDataTangent = reinterpret_cast<PxVec4*>(renderingDataNormal + alignedNumRenderVertices);
+ PX_ASSERT(((size_t)renderingDataTangent & 0xf) == 0);
+ }
+ memset(renderingDataPosition, 0, renderingDataSize);
+
+ // update rma to use the custom buffers
+ uint32_t submeshOffset = 0;
+ for (uint32_t i = 0; i < meshAsset.getSubmeshCount(); i++)
+ {
+ PxVec3* position = renderingDataPosition + (renderingDataPosition != NULL ? submeshOffset : 0);
+ PxVec3* normal = renderingDataNormal + (renderingDataNormal != NULL ? submeshOffset : 0);
+ PxVec4* tangent = renderingDataTangent + (renderingDataTangent != NULL ? submeshOffset : 0);
+ mRenderMeshActor->addVertexBuffer(i, true, position, normal, tangent);
+
+ // morph targets
+ if (mMorphTargetNewPositions != NULL)
+ {
+ const PxVec3* staticPosition = mMorphTargetNewPositions + morphTargetVertexOffsets[i];
+ mRenderMeshActor->setStaticPositionReplacement(i, staticPosition);
+ }
+
+ submeshOffset += meshAsset.getNumVertices(i);
+ }
+ }
+}
+
+
+
+ClothingRenderProxyImpl::~ClothingRenderProxyImpl()
+{
+ mRMALock.lock();
+ if (mRenderMeshActor != NULL)
+ {
+ mRenderMeshActor->release();
+ mRenderMeshActor = NULL;
+ }
+ mRMALock.unlock();
+
+ if (renderingDataPosition != NULL)
+ {
+ PX_FREE(renderingDataPosition);
+ renderingDataPosition = NULL;
+ renderingDataNormal = NULL;
+ renderingDataTangent = NULL;
+ }
+}
+
+
+
+// from ApexInterface
+void ClothingRenderProxyImpl::release()
+{
+ WRITE_ZONE();
+ setTimeInPool(1);
+ if(mScene == NULL || mRenderMeshActor == NULL)
+ {
+ PX_DELETE(this);
+ }
+}
+
+
+
+// from Renderable
+void ClothingRenderProxyImpl::dispatchRenderResources(UserRenderer& api)
+{
+ mRMALock.lock();
+ if (mRenderMeshActor != NULL)
+ {
+ mRenderMeshActor->dispatchRenderResources(api, mPose);
+ }
+ mRMALock.unlock();
+}
+
+
+
+// from RenderDataProvider.h
+void ClothingRenderProxyImpl::updateRenderResources(bool rewriteBuffers, void* userRenderData)
+{
+ URR_SCOPE;
+
+ mRMALock.lock();
+ if (mRenderMeshActor != NULL)
+ {
+ mRenderMeshActor->updateRenderResources(renderingDataPosition == NULL, rewriteBuffers, userRenderData);
+ }
+ mRMALock.unlock();
+}
+
+
+void ClothingRenderProxyImpl::lockRenderResources()
+{
+ // no need to lock anything, as soon as the user can access the proxy, we don't write it anymore
+ // until he calls release
+}
+
+
+void ClothingRenderProxyImpl::unlockRenderResources()
+{
+}
+
+
+
+bool ClothingRenderProxyImpl::hasSimulatedData() const
+{
+ READ_ZONE();
+ return renderingDataPosition != NULL;
+}
+
+
+
+RenderMeshActorIntl* ClothingRenderProxyImpl::getRenderMeshActor()
+{
+ return mRenderMeshActor;
+}
+
+
+
+RenderMeshAssetIntl* ClothingRenderProxyImpl::getRenderMeshAsset()
+{
+ return mRenderMeshAsset;
+}
+
+
+
+void ClothingRenderProxyImpl::setOverrideMaterial(uint32_t submeshIndex, const char* overrideMaterialName)
+{
+ mOverrideMaterials[submeshIndex] = overrideMaterialName;
+ mRMALock.lock();
+ if (mRenderMeshActor != NULL)
+ {
+ mRenderMeshActor->setOverrideMaterial(submeshIndex, overrideMaterialName);
+ }
+ mRMALock.unlock();
+}
+
+
+
+bool ClothingRenderProxyImpl::overrideMaterialsEqual(const HashMap<uint32_t, ApexSimpleString>& overrideMaterials)
+{
+ uint32_t numEntries = mOverrideMaterials.size();
+ if (overrideMaterials.size() != numEntries)
+ return false;
+
+ for(HashMap<uint32_t, ApexSimpleString>::Iterator iter = mOverrideMaterials.getIterator(); !iter.done(); ++iter)
+ {
+ uint32_t submeshIndex = iter->first;
+ const Pair<const uint32_t, ApexSimpleString>* overrideMat = overrideMaterials.find(submeshIndex);
+
+ // submeshIndex not found
+ if (overrideMat == NULL)
+ return false;
+
+ // name is different
+ if (overrideMat->second != iter->second)
+ return false;
+ }
+
+ return true;
+}
+
+
+uint32_t ClothingRenderProxyImpl::getTimeInPool() const
+{
+ return mTimeInPool;
+}
+
+
+void ClothingRenderProxyImpl::setTimeInPool(uint32_t time)
+{
+ mTimeInPool = time;
+}
+
+
+void ClothingRenderProxyImpl::notifyAssetRelease()
+{
+ mRMALock.lock();
+ if (mRenderMeshActor != NULL)
+ {
+ mRenderMeshActor->release();
+ mRenderMeshActor = NULL;
+ }
+ mRenderMeshAsset = NULL;
+ mRMALock.unlock();
+}
+
+}
+} // namespace nvidia
+
diff --git a/APEX_1.4/module/clothing/src/ClothingScene.cpp b/APEX_1.4/module/clothing/src/ClothingScene.cpp
new file mode 100644
index 00000000..cd4f5985
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/ClothingScene.cpp
@@ -0,0 +1,889 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+
+#include "ApexDefs.h"
+
+#include "Apex.h"
+#include "ClothingScene.h"
+#include "ClothingActorImpl.h"
+#include "ClothingAssetImpl.h"
+#include "ClothingCooking.h"
+#include "SceneIntl.h"
+#include "ClothingRenderProxyImpl.h"
+
+#include "DebugRenderParams.h"
+#include "ProfilerCallback.h"
+
+#include "Simulation.h"
+
+#include "PsThread.h"
+#include "ApexUsingNamespace.h"
+#include "PsAtomic.h"
+
+#if APEX_CUDA_SUPPORT
+#include "PxGpuDispatcher.h"
+#endif
+
+#include "ApexPvdClient.h"
+
+namespace nvidia
+{
+namespace clothing
+{
+
+ClothingScene::ClothingScene(ModuleClothingImpl& _module, SceneIntl& scene, RenderDebugInterface* renderDebug, ResourceList& list)
+ : mModule(&_module)
+ , mApexScene(&scene)
+#if PX_PHYSICS_VERSION_MAJOR == 3
+ , mPhysXScene(NULL)
+#endif
+ , mSumBenefit(0)
+ , mWaitForSolverTask(NULL)
+ , mSimulationTask(NULL)
+ , mSceneRunning(0)
+ , mRenderDebug(renderDebug)
+ , mDebugRenderParams(NULL)
+ , mClothingDebugRenderParams(NULL)
+ , mCurrentCookingTask(NULL)
+ , mCurrentSimulationDelta(0)
+ , mAverageSimulationFrequency(0.0f)
+#ifndef _DEBUG
+ , mFramesCount(0)
+ , mSimulatedTime(0.f)
+ , mTimestep(0.f)
+#endif
+ , mCpuFactory(NULL, NULL)
+#if APEX_CUDA_SUPPORT
+ , mGpuFactory(NULL, NULL)
+ , mPhysXGpuIndicator(NULL)
+#endif
+{
+ mClothingBeforeTickStartTask.setScene(this);
+ list.add(*this);
+
+ /* Initialize reference to ClothingDebugRenderParams */
+ mDebugRenderParams = DYNAMIC_CAST(DebugRenderParams*)(mApexScene->getDebugRenderParams());
+ PX_ASSERT(mDebugRenderParams);
+ NvParameterized::Handle handle(*mDebugRenderParams), memberHandle(*mDebugRenderParams);
+ int size;
+
+ if (mDebugRenderParams->getParameterHandle("moduleName", handle) == NvParameterized::ERROR_NONE)
+ {
+ handle.getArraySize(size, 0);
+ handle.resizeArray(size + 1);
+ if (handle.getChildHandle(size, memberHandle) == NvParameterized::ERROR_NONE)
+ {
+ memberHandle.initParamRef(ClothingDebugRenderParams::staticClassName(), true);
+ }
+ }
+
+ /* Load reference to ClothingDebugRenderParams */
+ NvParameterized::Interface* refPtr = NULL;
+ memberHandle.getParamRef(refPtr);
+ mClothingDebugRenderParams = DYNAMIC_CAST(ClothingDebugRenderParams*)(refPtr);
+ PX_ASSERT(mClothingDebugRenderParams);
+
+ mLastSimulationDeltas.reserve(mModule->getAvgSimFrequencyWindowSize());
+
+ mWaitForSolverTask = PX_NEW(WaitForSolverTask)(this);
+
+ mSimulationTask = PX_NEW(ClothingSceneSimulateTask)(mApexScene, this, mModule, GetInternalApexSDK()->getProfileZoneManager());
+ mSimulationTask->setWaitTask(mWaitForSolverTask);
+}
+
+
+
+ClothingScene::~ClothingScene()
+{
+}
+
+
+
+void ClothingScene::simulate(float elapsedTime)
+{
+ for (uint32_t i = 0; i < mActorArray.size(); i++)
+ {
+ ClothingActorImpl* clothingActor = static_cast<ClothingActorImpl*>(mActorArray[i]);
+ clothingActor->waitForFetchResults();
+ }
+
+ if (mLastSimulationDeltas.size() < mLastSimulationDeltas.capacity())
+ {
+ mCurrentSimulationDelta = mLastSimulationDeltas.size();
+ mLastSimulationDeltas.pushBack(elapsedTime);
+ }
+ else if (mLastSimulationDeltas.size() > 0)
+ {
+ mCurrentSimulationDelta = (mCurrentSimulationDelta + 1) % mLastSimulationDeltas.size();
+ mLastSimulationDeltas[mCurrentSimulationDelta] = elapsedTime;
+ }
+
+ float temp = 0.0f;
+ for (uint32_t i = 0; i < mLastSimulationDeltas.size(); i++)
+ temp += mLastSimulationDeltas[i];
+
+ if (temp > 0.0f)
+ mAverageSimulationFrequency = (float)(mLastSimulationDeltas.size()) / temp;
+ else
+ mAverageSimulationFrequency = 0.0f;
+
+ tickRenderProxies();
+}
+
+
+
+bool ClothingScene::needsManualSubstepping() const
+{
+ // we could test if any of them is being simulated, but assuming some sane budget settings
+ // there will always be >0 clothing actors simulated if there are any present
+
+ if (!mModule->allowApexWorkBetweenSubsteps())
+ {
+ return false;
+ }
+
+ // PH: new rule. The actual simulation object needs to request this too!
+ bool manualSubstepping = false;
+ for (uint32_t i = 0; i < mActorArray.size(); i++)
+ {
+ ClothingActorImpl* clothingActor = static_cast<ClothingActorImpl*>(mActorArray[i]);
+ manualSubstepping |= clothingActor->needsManualSubstepping();
+ }
+ return manualSubstepping;
+}
+
+
+
+void ClothingScene::interStep(uint32_t substepNumber, uint32_t maxSubSteps)
+{
+ for (uint32_t i = 0; i < mActorArray.size(); i++)
+ {
+ ClothingActorImpl* clothingActor = static_cast<ClothingActorImpl*>(mActorArray[i]);
+
+ if (clothingActor->needsManualSubstepping())
+ {
+ clothingActor->tickSynchBeforeSimulate_LocksPhysX(0.0f, 0.0f, substepNumber, maxSubSteps);
+ clothingActor->skinPhysicsMesh(maxSubSteps > 1, (float)(substepNumber + 1) / (float)maxSubSteps);
+ clothingActor->updateConstrainPositions_LocksPhysX();
+ clothingActor->applyCollision_LocksPhysX();
+ }
+ }
+}
+
+
+
+void ClothingScene::submitTasks(float elapsedTime, float substepSize, uint32_t numSubSteps)
+{
+ PxTaskManager* taskManager = mApexScene->getTaskManager();
+ const bool isFinalStep = mApexScene->isFinalStep();
+
+ for (uint32_t i = 0; i < mActorArray.size(); i++)
+ {
+ ClothingActorImpl* clothingActor = static_cast<ClothingActorImpl*>(mActorArray[i]);
+#if APEX_UE4
+ clothingActor->initBeforeTickTasks(elapsedTime, substepSize, numSubSteps, taskManager, 0, 0);
+#else
+ clothingActor->initBeforeTickTasks(elapsedTime, substepSize, numSubSteps);
+#endif
+
+ if (isFinalStep)
+ {
+ clothingActor->submitTasksDuring(taskManager);
+ }
+ }
+
+ taskManager->submitUnnamedTask(mClothingBeforeTickStartTask);
+
+ mSimulationTask->setDeltaTime(elapsedTime);
+ if (elapsedTime > 0.0f)
+ {
+ taskManager->submitUnnamedTask(*mSimulationTask);
+ taskManager->submitUnnamedTask(*mWaitForSolverTask);
+ }
+}
+
+
+
+void ClothingScene::setTaskDependencies()
+{
+ PxTaskManager* taskManager = mApexScene->getTaskManager();
+ const PxTaskID physxTick = taskManager->getNamedTask(AST_PHYSX_SIMULATE);
+ PxTask* physxTickTask = taskManager->getTaskFromID(physxTick);
+
+#if APEX_DURING_TICK_TIMING_FIX
+ const PxTaskID duringFinishedId = taskManager->getNamedTask(AST_DURING_TICK_COMPLETE);
+#else
+ const PxTaskID duringFinishedId = taskManager->getNamedTask(AST_PHYSX_CHECK_RESULTS);
+#endif
+
+ bool startSimulateTask = mSimulationTask->getDeltaTime() > 0;
+
+#if APEX_UE4
+ PxTask* dependentTask = physxTickTask;
+ PxTaskID duringStartId = physxTick;
+
+ if (startSimulateTask)
+ {
+ dependentTask = mSimulationTask;
+ duringStartId = mSimulationTask->getTaskID();
+ mSimulationTask->startAfter(mClothingBeforeTickStartTask.getTaskID());
+ }
+#else
+ PxTaskID duringStartId = startSimulateTask ? mSimulationTask->getTaskID() : physxTick;
+#endif
+ const bool isFinalStep = mApexScene->isFinalStep();
+
+ for (uint32_t i = 0; i < mActorArray.size(); i++)
+ {
+ ApexActor* actor = mActorArray[i];
+ ClothingActorImpl* clothingActor = static_cast<ClothingActorImpl*>(actor);
+#if !APEX_UE4
+ PxTask* dependentTask = physxTickTask;
+ if (startSimulateTask)
+ {
+ dependentTask = mSimulationTask;
+ mSimulationTask->startAfter(mClothingBeforeTickStartTask.getTaskID());
+ }
+#endif
+
+ clothingActor->setTaskDependenciesBefore(dependentTask);
+
+ if (isFinalStep)
+ {
+ // PH: daisy chain the during tasks to not trash other (=PhysX) tasks' cache etc.
+ // HL: found a case where duringTick becomes the bottleneck because of the daisy chaining
+
+ /*duringStartId = */clothingActor->setTaskDependenciesDuring(duringStartId, duringFinishedId);
+ }
+ }
+#if APEX_UE4
+ mSimulationTask->startAfter(mClothingBeforeTickStartTask.getTaskID());
+#endif
+
+ mClothingBeforeTickStartTask.finishBefore(physxTick);
+
+ if (startSimulateTask)
+ {
+ mSimulationTask->finishBefore(physxTick);
+ mWaitForSolverTask->startAfter(mSimulationTask->getTaskID());
+ mWaitForSolverTask->startAfter(duringFinishedId);
+ mWaitForSolverTask->finishBefore(taskManager->getNamedTask(AST_PHYSX_FETCH_RESULTS));
+ }
+}
+
+
+
+void ClothingScene::fetchResults()
+{
+ if (!mApexScene->isFinalStep())
+ {
+ return;
+ }
+
+ PX_PROFILE_ZONE("ClothingScene::fetchResults", GetInternalApexSDK()->getContextId());
+
+ // make sure to start cooking tasks if possible (and delete old ones)
+ submitCookingTask(NULL);
+
+ if (!mModule->allowAsyncFetchResults())
+ {
+ for (uint32_t i = 0; i < mActorArray.size(); i++)
+ {
+ ClothingActorImpl* clothingActor = static_cast<ClothingActorImpl*>(mActorArray[i]);
+ clothingActor->waitForFetchResults();
+ }
+ }
+
+ // TBD - if we need to send callbacks to the user, add them here
+}
+
+
+#if PX_PHYSICS_VERSION_MAJOR == 3
+
+void ClothingScene::setModulePhysXScene(PxScene* newPhysXScene)
+{
+ if (mPhysXScene == newPhysXScene)
+ {
+ return;
+ }
+
+ PxScene* oldPhysXScene = mPhysXScene;
+
+ mPhysXScene = newPhysXScene;
+ for (uint32_t i = 0; i < mActorArray.size(); ++i)
+ {
+ // downcast
+ ClothingActorImpl* actor = static_cast<ClothingActorImpl*>(mActorArray[i]);
+
+ actor->setPhysXScene(newPhysXScene);
+ }
+
+ mClothingAssetsMutex.lock();
+ mClothingAssets.clear();
+ mClothingAssetsMutex.unlock();
+
+#if APEX_CUDA_SUPPORT
+ {
+ if (mGpuFactory.factory != NULL && oldPhysXScene != NULL)
+ {
+ mSimulationTask->clearGpuSolver();
+ PX_ASSERT(mApexScene->getTaskManager() == oldPhysXScene->getTaskManager());
+ if (newPhysXScene != NULL)
+ {
+ mModule->releaseClothFactory(oldPhysXScene->getTaskManager()->getGpuDispatcher()->getCudaContextManager());
+ }
+ mGpuFactory.clear();
+ }
+ }
+#else
+ {
+ if (mCpuFactory.factory != NULL && oldPhysXScene != NULL)
+ {
+ if (newPhysXScene != NULL)
+ {
+ mModule->releaseClothFactory(NULL);
+ }
+ mCpuFactory.clear();
+ }
+ }
+#endif
+}
+
+#endif
+
+void ClothingScene::release()
+{
+ mModule->releaseModuleSceneIntl(*this);
+}
+
+
+
+void ClothingScene::visualize()
+{
+#ifdef WITHOUT_DEBUG_VISUALIZE
+#else
+ if (!mClothingDebugRenderParams->Actors)
+ {
+ return;
+ }
+
+ for (uint32_t i = 0; i < mActorArray.size(); i++)
+ {
+ // downcast
+ ClothingActorImpl* actor = static_cast<ClothingActorImpl*>(mActorArray[i]);
+ actor->visualize();
+ }
+#endif
+}
+
+
+
+Module* ClothingScene::getModule()
+{
+ return mModule;
+}
+
+
+
+bool ClothingScene::isSimulating() const
+{
+ if (mApexScene != NULL)
+ {
+ return mApexScene->isSimulating();
+ }
+
+ return false;
+}
+
+
+
+void ClothingScene::registerAsset(ClothingAssetImpl* asset)
+{
+ mClothingAssetsMutex.lock();
+ for (uint32_t i = 0; i < mClothingAssets.size(); i++)
+ {
+ if (mClothingAssets[i] == asset)
+ {
+ mClothingAssetsMutex.unlock();
+ return;
+ }
+ }
+ mClothingAssets.pushBack(asset);
+ mClothingAssetsMutex.unlock();
+}
+
+
+
+void ClothingScene::unregisterAsset(ClothingAssetImpl* asset)
+{
+ // remove assets from assets list
+ mClothingAssetsMutex.lock();
+ for (int32_t i = (int32_t)mClothingAssets.size() - 1; i >= 0; i--)
+ {
+ if (mClothingAssets[(uint32_t)i] == asset)
+ {
+ mClothingAssets.replaceWithLast((uint32_t)i);
+ }
+ }
+ mClothingAssetsMutex.unlock();
+
+ removeRenderProxies(asset);
+}
+
+
+
+void ClothingScene::removeRenderProxies(ClothingAssetImpl* asset)
+{
+ // delete all render proxies that have the RenderMeshAsset
+ // of this ClothingAssetImpl
+ mRenderProxiesLock.lock();
+ uint32_t numGraphicalMeshes = asset->getNumGraphicalMeshes();
+ for (uint32_t i = 0; i < numGraphicalMeshes; ++i)
+ {
+ RenderMeshAssetIntl* renderMeshAsset = asset->getGraphicalMesh(i);
+
+ Array<ClothingRenderProxyImpl*>& renderProxies = mRenderProxies[renderMeshAsset];
+ for (int32_t i = (int32_t)renderProxies.size()-1; i >= 0 ; --i)
+ {
+ ClothingRenderProxyImpl* renderProxy = renderProxies[(uint32_t)i];
+ if (renderProxy->getTimeInPool() > 0)
+ {
+ PX_DELETE(renderProxies[(uint32_t)i]);
+ }
+ else
+ {
+ renderProxy->notifyAssetRelease();
+ }
+ }
+ renderProxies.clear();
+ mRenderProxies.erase(renderMeshAsset);
+ }
+ mRenderProxiesLock.unlock();
+}
+
+
+
+uint32_t ClothingScene::submitCookingTask(ClothingCookingTask* newTask)
+{
+ mCookingTaskMutex.lock();
+
+ ClothingCookingTask** currPointer = &mCurrentCookingTask;
+ ClothingCookingTask* lastTask = NULL;
+
+ uint32_t numRunning = 0;
+ uint32_t numReleased = 0;
+
+ while (*currPointer != NULL)
+ {
+ PX_ASSERT(lastTask == NULL || currPointer == &lastTask->nextTask);
+ if ((*currPointer)->readyForRelease())
+ {
+ ClothingCookingTask* releaseMe = *currPointer;
+ *currPointer = releaseMe->nextTask;
+ delete releaseMe;
+ numReleased++;
+ }
+ else
+ {
+ lastTask = *currPointer;
+ numRunning += lastTask->waitsForBeingScheduled() ? 0 : 1;
+ currPointer = &(*currPointer)->nextTask;
+ }
+ }
+
+ // set the linked list
+ *currPointer = newTask;
+ if (newTask != NULL)
+ {
+ PX_ASSERT(mApexScene->getTaskManager() != NULL);
+ newTask->initCooking(*mApexScene->getTaskManager(), NULL);
+ }
+
+ if (numRunning == 0 && mCurrentCookingTask != NULL)
+ {
+ PX_ASSERT(mCurrentCookingTask->waitsForBeingScheduled());
+ mCurrentCookingTask->removeReference();
+ }
+
+ mCookingTaskMutex.unlock();
+
+ return numReleased;
+}
+
+
+
+void ClothingScene::destroy()
+{
+ for (uint32_t i = 0; i < mActorArray.size(); i++)
+ {
+ ClothingActorImpl* clothingActor = static_cast<ClothingActorImpl*>(mActorArray[i]);
+ clothingActor->waitForFetchResults();
+ }
+
+ removeAllActors();
+
+ mClothingAssetsMutex.lock();
+ for (uint32_t i = 0 ; i < mClothingAssets.size(); i++)
+ {
+ // for PhysX3: making sure that fabrics (in assets) are released before the factories (in mSimulationTask)
+ mClothingAssets[i]->releaseCookedInstances();
+ }
+ mClothingAssets.clear();
+ mClothingAssetsMutex.unlock();
+
+ // clear render list
+ for (HashMap<RenderMeshAssetIntl*, Array<ClothingRenderProxyImpl*> >::Iterator iter = mRenderProxies.getIterator(); !iter.done(); ++iter)
+ {
+ Array<ClothingRenderProxyImpl*>& renderProxies = iter->second;
+
+ for (int32_t i = (int32_t)renderProxies.size()-1; i >= 0 ; --i)
+ {
+ uint32_t timeInPool = renderProxies[(uint32_t)i]->getTimeInPool();
+ if (timeInPool > 0)
+ {
+ PX_DELETE(renderProxies[(uint32_t)i]);
+ renderProxies.replaceWithLast((uint32_t)i);
+ }
+ else
+ {
+ // actually the scene is released, but we just want to make sure
+ // that the render proxy deletes itself when it's returned next time
+ renderProxies[(uint32_t)i]->notifyAssetRelease();
+ }
+ }
+
+ renderProxies.clear();
+ }
+ //mRenderProxies.clear();
+
+ while (mCurrentCookingTask != NULL)
+ {
+ submitCookingTask(NULL);
+ nvidia::Thread::sleep(0); // wait for remaining cooking tasks to finish
+ }
+
+ if (mSimulationTask != NULL)
+ {
+#if PX_PHYSICS_VERSION_MAJOR == 3
+ setModulePhysXScene(NULL); // does some cleanup necessary here. Only needed when module gets deleted without the apex scene being deleted before!
+#elif APEX_CUDA_SUPPORT
+ if (mGpuFactory.factory != NULL)
+ {
+ mSimulationTask->clearGpuSolver();
+ mGpuFactory.clear();
+ }
+#endif
+ PX_DELETE(mSimulationTask);
+ mSimulationTask = NULL;
+ }
+
+ if (mWaitForSolverTask != NULL)
+ {
+ PX_DELETE(mWaitForSolverTask);
+ mWaitForSolverTask = NULL;
+ }
+
+ {
+ if (mCpuFactory.factory != NULL)
+ {
+ mCpuFactory.clear();
+ }
+
+#if APEX_CUDA_SUPPORT
+ PX_ASSERT(mGpuFactory.factory == NULL);
+
+ ApexSDKIntl* apexSdk = GetInternalApexSDK();
+ apexSdk->unregisterPhysXIndicatorGpuClient(mPhysXGpuIndicator);
+ mPhysXGpuIndicator = NULL;
+#endif
+ }
+
+ mApexScene->moduleReleased(*this);
+ delete this;
+}
+
+
+
+void ClothingScene::ClothingBeforeTickStartTask::run()
+{
+#ifdef PROFILE
+ PIXBeginNamedEvent(0, "ClothingBeforeTickStartTask");
+#endif
+ for (uint32_t i = 0; i < m_pScene->mActorArray.size(); ++i)
+ {
+ ClothingActorImpl* actor = static_cast<ClothingActorImpl*>(m_pScene->mActorArray[i]);
+
+ actor->startBeforeTickTask();
+ }
+#ifdef PROFILE
+ PIXEndNamedEvent();
+#endif
+}
+
+
+
+const char* ClothingScene::ClothingBeforeTickStartTask::getName() const
+{
+#if APEX_UE4
+ return CLOTHING_BEFORE_TICK_START_TASK_NAME;
+#else
+ return "ClothingScene::ClothingBeforeTickStartTask";
+#endif
+}
+
+
+
+ClothFactory ClothingScene::getClothFactory(bool& useCuda)
+{
+#if APEX_CUDA_SUPPORT
+ if (useCuda)
+ {
+ if (mGpuFactory.factory == NULL)
+ {
+ PxCudaContextManager* contextManager = NULL;
+ PxGpuDispatcher* gpuDispatcher = mApexScene->getTaskManager()->getGpuDispatcher();
+ if (gpuDispatcher != NULL)
+ {
+ contextManager = gpuDispatcher->getCudaContextManager();
+ }
+
+ if (contextManager != NULL)
+ {
+ mGpuFactory = mModule->createClothFactory(contextManager);
+ if (mGpuFactory.factory != NULL)
+ {
+ ApexSDKIntl* apexSdk = GetInternalApexSDK();
+ mPhysXGpuIndicator = apexSdk->registerPhysXIndicatorGpuClient();
+ }
+ }
+ }
+
+ //APEX_DEBUG_INFO("Gpu Factory %p", mGpuFactory);
+ if (mGpuFactory.factory != NULL)
+ {
+ return mGpuFactory;
+ }
+ else
+ {
+ APEX_DEBUG_INFO("Gpu Factory could not be created");
+ useCuda = false;
+ }
+ }
+
+ if (!useCuda)
+#else
+ PX_UNUSED(useCuda);
+#endif
+ {
+ if (mCpuFactory.factory == NULL)
+ {
+ mCpuFactory = mModule->createClothFactory(NULL);
+ }
+
+ //APEX_DEBUG_INFO("Cpu Factory %p", mCpuFactory.factory);
+ return mCpuFactory;
+ }
+
+#if APEX_CUDA_SUPPORT
+ PX_ALWAYS_ASSERT_MESSAGE("this code path is unreachable, at least it used to be.");
+ return ClothFactory(NULL, NULL);
+#endif
+}
+
+
+
+cloth::Solver* ClothingScene::getClothSolver(bool useCuda)
+{
+ ClothFactory factory(NULL, NULL);
+#if APEX_CUDA_SUPPORT
+ if (useCuda)
+ {
+ factory = mGpuFactory;
+ }
+ else
+#else
+ PX_UNUSED(useCuda);
+#endif
+ {
+ factory = mCpuFactory;
+ }
+
+ PX_ASSERT(factory.factory != NULL);
+ if (factory.factory != NULL)
+ {
+ return mSimulationTask->getSolver(factory);
+ }
+
+ return NULL;
+}
+
+
+
+void ClothingScene::lockScene()
+{
+ mSceneLock.lock();
+
+ if (mSceneRunning == 1)
+ {
+ APEX_INVALID_OPERATION("The scene is running while the scene write lock is being acquired!");
+ PX_ALWAYS_ASSERT();
+ }
+}
+
+
+
+void ClothingScene::unlockScene()
+{
+ mSceneLock.unlock();
+}
+
+
+
+void ClothingScene::setSceneRunning(bool on)
+{
+#ifndef _DEBUG
+ int32_t newValue;
+ if (on)
+ {
+ APEX_CHECK_STAT_TIMER("--------- Start ClothingSimulationTime");
+ mClothingSimulationTime.getElapsedSeconds();
+
+ newValue = nvidia::atomicIncrement(&mSceneRunning);
+ }
+ else
+ {
+ StatValue dataVal;
+ dataVal.Float = (float)(1000.0f * mClothingSimulationTime.getElapsedSeconds());
+ APEX_CHECK_STAT_TIMER("--------- Stop ClothingSimulationTime");
+ mApexScene->setApexStatValue(SceneIntl::ClothingSimulationTime, dataVal);
+
+ // Warn if simulation time was bigger than timestep for 10 or more consecutive frames
+ float simulatedTime = 1000.0f * mApexScene->getElapsedTime();
+ if (simulatedTime < dataVal.Float)
+ {
+ mFramesCount++;
+ mSimulatedTime += simulatedTime;
+ mTimestep += dataVal.Float;
+ }
+
+ if (mFramesCount >= 10)
+ {
+ float averageSimulatedTime = mSimulatedTime / (float)mFramesCount;
+ float averageTimestep = mTimestep / (float)mFramesCount;
+ APEX_DEBUG_WARNING("Cloth complexity in scene is too high to be simulated in real time for 10 consecutive frames. (Average Delta Time: %f ms, Average Simulation Time: %f ms)",
+ averageSimulatedTime, averageTimestep);
+ mFramesCount = 0;
+ mSimulatedTime = 0.f;
+ mTimestep = 0.f;
+ }
+
+ newValue = nvidia::atomicDecrement(&mSceneRunning);
+ }
+
+ if (newValue != (on ? 1 : 0))
+ {
+ APEX_INTERNAL_ERROR("scene running state was not tracked properly!: on = %s, prevValue = %d", on ? "true" : "false", newValue);
+ }
+#else
+ PX_UNUSED(on);
+#endif
+}
+
+
+
+void ClothingScene::embeddedPostSim()
+{
+ for (uint32_t i = 0; i < mActorArray.size(); i++)
+ {
+ ClothingActorImpl* clothingActor = static_cast<ClothingActorImpl*>(mActorArray[i]);
+ clothingActor->startFetchTasks();
+ }
+}
+
+
+
+ClothingRenderProxyImpl* ClothingScene::getRenderProxy(RenderMeshAssetIntl* rma, bool useFallbackSkinning, bool useCustomVertexBuffer, const HashMap<uint32_t, ApexSimpleString>& overrideMaterials, const PxVec3* morphTargetNewPositions, const uint32_t* morphTargetVertexOffsets)
+{
+ if (rma == NULL)
+ {
+ return NULL;
+ }
+
+ ClothingRenderProxyImpl* renderProxy = NULL;
+
+
+ mRenderProxiesLock.lock();
+ Array<ClothingRenderProxyImpl*>& renderProxies = mRenderProxies[rma];
+ for (uint32_t i = 0; i < renderProxies.size(); ++i)
+ {
+ ClothingRenderProxyImpl* proxyInPool = renderProxies[i];
+ if (
+ proxyInPool->getTimeInPool() > 0 && // proxy is available
+ useFallbackSkinning == proxyInPool->usesFallbackSkinning() &&
+ useCustomVertexBuffer == proxyInPool->usesCustomVertexBuffer() &&
+ morphTargetNewPositions == proxyInPool->getMorphTargetBuffer() &&
+ proxyInPool->overrideMaterialsEqual(overrideMaterials)
+ )
+ {
+ renderProxy = proxyInPool;
+ break;
+ }
+ }
+
+ // no corresponding proxy in pool, so create one
+ if (renderProxy == NULL)
+ {
+ renderProxy = PX_NEW(ClothingRenderProxyImpl)(rma, useFallbackSkinning, useCustomVertexBuffer, overrideMaterials, morphTargetNewPositions, morphTargetVertexOffsets, this);
+ renderProxies.pushBack(renderProxy);
+ }
+
+ renderProxy->setTimeInPool(0);
+ mRenderProxiesLock.unlock();
+
+ return renderProxy;
+}
+
+
+
+void ClothingScene::tickRenderProxies()
+{
+ PX_PROFILE_ZONE("ClothingScene::tickRenderProxies", GetInternalApexSDK()->getContextId());
+ mRenderProxiesLock.lock();
+
+ for(HashMap<RenderMeshAssetIntl*, Array<ClothingRenderProxyImpl*> >::Iterator iter = mRenderProxies.getIterator(); !iter.done(); ++iter)
+ {
+ Array<ClothingRenderProxyImpl*>& renderProxies = iter->second;
+
+ for (int32_t i = (int32_t)renderProxies.size()-1; i >= 0 ; --i)
+ {
+ uint32_t timeInPool = renderProxies[(uint32_t)i]->getTimeInPool();
+
+ if (timeInPool > 0)
+ {
+ if (timeInPool > mModule->getMaxTimeRenderProxyInPool() + 1) // +1 because we add them with time 1
+ {
+ PX_DELETE(renderProxies[(uint32_t)i]);
+ renderProxies.replaceWithLast((uint32_t)i);
+ }
+ else
+ {
+ renderProxies[(uint32_t)i]->setTimeInPool(timeInPool+1);
+ }
+ }
+ }
+ }
+
+ mRenderProxiesLock.unlock();
+}
+
+}
+} // namespace nvidia
+
diff --git a/APEX_1.4/module/clothing/src/CookingAbstract.cpp b/APEX_1.4/module/clothing/src/CookingAbstract.cpp
new file mode 100644
index 00000000..8d40c927
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/CookingAbstract.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+
+#include "CookingAbstract.h"
+
+
+
+namespace nvidia
+{
+namespace clothing
+{
+
+using namespace nvidia;
+
+void CookingAbstract::PhysicalMesh::computeTriangleAreas()
+{
+ smallestTriangleArea = largestTriangleArea = 0.0f;
+
+ if (indices == NULL || vertices == NULL)
+ {
+ return;
+ }
+
+ smallestTriangleArea = PX_MAX_F32;
+
+ for (uint32_t i = 0; i < numIndices; i += 3)
+ {
+ const PxVec3 edge1 = vertices[indices[i + 1]] - vertices[indices[i]];
+ const PxVec3 edge2 = vertices[indices[i + 2]] - vertices[indices[i]];
+ const float triangleArea = edge1.cross(edge2).magnitude();
+
+ largestTriangleArea = PxMax(largestTriangleArea, triangleArea);
+ smallestTriangleArea = PxMin(smallestTriangleArea, triangleArea);
+ }
+}
+
+
+
+void CookingAbstract::addPhysicalMesh(const PhysicalMesh& physicalMesh)
+{
+ PhysicalMesh physicalMeshCopy = physicalMesh;
+ physicalMeshCopy.computeTriangleAreas();
+ mPhysicalMeshes.pushBack(physicalMeshCopy);
+}
+
+
+
+void CookingAbstract::setConvexBones(const BoneActorEntry* boneActors, uint32_t numBoneActors, const BoneEntry* boneEntries,
+ uint32_t numBoneEntries, const PxVec3* boneVertices, uint32_t maxConvexVertices)
+{
+ mBoneActors = boneActors;
+ mNumBoneActors = numBoneActors;
+ mBoneEntries = boneEntries;
+ mNumBoneEntries = numBoneEntries;
+ mBoneVertices = boneVertices;
+
+ PX_ASSERT(maxConvexVertices <= 256);
+ mMaxConvexVertices = maxConvexVertices;
+}
+
+
+bool CookingAbstract::isValid() const
+{
+ return mPhysicalMeshes.size() > 0;
+}
+
+}
+} \ No newline at end of file
diff --git a/APEX_1.4/module/clothing/src/ModuleClothingHelpers.cpp b/APEX_1.4/module/clothing/src/ModuleClothingHelpers.cpp
new file mode 100644
index 00000000..7fbe1c46
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/ModuleClothingHelpers.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+
+#include "ApexDefs.h"
+
+#include "ModuleClothingHelpers.h"
+#include "AbstractMeshDescription.h"
+
+namespace nvidia
+{
+namespace apex
+{
+
+void AbstractMeshDescription::UpdateDerivedInformation(RenderDebugInterface* renderDebug)
+{
+ if (numIndices > 0)
+ {
+ pMin = pPosition[pIndices[0]];
+ pMax = pMin;
+ }
+ avgEdgeLength = 0;
+ avgTriangleArea = 0;
+
+ uint32_t triCount(numIndices / 3);
+ uint32_t edgeCount(numIndices);
+ for (uint32_t j = 0; j < numIndices; j += 3)
+ {
+ uint32_t i0 = pIndices[j + 0];
+ uint32_t i1 = pIndices[j + 1];
+ uint32_t i2 = pIndices[j + 2];
+
+ const PxVec3& v0 = pPosition[i0];
+ const PxVec3& v1 = pPosition[i1];
+ const PxVec3& v2 = pPosition[i2];
+
+ pMin.minimum(v0);
+ pMin.minimum(v1);
+ pMin.minimum(v2);
+
+ pMax.maximum(v0);
+ pMax.maximum(v1);
+ pMax.maximum(v2);
+
+ PxVec3 e0 = v1 - v0;
+ PxVec3 e1 = v2 - v1;
+ PxVec3 e2 = v0 - v2;
+
+ avgEdgeLength += e0.magnitude();
+ avgEdgeLength += e1.magnitude();
+ avgEdgeLength += e2.magnitude();
+
+
+ if (renderDebug)
+ {
+ using RENDER_DEBUG::DebugColors;
+ RENDER_DEBUG_IFACE(renderDebug)->setCurrentColor(RENDER_DEBUG_IFACE(renderDebug)->getDebugColor(DebugColors::DarkBlue));
+ RENDER_DEBUG_IFACE(renderDebug)->debugLine(v0, v1);
+ RENDER_DEBUG_IFACE(renderDebug)->debugLine(v1, v2);
+ RENDER_DEBUG_IFACE(renderDebug)->debugLine(v2, v0);
+ RENDER_DEBUG_IFACE(renderDebug)->setCurrentColor(RENDER_DEBUG_IFACE(renderDebug)->getDebugColor(DebugColors::Green));
+ RENDER_DEBUG_IFACE(renderDebug)->debugPoint(v0, 0.1f);
+ RENDER_DEBUG_IFACE(renderDebug)->debugPoint(v1, 0.1f);
+ RENDER_DEBUG_IFACE(renderDebug)->debugPoint(v2, 0.1f);
+ }
+
+ float triangleArea = e0.cross(e2).magnitude() * 0.5f;
+ avgTriangleArea += triangleArea;
+ triCount++;
+ }
+
+ avgEdgeLength /= edgeCount;
+ avgTriangleArea /= triCount;
+ centroid = 0.5f * (pMin + pMax);
+ radius = 0.5f * (pMax - pMin).magnitude();
+
+ //printf("Min = <%f, %f, %f>; Max = <%f, %f, %f>; centroid = <%f, %f, %f>; radius = %f; avgEdgeLength = %f; avgTriangleArea = %f;\n",
+ // pMin.x, pMin.y, pMin.z, pMax.x, pMax.y, pMax.z, centroid.x, centroid.y, centroid.z, radius, avgEdgeLength, avgTriangleArea);
+}
+
+}
+} // namespace nvidia
+
diff --git a/APEX_1.4/module/clothing/src/ModuleClothingImpl.cpp b/APEX_1.4/module/clothing/src/ModuleClothingImpl.cpp
new file mode 100644
index 00000000..0baec7bb
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/ModuleClothingImpl.cpp
@@ -0,0 +1,1210 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+
+#include "ApexDefs.h"
+
+#include "ApexAuthorableObject.h"
+#include "ApexIsoMesh.h"
+#include "ApexSubdivider.h"
+#include "ApexSharedUtils.h"
+
+#include "RenderMeshAssetIntl.h"
+#include <limits.h>
+#include <new>
+
+#include "PxCudaContextManager.h"
+#include "Factory.h"
+
+#include "ModuleClothingImpl.h"
+#include "ModuleClothingRegistration.h"
+
+#include "ClothingAssetImpl.h"
+#include "ClothingAssetAuthoringImpl.h"
+#include "ClothingPhysicalMeshImpl.h"
+#include "SceneIntl.h"
+
+#include "ClothingScene.h"
+#include "ModulePerfScope.h"
+
+#include "CookingPhysX.h"
+#include "Cooking.h"
+#include "Simulation.h"
+
+#include "ApexSDKIntl.h"
+#include "ApexUsingNamespace.h"
+
+#if APEX_CUDA_SUPPORT
+#include "CuFactory.h"
+#endif
+
+#include "ApexPvdClient.h"
+
+using namespace clothing;
+using namespace physx::pvdsdk;
+
+#define INIT_PVD_CLASSES_PARAMETERIZED( parameterizedClassName ) { \
+ pvdStream.createClass(NamespacedName(APEX_PVD_NAMESPACE, #parameterizedClassName)); \
+ parameterizedClassName* params = DYNAMIC_CAST(parameterizedClassName*)(GetInternalApexSDK()->getParameterizedTraits()->createNvParameterized(#parameterizedClassName)); \
+ client->initPvdClasses(*params->rootParameterDefinition(), #parameterizedClassName); \
+ params->destroy(); }
+
+
+namespace nvidia
+{
+namespace apex
+{
+
+#if defined(_USRDLL) || PX_OSX
+
+/* Modules don't have to link against the framework, they keep their own */
+ApexSDKIntl* gApexSdk = 0;
+ApexSDK* GetApexSDK()
+{
+ return gApexSdk;
+}
+ApexSDKIntl* GetInternalApexSDK()
+{
+ return gApexSdk;
+}
+
+APEX_API Module* CALL_CONV createModule(
+ ApexSDKIntl* inSdk,
+ ModuleIntl** niRef,
+ uint32_t APEXsdkVersion,
+ uint32_t PhysXsdkVersion,
+ ApexCreateError* errorCode)
+{
+ if (APEXsdkVersion != APEX_SDK_VERSION)
+ {
+ if (errorCode)
+ {
+ *errorCode = APEX_CE_WRONG_VERSION;
+ }
+ return NULL;
+ }
+
+ if (PhysXsdkVersion != PX_PHYSICS_VERSION)
+ {
+ if (errorCode)
+ {
+ *errorCode = APEX_CE_WRONG_VERSION;
+ }
+ return NULL;
+ }
+
+ gApexSdk = inSdk;
+ clothing::ModuleClothingImpl* impl = PX_NEW(clothing::ModuleClothingImpl)(inSdk);
+ *niRef = (ModuleIntl*) impl;
+ return (Module*) impl;
+}
+
+#else // !defined(_USRDLL) && !PX_OSX
+
+/* Statically linking entry function */
+void instantiateModuleClothing()
+{
+ using namespace clothing;
+ ApexSDKIntl* sdk = GetInternalApexSDK();
+ clothing::ModuleClothingImpl* impl = PX_NEW(clothing::ModuleClothingImpl)(sdk);
+ sdk->registerExternalModule((Module*) impl, (ModuleIntl*) impl);
+}
+#endif // !defined(_USRDLL) && !PX_OSX
+}
+
+namespace clothing
+{
+
+// This is needed to have an actor assigned to every PxActor, even if they currently don't belong to an ClothingActor
+class DummyActor : public Actor, public UserAllocated, public ApexRWLockable
+{
+public:
+ APEX_RW_LOCKABLE_BOILERPLATE
+
+ DummyActor(Asset* owner) : mOwner(owner) {}
+ void release()
+ {
+ PX_DELETE(this);
+ }
+ Asset* getOwner() const
+ {
+ return mOwner;
+ }
+
+ void getLodRange(float& min, float& max, bool& intOnly) const
+ {
+ PX_UNUSED(min);
+ PX_UNUSED(max);
+ PX_UNUSED(intOnly);
+ }
+
+ float getActiveLod() const
+ {
+ return -1.0f;
+ }
+
+ void forceLod(float lod)
+ {
+ PX_UNUSED(lod);
+ }
+
+ /**
+ \brief Selectively enables/disables debug visualization of a specific APEX actor. Default value it true.
+ */
+ virtual void setEnableDebugVisualization(bool state)
+ {
+ PX_UNUSED(state);
+ }
+
+private:
+ Asset* mOwner;
+};
+
+
+
+// This is needed to for every dummy actor to point to an asset that in turn has the right object type id.
+class DummyAsset : public Asset, public UserAllocated, public ApexRWLockable
+{
+public:
+ APEX_RW_LOCKABLE_BOILERPLATE
+
+ DummyAsset(AuthObjTypeID assetTypeID) : mAssetTypeID(assetTypeID) {};
+
+ void release()
+ {
+ PX_DELETE(this);
+ }
+
+ virtual const char* getName() const
+ {
+ return NULL;
+ }
+ virtual AuthObjTypeID getObjTypeID() const
+ {
+ return mAssetTypeID;
+ }
+ virtual const char* getObjTypeName() const
+ {
+ return NULL;
+ }
+ virtual uint32_t forceLoadAssets()
+ {
+ return 0;
+ }
+ virtual const NvParameterized::Interface* getAssetNvParameterized() const
+ {
+ return NULL;
+ }
+
+ NvParameterized::Interface* getDefaultActorDesc()
+ {
+ PX_ALWAYS_ASSERT();
+ return NULL;
+ };
+ NvParameterized::Interface* getDefaultAssetPreviewDesc()
+ {
+ PX_ALWAYS_ASSERT();
+ return NULL;
+ };
+
+ virtual Actor* createApexActor(const NvParameterized::Interface& /*parms*/, Scene& /*apexScene*/)
+ {
+ PX_ALWAYS_ASSERT();
+ return NULL;
+ }
+
+ virtual AssetPreview* createApexAssetPreview(const ::NvParameterized::Interface& /*params*/, AssetPreviewScene* /*previewScene*/)
+ {
+ PX_ALWAYS_ASSERT();
+ return NULL;
+ }
+
+ virtual bool isValidForActorCreation(const ::NvParameterized::Interface& /*parms*/, Scene& /*apexScene*/) const
+ {
+ return true; // TODO implement this method
+ }
+
+ virtual bool isDirty() const
+ {
+ return false;
+ }
+
+
+ /**
+ * \brief Releases the ApexAsset but returns the NvParameterized::Interface and *ownership* to the caller.
+ */
+ virtual NvParameterized::Interface* releaseAndReturnNvParameterizedInterface(void)
+ {
+ return NULL;
+ }
+
+private:
+ AuthObjTypeID mAssetTypeID;
+};
+
+ModuleClothingImpl::ModuleClothingImpl(ApexSDKIntl* inSdk)
+ : mDummyActor(NULL)
+ , mDummyAsset(NULL)
+ , mModuleParams(NULL)
+ , mApexClothingActorParams(NULL)
+ , mApexClothingPreviewParams(NULL)
+ , mCpuFactory(NULL)
+ , mCpuFactoryReferenceCount(0)
+#if APEX_CUDA_SUPPORT
+ , mGpuDllHandle(NULL)
+ , mPxCreateCuFactoryFunc(NULL)
+#endif
+{
+ mInternalModuleParams.maxNumCompartments = 4;
+ mInternalModuleParams.maxUnusedPhysXResources = 5;
+ mInternalModuleParams.allowAsyncCooking = true;
+ mInternalModuleParams.avgSimFrequencyWindow = 60;
+ mInternalModuleParams.allowApexWorkBetweenSubsteps = true;
+ mInternalModuleParams.interCollisionDistance = 0.0f;
+ mInternalModuleParams.interCollisionStiffness = 1.0f;
+ mInternalModuleParams.interCollisionIterations = 1;
+ mInternalModuleParams.sparseSelfCollision = false;
+ mInternalModuleParams.maxTimeRenderProxyInPool = 100;
+ PX_COMPILE_TIME_ASSERT(sizeof(mInternalModuleParams) == 40); // don't forget to init the new param here (and then update this assert)
+
+ mName = "Clothing";
+ mSdk = inSdk;
+ mApiProxy = this;
+
+ NvParameterized::Traits* traits = mSdk->getParameterizedTraits();
+ if (traits)
+ {
+ ModuleClothingRegistration::invokeRegistration(traits);
+ mApexClothingActorParams = traits->createNvParameterized(ClothingActorParam::staticClassName());
+ mApexClothingPreviewParams = traits->createNvParameterized(ClothingPreviewParam::staticClassName());
+ }
+
+#if APEX_CUDA_SUPPORT
+ // Since we split out the GPU code, we load the module and create the CuFactory ourselves
+ ApexSimpleString gpuClothingDllName;
+ PX_COMPILE_TIME_ASSERT(sizeof(HMODULE) == sizeof(mGpuDllHandle));
+ {
+ ModuleUpdateLoader moduleLoader(UPDATE_LOADER_DLL_NAME);
+
+#define APEX_CLOTHING_GPU_DLL_PREFIX "APEX_ClothingGPU"
+
+#ifdef PX_PHYSX_DLL_NAME_POSTFIX
+# if PX_X86
+ static const char* gpuClothingDllPrefix = APEX_CLOTHING_GPU_DLL_PREFIX PX_STRINGIZE(PX_PHYSX_DLL_NAME_POSTFIX) "_x86";
+# elif PX_X64
+ static const char* gpuClothingDllPrefix = APEX_CLOTHING_GPU_DLL_PREFIX PX_STRINGIZE(PX_PHYSX_DLL_NAME_POSTFIX) "_x64";
+# endif
+#else
+# if PX_X86
+ static const char* gpuClothingDllPrefix = APEX_CLOTHING_GPU_DLL_PREFIX "_x86";
+# elif PX_X64
+ static const char* gpuClothingDllPrefix = APEX_CLOTHING_GPU_DLL_PREFIX "_x64";
+# endif
+#endif
+
+#undef APEX_CLOTHING_GPU_DLL_PREFIX
+
+ gpuClothingDllName = ApexSimpleString(gpuClothingDllPrefix);
+
+ // applications can append strings to the APEX DLL filenames, support this with getCustomDllNamePostfix()
+ gpuClothingDllName += ApexSimpleString(GetInternalApexSDK()->getCustomDllNamePostfix());
+ gpuClothingDllName += ApexSimpleString(".dll");
+
+ mGpuDllHandle = moduleLoader.loadModule(gpuClothingDllName.c_str(), GetInternalApexSDK()->getAppGuid());
+ }
+
+ if (mGpuDllHandle)
+ {
+ mPxCreateCuFactoryFunc = (PxCreateCuFactory_FUNC*)GetProcAddress((HMODULE)mGpuDllHandle, "PxCreateCuFactory");
+ if (mPxCreateCuFactoryFunc == NULL)
+ {
+ APEX_DEBUG_WARNING("Failed to find method PxCreateCuFactory in dll \'%s\'", gpuClothingDllName.c_str());
+ FreeLibrary((HMODULE)mGpuDllHandle);
+ mGpuDllHandle = NULL;
+ }
+ }
+ else if (!gpuClothingDllName.empty())
+ {
+ APEX_DEBUG_WARNING("Failed to load the GPU dll \'%s\'", gpuClothingDllName.c_str());
+ }
+#endif
+}
+
+
+
+AuthObjTypeID ModuleClothingImpl::getModuleID() const
+{
+ return ClothingAssetImpl::mAssetTypeID;
+}
+
+
+
+RenderableIterator* ModuleClothingImpl::createRenderableIterator(const Scene& apexScene)
+{
+ ClothingScene* cs = getClothingScene(apexScene);
+ if (cs)
+ {
+ return cs->createRenderableIterator();
+ }
+
+ return NULL;
+}
+
+#ifdef WITHOUT_APEX_AUTHORING
+
+class ClothingAssetDummyAuthoring : public AssetAuthoring, public UserAllocated
+{
+public:
+ ClothingAssetDummyAuthoring(ModuleClothingImpl* module, ResourceList& list, NvParameterized::Interface* params, const char* name)
+ {
+ PX_UNUSED(module);
+ PX_UNUSED(list);
+ PX_UNUSED(params);
+ PX_UNUSED(name);
+ }
+
+ ClothingAssetDummyAuthoring(ModuleClothingImpl* module, ResourceList& list, const char* name)
+ {
+ PX_UNUSED(module);
+ PX_UNUSED(list);
+ PX_UNUSED(name);
+ }
+
+ ClothingAssetDummyAuthoring(ModuleClothingImpl* module, ResourceList& list)
+ {
+ PX_UNUSED(module);
+ PX_UNUSED(list);
+ }
+
+ virtual ~ClothingAssetDummyAuthoring() {}
+
+ virtual void setToolString(const char* /*toolName*/, const char* /*toolVersion*/, uint32_t /*toolChangelist*/)
+ {
+
+ }
+
+
+ virtual void release()
+ {
+ destroy();
+ }
+
+ // internal
+ void destroy()
+ {
+ PX_DELETE(this);
+ }
+
+ /**
+ * \brief Returns the name of this APEX authorable object type
+ */
+ virtual const char* getObjTypeName() const
+ {
+ return CLOTHING_AUTHORING_TYPE_NAME;
+ }
+
+ /**
+ * \brief Prepares a fully authored Asset Authoring object for a specified platform
+ */
+ virtual bool prepareForPlatform(nvidia::apex::PlatformTag)
+ {
+ PX_ASSERT(0);
+ return false;
+ }
+
+ const char* getName(void) const
+ {
+ return NULL;
+ }
+
+ /**
+ * \brief Save asset's NvParameterized interface, may return NULL
+ */
+ virtual NvParameterized::Interface* getNvParameterized() const
+ {
+ PX_ASSERT(0);
+ return NULL; //ClothingAssetImpl::getAssetNvParameterized();
+ }
+
+ virtual NvParameterized::Interface* releaseAndReturnNvParameterizedInterface(void)
+ {
+ PX_ALWAYS_ASSERT();
+ return NULL;
+ }
+
+};
+
+typedef ApexAuthorableObject<ModuleClothingImpl, ClothingAssetImpl, ClothingAssetDummyAuthoring> ClothingAO;
+#else
+typedef ApexAuthorableObject<ModuleClothingImpl, ClothingAssetImpl, ClothingAssetAuthoringImpl> ClothingAO;
+#endif
+
+NvParameterized::Interface* ModuleClothingImpl::getDefaultModuleDesc()
+{
+ NvParameterized::Traits* traits = mSdk->getParameterizedTraits();
+
+ if (!mModuleParams)
+ {
+ mModuleParams = DYNAMIC_CAST(ClothingModuleParameters*)
+ (traits->createNvParameterized("ClothingModuleParameters"));
+ PX_ASSERT(mModuleParams);
+ }
+ else
+ {
+ mModuleParams->initDefaults();
+ }
+
+ const NvParameterized::Hint* hint = NULL;
+ NvParameterized::Handle h(mModuleParams);
+
+ h.getParameter("maxNumCompartments");
+ PX_ASSERT(h.isValid());
+#if PX_WINDOWS_FAMILY
+ hint = h.parameterDefinition()->hint("defaultValueWindows");
+#else
+ hint = h.parameterDefinition()->hint("defaultValueConsoles");
+#endif
+ PX_ASSERT(hint);
+ if (hint)
+ {
+ mModuleParams->maxNumCompartments = (uint32_t)hint->asUInt();
+ }
+
+ return mModuleParams;
+}
+
+
+
+void ModuleClothingImpl::init(NvParameterized::Interface& desc)
+{
+ if (::strcmp(desc.className(), ClothingModuleParameters::staticClassName()) == 0)
+ {
+ ClothingModuleParameters* params = DYNAMIC_CAST(ClothingModuleParameters*)(&desc);
+ mInternalModuleParams = *params;
+ }
+ else
+ {
+ APEX_INVALID_PARAMETER("The NvParameterized::Interface object is of the wrong type");
+ }
+
+
+ ClothingAO* AOClothingAsset = PX_NEW(ClothingAO)(this, mAssetAuthorableObjectFactories, ClothingAssetParameters::staticClassName());
+ ClothingAssetImpl::mAssetTypeID = AOClothingAsset->getResID();
+ registerBackendFactory(&mBackendFactory);
+
+
+#ifndef WITHOUT_PVD
+ AOClothingAsset->mAssets.setupForPvd(mApiProxy, "ClothingAssets", "ClothingAsset");
+
+ // handle case if module is created after pvd connection
+ pvdsdk::ApexPvdClient* client = mSdk->getApexPvdClient();
+ if (client != NULL)
+ {
+ if (client->isConnected() && client->getPxPvd().getInstrumentationFlags() & PxPvdInstrumentationFlag::eDEBUG)
+ {
+ pvdsdk::PvdDataStream* pvdStream = client->getDataStream();
+ if (pvdStream != NULL)
+ {
+ pvdsdk::NamespacedName pvdModuleName(APEX_PVD_NAMESPACE, getName());
+ pvdStream->createClass(pvdModuleName);
+ initPvdClasses(*pvdStream);
+
+ ModuleBase* nxModule = static_cast<ModuleBase*>(this);
+ pvdStream->createInstance(pvdModuleName, nxModule);
+ pvdStream->pushBackObjectRef(mSdk, "Modules", nxModule);
+ initPvdInstances(*pvdStream);
+ }
+ }
+ }
+#endif
+}
+
+
+
+ClothingPhysicalMesh* ModuleClothingImpl::createEmptyPhysicalMesh()
+{
+ WRITE_ZONE();
+ return createPhysicalMeshInternal(NULL);
+}
+
+
+
+ClothingPhysicalMesh* ModuleClothingImpl::createSingleLayeredMesh(RenderMeshAssetAuthoring* asset, uint32_t subdivisionSize, bool mergeVertices, bool closeHoles, IProgressListener* progress)
+{
+ WRITE_ZONE();
+ return createSingleLayeredMeshInternal(DYNAMIC_CAST(RenderMeshAssetAuthoringIntl*)(asset), subdivisionSize, mergeVertices, closeHoles, progress);
+}
+
+
+
+void ModuleClothingImpl::destroy()
+{
+ mClothingSceneList.clear();
+
+ if (mApexClothingActorParams != NULL)
+ {
+ mApexClothingActorParams->destroy();
+ mApexClothingActorParams = NULL;
+ }
+
+ if (mApexClothingPreviewParams != NULL)
+ {
+ mApexClothingPreviewParams->destroy();
+ mApexClothingPreviewParams = NULL;
+ }
+
+#if APEX_CUDA_SUPPORT
+ for (PxU32 i = 0; i < mGpuFactories.size(); i++)
+ {
+ //APEX_DEBUG_INFO("Release Gpu factory %d", i);
+ PX_DELETE(mGpuFactories[i].factoryGpu);
+ mGpuFactories.replaceWithLast(i);
+ }
+#endif
+ PX_DELETE(mCpuFactory);
+ mCpuFactory = NULL;
+
+#ifndef WITHOUT_PVD
+ destroyPvdInstances();
+#endif
+ if (mModuleParams != NULL)
+ {
+ mModuleParams->destroy();
+ mModuleParams = NULL;
+ }
+
+ if (mDummyActor != NULL)
+ {
+ mDummyActor->release();
+ mDummyActor = NULL;
+ }
+
+ if (mDummyAsset != NULL)
+ {
+ mDummyAsset->release();
+ mDummyAsset = NULL;
+ }
+
+ NvParameterized::Traits* traits = mSdk->getParameterizedTraits();
+
+ ModuleBase::destroy();
+
+ mAssetAuthorableObjectFactories.clear(); // needs to be done before destructor!
+
+#if APEX_CUDA_SUPPORT
+ if (mGpuDllHandle != NULL)
+ {
+ FreeLibrary((HMODULE)mGpuDllHandle);
+ }
+#endif
+
+ if (traits)
+ {
+ ModuleClothingRegistration::invokeUnregistration(traits);
+ }
+ PX_DELETE(this);
+}
+
+
+
+ModuleSceneIntl* ModuleClothingImpl::createInternalModuleScene(SceneIntl& scene, RenderDebugInterface* renderDebug)
+{
+ return PX_NEW(ClothingScene)(*this, scene, renderDebug, mClothingSceneList);
+}
+
+
+
+void ModuleClothingImpl::releaseModuleSceneIntl(ModuleSceneIntl& scene)
+{
+ ClothingScene* clothingScene = DYNAMIC_CAST(ClothingScene*)(&scene);
+ clothingScene->destroy();
+}
+
+
+
+uint32_t ModuleClothingImpl::forceLoadAssets()
+{
+ uint32_t loadedAssetCount = 0;
+ for (uint32_t i = 0; i < mAssetAuthorableObjectFactories.getSize(); i++)
+ {
+ AuthorableObjectIntl* ao = static_cast<AuthorableObjectIntl*>(mAssetAuthorableObjectFactories.getResource(i));
+ loadedAssetCount += ao->forceLoadAssets();
+ }
+ return loadedAssetCount;
+}
+
+
+
+#ifndef WITHOUT_PVD
+void ModuleClothingImpl::initPvdClasses(pvdsdk::PvdDataStream& pvdStream)
+{
+ NamespacedName objRef = getPvdNamespacedNameForType<ObjectRef>();
+
+ // ---------------------------------------
+ // Hierarchy
+
+ // ModuleBase holds ClothingAssets
+ pvdStream.createClass(NamespacedName(APEX_PVD_NAMESPACE, "ClothingAsset"));
+ pvdStream.createProperty(NamespacedName(APEX_PVD_NAMESPACE, getName()), "ClothingAssets", "children", objRef, PropertyType::Array);
+
+ // ClothingAsset holds ClothingActors
+ pvdStream.createClass(NamespacedName(APEX_PVD_NAMESPACE, "ClothingActor"));
+ pvdStream.createProperty(NamespacedName(APEX_PVD_NAMESPACE, "ClothingAsset"), "ClothingActors", "children", objRef, PropertyType::Array);
+
+
+ // ---------------------------------------
+ // NvParameterized
+ pvdsdk::ApexPvdClient* client = GetInternalApexSDK()->getApexPvdClient();
+ PX_ASSERT(client != NULL);
+
+ // ModuleBase Params
+ INIT_PVD_CLASSES_PARAMETERIZED(ClothingModuleParameters);
+ pvdStream.createProperty(NamespacedName(APEX_PVD_NAMESPACE, getName()), "ModuleParams", "", objRef, PropertyType::Scalar);
+
+ // Asset Params
+
+ INIT_PVD_CLASSES_PARAMETERIZED(ClothingPhysicalMeshParameters);
+ INIT_PVD_CLASSES_PARAMETERIZED(ClothingGraphicalLodParameters);
+ INIT_PVD_CLASSES_PARAMETERIZED(ClothingCookedParam);
+ INIT_PVD_CLASSES_PARAMETERIZED(ClothingCookedPhysX3Param);
+ INIT_PVD_CLASSES_PARAMETERIZED(ClothingMaterialLibraryParameters);
+ INIT_PVD_CLASSES_PARAMETERIZED(ClothingAssetParameters);
+ pvdStream.createProperty(NamespacedName(APEX_PVD_NAMESPACE, "ClothingAsset"), "AssetParams", "", objRef, PropertyType::Scalar);
+
+ // Actor Params
+ INIT_PVD_CLASSES_PARAMETERIZED(ClothingActorParam);
+ pvdStream.createProperty(NamespacedName(APEX_PVD_NAMESPACE, "ClothingActor"), "ActorParams", "", objRef, PropertyType::Scalar);
+
+
+ // ---------------------------------------
+ // Additional Properties
+
+ // ---------------------------------------
+}
+
+
+
+void ModuleClothingImpl::initPvdInstances(pvdsdk::PvdDataStream& pvdStream)
+{
+ // if there's more than one AOFactory we don't know any more for sure that its a clothing asset factory, so we have to adapt the code below
+ PX_ASSERT(mAssetAuthorableObjectFactories.getSize() == 1 && "Adapt the code below");
+
+ pvdsdk::ApexPvdClient* client = GetInternalApexSDK()->getApexPvdClient();
+ PX_ASSERT(client != NULL);
+
+ // ModuleBase Params
+ pvdStream.createInstance(NamespacedName(APEX_PVD_NAMESPACE, "ClothingModuleParameters"), mModuleParams);
+ pvdStream.setPropertyValue(mApiProxy, "ModuleParams", DataRef<const uint8_t>((const uint8_t*)&mModuleParams, sizeof(ClothingModuleParameters*)), getPvdNamespacedNameForType<ObjectRef>());
+ // update module properties (should we do this per frame? if so, how?)
+ client->updatePvd(mModuleParams, *mModuleParams);
+
+ // prepare asset list and forward init calls
+ AuthorableObjectIntl* ao = static_cast<AuthorableObjectIntl*>(mAssetAuthorableObjectFactories.getResource(0));
+ ao->mAssets.initPvdInstances(pvdStream);
+}
+
+
+
+void ModuleClothingImpl::destroyPvdInstances()
+{
+ pvdsdk::ApexPvdClient* client = GetInternalApexSDK()->getApexPvdClient();
+ if (client != NULL)
+ {
+ if (client->isConnected() && client->getPxPvd().getInstrumentationFlags() & PxPvdInstrumentationFlag::eDEBUG)
+ {
+ pvdsdk::PvdDataStream* pvdStream = client->getDataStream();
+ {
+ if (pvdStream != NULL)
+ {
+ client->updatePvd(mModuleParams, *mModuleParams, pvdsdk::PvdAction::DESTROY);
+ pvdStream->destroyInstance(mModuleParams);
+ }
+ }
+ }
+ }
+}
+#endif
+
+
+ClothingScene* ModuleClothingImpl::getClothingScene(const Scene& apexScene)
+{
+ const SceneIntl* niScene = DYNAMIC_CAST(const SceneIntl*)(&apexScene);
+ for (uint32_t i = 0 ; i < mClothingSceneList.getSize() ; i++)
+ {
+ ClothingScene* clothingScene = DYNAMIC_CAST(ClothingScene*)(mClothingSceneList.getResource(i));
+ if (clothingScene->mApexScene == niScene)
+ {
+ return clothingScene;
+ }
+ }
+
+ PX_ASSERT(!"Unable to locate an appropriate ClothingScene");
+ return NULL;
+}
+
+
+
+ClothingPhysicalMeshImpl* ModuleClothingImpl::createPhysicalMeshInternal(ClothingPhysicalMeshParameters* mesh)
+{
+ ClothingPhysicalMeshImpl* result = PX_NEW(ClothingPhysicalMeshImpl)(this, mesh, &mPhysicalMeshes);
+ return result;
+}
+
+
+
+void ModuleClothingImpl::releasePhysicalMesh(ClothingPhysicalMeshImpl* physicalMesh)
+{
+ physicalMesh->destroy();
+}
+
+
+
+void ModuleClothingImpl::unregisterAssetWithScenes(ClothingAssetImpl* asset)
+{
+ for (uint32_t i = 0; i < mClothingSceneList.getSize(); i++)
+ {
+ ClothingScene* clothingScene = static_cast<ClothingScene*>(mClothingSceneList.getResource(i));
+ clothingScene->unregisterAsset(asset);
+ }
+}
+
+
+void ModuleClothingImpl::notifyReleaseGraphicalData(ClothingAssetImpl* asset)
+{
+ for (uint32_t i = 0; i < mClothingSceneList.getSize(); i++)
+ {
+ ClothingScene* clothingScene = static_cast<ClothingScene*>(mClothingSceneList.getResource(i));
+ clothingScene->removeRenderProxies(asset);
+ }
+}
+
+
+Actor* ModuleClothingImpl::getDummyActor()
+{
+ mDummyProtector.lock();
+ if (mDummyActor == NULL)
+ {
+ PX_ASSERT(mDummyAsset == NULL);
+ mDummyAsset = PX_NEW(DummyAsset)(getModuleID());
+ mDummyActor = PX_NEW(DummyActor)(mDummyAsset);
+ }
+ mDummyProtector.unlock();
+
+ return mDummyActor;
+}
+
+
+
+void ModuleClothingImpl::registerBackendFactory(BackendFactory* factory)
+{
+ for (uint32_t i = 0; i < mBackendFactories.size(); i++)
+ {
+ if (::strcmp(mBackendFactories[i]->getName(), factory->getName()) == 0)
+ {
+ return;
+ }
+ }
+
+ mBackendFactories.pushBack(factory);
+}
+
+
+
+void ModuleClothingImpl::unregisterBackendFactory(BackendFactory* factory)
+{
+ uint32_t read = 0, write = 0;
+
+ while (read < mBackendFactories.size())
+ {
+ mBackendFactories[write] = mBackendFactories[read];
+
+ if (mBackendFactories[read] == factory)
+ {
+ read++;
+ }
+ else
+ {
+ read++, write++;
+ }
+ }
+
+ while (read < write)
+ {
+ mBackendFactories.popBack();
+ }
+}
+
+
+
+BackendFactory* ModuleClothingImpl::getBackendFactory(const char* simulationBackend)
+{
+ PX_ASSERT(simulationBackend != NULL);
+
+ for (uint32_t i = 0; i < mBackendFactories.size(); i++)
+ {
+ if (mBackendFactories[i]->isMatch(simulationBackend))
+ {
+ return mBackendFactories[i];
+ }
+ }
+
+ //APEX_INVALID_OPERATION("Simulation back end \'%s\' not found, using \'PhysX\' instead\n", simulationBackend);
+
+ PX_ASSERT(mBackendFactories.size() >= 1);
+ return mBackendFactories[0];
+}
+
+
+
+ClothFactory ModuleClothingImpl::createClothFactory(PxCudaContextManager* contextManager)
+{
+ nvidia::Mutex::ScopedLock lock(mFactoryMutex);
+
+#if APEX_CUDA_SUPPORT
+
+ if (contextManager != NULL && contextManager->supportsArchSM20())
+ {
+ for (uint32_t i = 0; i < mGpuFactories.size(); i++)
+ {
+ if (mGpuFactories[i].contextManager == contextManager)
+ {
+ mGpuFactories[i].referenceCount++;
+ //APEX_DEBUG_INFO("Found Gpu factory %d (ref = %d)", i, mGpuFactories[i].referenceCount);
+ return ClothFactory(mGpuFactories[i].factoryGpu, &mFactoryMutex);
+ }
+ }
+
+ // nothing found
+ if (mPxCreateCuFactoryFunc != NULL)
+ {
+ GpuFactoryEntry entry(mPxCreateCuFactoryFunc(contextManager), contextManager);
+ if (entry.factoryGpu != NULL)
+ {
+ //APEX_DEBUG_INFO("Create Gpu factory %d", mGpuFactories.size());
+ entry.referenceCount = 1;
+ mGpuFactories.pushBack(entry);
+ return ClothFactory(entry.factoryGpu, &mFactoryMutex);
+ }
+ }
+
+ return ClothFactory(NULL, &mFactoryMutex);
+ }
+ else
+#else
+ PX_UNUSED(contextManager);
+#endif
+ {
+ if (mCpuFactory == NULL)
+ {
+ mCpuFactory = cloth::Factory::createFactory(cloth::Factory::CPU);
+ //APEX_DEBUG_INFO("Create Cpu factory");
+ PX_ASSERT(mCpuFactoryReferenceCount == 0);
+ }
+
+ mCpuFactoryReferenceCount++;
+ //APEX_DEBUG_INFO("Get Cpu factory (ref = %d)", mCpuFactoryReferenceCount);
+
+ return ClothFactory(mCpuFactory, &mFactoryMutex);
+ }
+}
+
+
+
+void ModuleClothingImpl::releaseClothFactory(PxCudaContextManager* contextManager)
+{
+ nvidia::Mutex::ScopedLock lock(mFactoryMutex);
+
+#if APEX_CUDA_SUPPORT
+ if (contextManager != NULL)
+ {
+ for (uint32_t i = 0; i < mGpuFactories.size(); i++)
+ {
+ if (mGpuFactories[i].contextManager == contextManager)
+ {
+ PX_ASSERT(mGpuFactories[i].referenceCount > 0);
+ mGpuFactories[i].referenceCount--;
+ //APEX_DEBUG_INFO("Found Gpu factory %d (ref = %d)", i, mGpuFactories[i].referenceCount);
+
+ if (mGpuFactories[i].referenceCount == 0)
+ {
+ //APEX_DEBUG_INFO("Release Gpu factory %d", i);
+ PX_DELETE(mGpuFactories[i].factoryGpu);
+ mGpuFactories.replaceWithLast(i);
+ }
+ }
+ }
+ }
+ else
+#else
+ PX_UNUSED(contextManager);
+#endif
+ {
+ PX_ASSERT(mCpuFactoryReferenceCount > 0);
+
+ mCpuFactoryReferenceCount--;
+ //APEX_DEBUG_INFO("Release Cpu factory (ref = %d)", mCpuFactoryReferenceCount);
+
+ if (mCpuFactoryReferenceCount == 0)
+ {
+ PX_DELETE(mCpuFactory);
+ mCpuFactory = NULL;
+ }
+ }
+}
+
+
+
+ClothingPhysicalMesh* ModuleClothingImpl::createSingleLayeredMeshInternal(RenderMeshAssetAuthoringIntl* renderMeshAsset, uint32_t subdivisionSize,
+ bool mergeVertices, bool closeHoles, IProgressListener* progressListener)
+{
+ if (renderMeshAsset->getPartCount() > 1)
+ {
+ APEX_INVALID_PARAMETER("RenderMeshAssetAuthoring has more than one part (%d)", renderMeshAsset->getPartCount());
+ return NULL;
+ }
+
+ if (subdivisionSize > 200)
+ {
+ APEX_INVALID_PARAMETER("subdivisionSize must be smaller or equal to 200 and has been clamped (was %d).", subdivisionSize);
+ subdivisionSize = 200;
+ }
+
+ HierarchicalProgressListener progress(100, progressListener);
+
+
+ uint32_t numGraphicalVertices = 0;
+
+ for (uint32_t i = 0; i < renderMeshAsset->getSubmeshCount(); i++)
+ {
+ const RenderSubmeshIntl& submesh = renderMeshAsset->getInternalSubmesh(i);
+ numGraphicalVertices += submesh.getVertexBuffer().getVertexCount();
+ }
+
+ ClothingPhysicalMeshImpl* physicalMesh = DYNAMIC_CAST(ClothingPhysicalMeshImpl*)(createEmptyPhysicalMesh());
+
+ // set time for registration, merge, close and subdivision
+ uint32_t times[4] = { 20, (uint32_t)(mergeVertices ? 20 : 0), (uint32_t)(closeHoles ? 30 : 0), (uint32_t)(subdivisionSize > 0 ? 30 : 0) };
+ uint32_t sum = times[0] + times[1] + times[2] + times[3];
+ for (uint32_t i = 0; i < 4; i++)
+ {
+ times[i] = 100 * times[i] / sum;
+ }
+
+ progress.setSubtaskWork((int32_t)times[0], "Creating single layered mesh");
+ ApexSubdivider subdivider;
+
+ Array<int32_t> old2New(numGraphicalVertices, -1);
+ uint32_t nbVertices = 0;
+
+ uint32_t vertexOffset = 0;
+
+ for (uint32_t submeshNr = 0; submeshNr < renderMeshAsset->getSubmeshCount(); submeshNr++)
+ {
+ const RenderSubmeshIntl& submesh = renderMeshAsset->getInternalSubmesh(submeshNr);
+
+ // used for physics?
+ const VertexFormat& vf = submesh.getVertexBuffer().getFormat();
+ uint32_t customIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID("USED_FOR_PHYSICS"));
+ RenderDataFormat::Enum outFormat = vf.getBufferFormat(customIndex);
+ const uint8_t* usedForPhysics = NULL;
+ if (outFormat == RenderDataFormat::UBYTE1)
+ {
+ usedForPhysics = (const uint8_t*)submesh.getVertexBuffer().getBuffer(customIndex);
+ }
+
+ customIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID("LATCH_TO_NEAREST_SLAVE"));
+ outFormat = vf.getBufferFormat(customIndex);
+ const uint32_t* latchToNearestSlave = outFormat != RenderDataFormat::UINT1 ? NULL : (uint32_t*)submesh.getVertexBuffer().getBuffer(customIndex);
+
+ customIndex = (uint32_t)vf.getBufferIndexFromID(vf.getID("LATCH_TO_NEAREST_MASTER"));
+ outFormat = vf.getBufferFormat(customIndex);
+ const uint32_t* latchToNearestMaster = outFormat != RenderDataFormat::UINT1 ? NULL : (uint32_t*)submesh.getVertexBuffer().getBuffer(customIndex);
+ PX_ASSERT((latchToNearestSlave != NULL) == (latchToNearestMaster != NULL)); // both NULL or not NULL
+
+ // triangles
+ const uint32_t* indices = submesh.getIndexBuffer(0); // only 1 part supported!
+
+ // vertices
+ RenderDataFormat::Enum format;
+ uint32_t bufferIndex = (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::POSITION));
+ const PxVec3* positions = (const PxVec3*)submesh.getVertexBuffer().getBufferAndFormat(format, bufferIndex);
+ if (format != RenderDataFormat::FLOAT3)
+ {
+ PX_ALWAYS_ASSERT();
+ positions = NULL;
+ }
+
+ const uint32_t submeshIndices = submesh.getIndexCount(0);
+ for (uint32_t meshIndex = 0; meshIndex < submeshIndices; meshIndex += 3)
+ {
+ if (latchToNearestSlave != NULL)
+ {
+ uint32_t numVerticesOk = 0;
+ for (uint32_t i = 0; i < 3; i++)
+ {
+ const uint32_t index = indices[meshIndex + i];
+ numVerticesOk += latchToNearestSlave[index] == 0 ? 1u : 0u;
+ }
+ if (numVerticesOk < 3)
+ {
+ continue; // skip this triangle
+ }
+ }
+ else if (usedForPhysics != NULL)
+ {
+ uint32_t numVerticesOk = 0;
+ for (uint32_t i = 0; i < 3; i++)
+ {
+ const uint32_t index = indices[meshIndex + i];
+ numVerticesOk += usedForPhysics[index] == 0 ? 0u : 1u;
+ }
+ if (numVerticesOk < 3)
+ {
+ continue; // skip this triangle
+ }
+ }
+
+ // add triangle to subdivider
+ for (uint32_t i = 0; i < 3; i++)
+ {
+ const uint32_t localIndex = indices[meshIndex + i];
+ const uint32_t index = localIndex + vertexOffset;
+ if (old2New[index] == -1)
+ {
+ old2New[index] = (int32_t)nbVertices++;
+ uint32_t master = latchToNearestMaster != NULL ? latchToNearestMaster[localIndex] : 0xffffffffu;
+ subdivider.registerVertex(positions[localIndex], master);
+ }
+ }
+
+ const uint32_t i0 = (uint32_t)old2New[indices[meshIndex + 0] + vertexOffset];
+ const uint32_t i1 = (uint32_t)old2New[indices[meshIndex + 1] + vertexOffset];
+ const uint32_t i2 = (uint32_t)old2New[indices[meshIndex + 2] + vertexOffset];
+ subdivider.registerTriangle(i0, i1, i2);
+ }
+ vertexOffset += submesh.getVertexBuffer().getVertexCount();
+ }
+
+ subdivider.endRegistration();
+ progress.completeSubtask();
+
+ if (nbVertices == 0)
+ {
+ APEX_INVALID_PARAMETER("Mesh has no active vertices (see Physics on/off channel)");
+ return NULL;
+ }
+
+ // use subdivider
+ if (mergeVertices)
+ {
+ progress.setSubtaskWork((int32_t)times[1], "Merging");
+ subdivider.mergeVertices(&progress);
+ progress.completeSubtask();
+ }
+
+ if (closeHoles)
+ {
+ progress.setSubtaskWork((int32_t)times[2], "Closing holes");
+ subdivider.closeMesh(&progress);
+ progress.completeSubtask();
+ }
+
+ if (subdivisionSize > 0)
+ {
+ progress.setSubtaskWork((int32_t)times[3], "Subdividing");
+ subdivider.subdivide(subdivisionSize, &progress);
+ progress.completeSubtask();
+ }
+
+ Array<PxVec3> newVertices(subdivider.getNumVertices());
+ Array<uint32_t> newMasterValues(subdivider.getNumVertices());
+ for (uint32_t i = 0; i < newVertices.size(); i++)
+ {
+ subdivider.getVertex(i, newVertices[i], newMasterValues[i]);
+ }
+
+ Array<uint32_t> newIndices(subdivider.getNumTriangles() * 3);
+ for (uint32_t i = 0; i < newIndices.size(); i += 3)
+ {
+ subdivider.getTriangle(i / 3, newIndices[i], newIndices[i + 1], newIndices[i + 2]);
+ }
+
+ physicalMesh->setGeometry(false, newVertices.size(), sizeof(PxVec3), newVertices.begin(),
+ newMasterValues.begin(), newIndices.size(), sizeof(uint32_t), &newIndices[0]);
+
+ return physicalMesh;
+}
+
+
+bool ModuleClothingImpl::ClothingBackendFactory::isMatch(const char* simulationBackend)
+{
+ if (::strcmp(getName(), simulationBackend) == 0)
+ {
+ return true;
+ }
+
+ if (::strcmp(ClothingCookedPhysX3Param::staticClassName(), simulationBackend) == 0
+ || ::strcmp(ClothingCookedParam::staticClassName(), simulationBackend) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+const char* ModuleClothingImpl::ClothingBackendFactory::getName()
+{
+ return "Embedded";
+}
+
+uint32_t ModuleClothingImpl::ClothingBackendFactory::getCookingVersion()
+{
+ return Cooking::getCookingVersion();
+}
+
+uint32_t ModuleClothingImpl::ClothingBackendFactory::getCookedDataVersion(const NvParameterized::Interface* cookedData)
+{
+ if (cookedData != NULL && isMatch(cookedData->className()))
+ {
+ if (::strcmp(ClothingCookedParam::staticClassName(), cookedData->className()) == 0)
+ {
+ return static_cast<const ClothingCookedParam*>(cookedData)->cookedDataVersion;
+ }
+ else if (::strcmp(ClothingCookedPhysX3Param::staticClassName(), cookedData->className()) == 0)
+ {
+ return static_cast<const ClothingCookedPhysX3Param*>(cookedData)->cookedDataVersion;
+ }
+ else
+ {
+ PX_ALWAYS_ASSERT_MESSAGE("Mechanism to extract cooked data version is not defined and not implemented");
+ }
+ }
+
+ return 0;
+}
+
+CookingAbstract* ModuleClothingImpl::ClothingBackendFactory::createCookingJob()
+{
+ bool withFibers = true;
+ return PX_NEW(Cooking)(withFibers);
+}
+
+void ModuleClothingImpl::ClothingBackendFactory::releaseCookedInstances(NvParameterized::Interface* cookedData)
+{
+ Simulation::releaseFabric(cookedData);
+}
+
+SimulationAbstract* ModuleClothingImpl::ClothingBackendFactory::createSimulation(ClothingScene* clothingScene, bool useHW)
+{
+ return PX_NEW(Simulation)(clothingScene, useHW);
+}
+
+}
+} // namespace nvidia
diff --git a/APEX_1.4/module/clothing/src/SimulationAbstract.cpp b/APEX_1.4/module/clothing/src/SimulationAbstract.cpp
new file mode 100644
index 00000000..22351f3a
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/SimulationAbstract.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, 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.
+ */
+
+
+#include "ApexDefs.h"
+
+#include "SimulationAbstract.h"
+
+// for NUM_VERTICES_PER_CACHE_BLOCK
+#include "ClothingAssetImpl.h"
+
+
+namespace nvidia
+{
+namespace clothing
+{
+
+void SimulationAbstract::init(uint32_t numVertices, uint32_t numIndices, bool writebackNormals)
+{
+ sdkNumDeformableVertices = numVertices;
+ sdkNumDeformableIndices = numIndices;
+
+ const uint32_t alignedNumVertices = (numVertices + 15) & 0xfffffff0;
+ const uint32_t writeBackDataSize = (sizeof(PxVec3) * alignedNumVertices) * (writebackNormals ? 2 : 1);
+
+ PX_ASSERT(sdkWritebackPosition == NULL);
+ PX_ASSERT(sdkWritebackNormal == NULL);
+ sdkWritebackPosition = (PxVec3*)PX_ALLOC(writeBackDataSize, PX_DEBUG_EXP("SimulationAbstract::writebackData"));
+ sdkWritebackNormal = writebackNormals ? sdkWritebackPosition + alignedNumVertices : NULL;
+
+ const uint32_t allocNumVertices = (((numVertices + NUM_VERTICES_PER_CACHE_BLOCK - 1) / NUM_VERTICES_PER_CACHE_BLOCK)) * NUM_VERTICES_PER_CACHE_BLOCK;
+ PX_ASSERT(skinnedPhysicsPositions == NULL);
+ PX_ASSERT(skinnedPhysicsNormals == NULL);
+ skinnedPhysicsPositions = (PxVec3*)PX_ALLOC(sizeof(PxVec3) * allocNumVertices * 2, PX_DEBUG_EXP("SimulationAbstract::skinnedPhysicsPositions"));
+ skinnedPhysicsNormals = skinnedPhysicsPositions + allocNumVertices;
+}
+
+
+
+void SimulationAbstract::initSimulation(const tSimParams& s)
+{
+ simulation = s;
+}
+
+
+}
+} // namespace nvidia
+
diff --git a/APEX_1.4/module/clothing/src/autogen/ClothingActorParam.cpp b/APEX_1.4/module/clothing/src/autogen/ClothingActorParam.cpp
new file mode 100644
index 00000000..291289e7
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/autogen/ClothingActorParam.cpp
@@ -0,0 +1,2394 @@
+// 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-2015 NVIDIA Corporation. All rights reserved.
+
+// This file was generated by NvParameterized/scripts/GenParameterized.pl
+
+
+#include "ClothingActorParam.h"
+#include <string.h>
+#include <stdlib.h>
+
+using namespace NvParameterized;
+
+namespace nvidia
+{
+namespace clothing
+{
+
+using namespace ClothingActorParamNS;
+
+const char* const ClothingActorParamFactory::vptr =
+ NvParameterized::getVptr<ClothingActorParam, ClothingActorParam::ClassAlignment>();
+
+const uint32_t NumParamDefs = 76;
+static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs];
+
+
+static const size_t ParamLookupChildrenTable[] =
+{
+ 1, 2, 3, 11, 12, 13, 14, 15, 16, 17, 18, 21, 24, 25, 27, 38, 54, 57, 58, 59, 61,
+ 63, 65, 66, 67, 68, 69, 70, 72, 73, 74, 75, 4, 5, 6, 7, 8, 9, 10, 19, 20, 22, 23,
+ 26, 28, 29, 30, 35, 36, 37, 31, 32, 33, 34, 39, 45, 46, 51, 52, 53, 40, 41, 42, 43,
+ 44, 47, 48, 49, 50, 55, 56, 60, 62, 64, 71,
+};
+
+#define TENUM(type) nvidia::##type
+#define CHILDREN(index) &ParamLookupChildrenTable[index]
+static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] =
+{
+ { TYPE_STRUCT, false, 0, CHILDREN(0), 32 },
+ { TYPE_MAT44, false, (size_t)(&((ParametersStruct*)0)->globalPose), NULL, 0 }, // globalPose
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->useHardwareCloth), NULL, 0 }, // useHardwareCloth
+ { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->flags), CHILDREN(32), 7 }, // flags
+ { TYPE_BOOL, false, (size_t)(&((ClothingActorFlags_Type*)0)->ParallelCpuSkinning), NULL, 0 }, // flags.ParallelCpuSkinning
+ { TYPE_BOOL, false, (size_t)(&((ClothingActorFlags_Type*)0)->RecomputeNormals), NULL, 0 }, // flags.RecomputeNormals
+ { TYPE_BOOL, false, (size_t)(&((ClothingActorFlags_Type*)0)->RecomputeTangents), NULL, 0 }, // flags.RecomputeTangents
+ { TYPE_BOOL, false, (size_t)(&((ClothingActorFlags_Type*)0)->Visualize), NULL, 0 }, // flags.Visualize
+ { TYPE_BOOL, false, (size_t)(&((ClothingActorFlags_Type*)0)->CorrectSimulationNormals), NULL, 0 }, // flags.CorrectSimulationNormals
+ { TYPE_BOOL, false, (size_t)(&((ClothingActorFlags_Type*)0)->ComputeRenderData), NULL, 0 }, // flags.ComputeRenderData
+ { TYPE_BOOL, false, (size_t)(&((ClothingActorFlags_Type*)0)->ComputePhysicsMeshNormals), NULL, 0 }, // flags.ComputePhysicsMeshNormals
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->fallbackSkinning), NULL, 0 }, // fallbackSkinning
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->slowStart), NULL, 0 }, // slowStart
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->useInternalBoneOrder), NULL, 0 }, // useInternalBoneOrder
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->updateStateWithGlobalMatrices), NULL, 0 }, // updateStateWithGlobalMatrices
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->uvChannelForTangentUpdate), NULL, 0 }, // uvChannelForTangentUpdate
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->maxDistanceBlendTime), NULL, 0 }, // maxDistanceBlendTime
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->clothingMaterialIndex), NULL, 0 }, // clothingMaterialIndex
+ { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->windParams), CHILDREN(39), 2 }, // windParams
+ { TYPE_VEC3, false, (size_t)(&((WindParameters_Type*)0)->Velocity), NULL, 0 }, // windParams.Velocity
+ { TYPE_F32, false, (size_t)(&((WindParameters_Type*)0)->Adaption), NULL, 0 }, // windParams.Adaption
+ { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->maxDistanceScale), CHILDREN(41), 2 }, // maxDistanceScale
+ { TYPE_F32, false, (size_t)(&((MaxDistanceScale_Type*)0)->Scale), NULL, 0 }, // maxDistanceScale.Scale
+ { TYPE_BOOL, false, (size_t)(&((MaxDistanceScale_Type*)0)->Multipliable), NULL, 0 }, // maxDistanceScale.Multipliable
+ { TYPE_U64, false, (size_t)(&((ParametersStruct*)0)->userData), NULL, 0 }, // userData
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->boneMatrices), CHILDREN(43), 1 }, // boneMatrices
+ { TYPE_MAT44, false, 1 * sizeof(physx::PxMat44), NULL, 0 }, // boneMatrices[]
+ { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->clothDescTemplate), CHILDREN(44), 6 }, // clothDescTemplate
+ { TYPE_F32, false, (size_t)(&((ClothDescTemplate_Type*)0)->collisionResponseCoefficient), NULL, 0 }, // clothDescTemplate.collisionResponseCoefficient
+ { TYPE_U16, false, (size_t)(&((ClothDescTemplate_Type*)0)->collisionGroup), NULL, 0 }, // clothDescTemplate.collisionGroup
+ { TYPE_STRUCT, false, (size_t)(&((ClothDescTemplate_Type*)0)->groupsMask), CHILDREN(50), 4 }, // clothDescTemplate.groupsMask
+ { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits0), NULL, 0 }, // clothDescTemplate.groupsMask.bits0
+ { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits1), NULL, 0 }, // clothDescTemplate.groupsMask.bits1
+ { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits2), NULL, 0 }, // clothDescTemplate.groupsMask.bits2
+ { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits3), NULL, 0 }, // clothDescTemplate.groupsMask.bits3
+ { TYPE_BOUNDS3, false, (size_t)(&((ClothDescTemplate_Type*)0)->validBounds), NULL, 0 }, // clothDescTemplate.validBounds
+ { TYPE_U64, false, (size_t)(&((ClothDescTemplate_Type*)0)->compartment), NULL, 0 }, // clothDescTemplate.compartment
+ { TYPE_U64, false, (size_t)(&((ClothDescTemplate_Type*)0)->userData), NULL, 0 }, // clothDescTemplate.userData
+ { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->shapeDescTemplate), CHILDREN(54), 6 }, // shapeDescTemplate
+ { TYPE_STRUCT, false, (size_t)(&((ShapeDescTemplate_Type*)0)->flags), CHILDREN(60), 5 }, // shapeDescTemplate.flags
+ { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_VISUALIZATION), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_VISUALIZATION
+ { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_DISABLE_COLLISION), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_DISABLE_COLLISION
+ { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_DISABLE_RAYCASTING), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_DISABLE_RAYCASTING
+ { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_DYNAMIC_DYNAMIC_CCD), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_DYNAMIC_DYNAMIC_CCD
+ { TYPE_BOOL, false, (size_t)(&((ShapeDescFlags_Type*)0)->NX_SF_DISABLE_SCENE_QUERIES), NULL, 0 }, // shapeDescTemplate.flags.NX_SF_DISABLE_SCENE_QUERIES
+ { TYPE_U16, false, (size_t)(&((ShapeDescTemplate_Type*)0)->collisionGroup), NULL, 0 }, // shapeDescTemplate.collisionGroup
+ { TYPE_STRUCT, false, (size_t)(&((ShapeDescTemplate_Type*)0)->groupsMask), CHILDREN(65), 4 }, // shapeDescTemplate.groupsMask
+ { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits0), NULL, 0 }, // shapeDescTemplate.groupsMask.bits0
+ { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits1), NULL, 0 }, // shapeDescTemplate.groupsMask.bits1
+ { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits2), NULL, 0 }, // shapeDescTemplate.groupsMask.bits2
+ { TYPE_U32, false, (size_t)(&((GroupsMask_Type*)0)->bits3), NULL, 0 }, // shapeDescTemplate.groupsMask.bits3
+ { TYPE_U16, false, (size_t)(&((ShapeDescTemplate_Type*)0)->materialIndex), NULL, 0 }, // shapeDescTemplate.materialIndex
+ { TYPE_U64, false, (size_t)(&((ShapeDescTemplate_Type*)0)->userData), NULL, 0 }, // shapeDescTemplate.userData
+ { TYPE_U64, false, (size_t)(&((ShapeDescTemplate_Type*)0)->name), NULL, 0 }, // shapeDescTemplate.name
+ { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->actorDescTemplate), CHILDREN(69), 2 }, // actorDescTemplate
+ { TYPE_U64, false, (size_t)(&((ActorDescTemplate_Type*)0)->userData), NULL, 0 }, // actorDescTemplate.userData
+ { TYPE_U64, false, (size_t)(&((ActorDescTemplate_Type*)0)->name), NULL, 0 }, // actorDescTemplate.name
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->actorScale), NULL, 0 }, // actorScale
+ { TYPE_REF, false, (size_t)(&((ParametersStruct*)0)->runtimeCooked), NULL, 0 }, // runtimeCooked
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->morphDisplacements), CHILDREN(71), 1 }, // morphDisplacements
+ { TYPE_VEC3, false, 1 * sizeof(physx::PxVec3), NULL, 0 }, // morphDisplacements[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->morphPhysicalMeshNewPositions), CHILDREN(72), 1 }, // morphPhysicalMeshNewPositions
+ { TYPE_VEC3, false, 1 * sizeof(physx::PxVec3), NULL, 0 }, // morphPhysicalMeshNewPositions[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->morphGraphicalMeshNewPositions), CHILDREN(73), 1 }, // morphGraphicalMeshNewPositions
+ { TYPE_VEC3, false, 1 * sizeof(physx::PxVec3), NULL, 0 }, // morphGraphicalMeshNewPositions[]
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->allowAdaptiveTargetFrequency), NULL, 0 }, // allowAdaptiveTargetFrequency
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->useVelocityClamping), NULL, 0 }, // useVelocityClamping
+ { TYPE_BOUNDS3, false, (size_t)(&((ParametersStruct*)0)->vertexVelocityClamp), NULL, 0 }, // vertexVelocityClamp
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->pressure), NULL, 0 }, // pressure
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->multiplyGlobalPoseIntoBones), NULL, 0 }, // multiplyGlobalPoseIntoBones
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->overrideMaterialNames), CHILDREN(74), 1 }, // overrideMaterialNames
+ { TYPE_STRING, false, 1 * sizeof(NvParameterized::DummyStringStruct), NULL, 0 }, // overrideMaterialNames[]
+ { TYPE_ENUM, false, (size_t)(&((ParametersStruct*)0)->simulationBackend), NULL, 0 }, // simulationBackend
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->freezeByLOD), NULL, 0 }, // freezeByLOD
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->localSpaceSim), NULL, 0 }, // localSpaceSim
+ { TYPE_I32, false, (size_t)(&((ParametersStruct*)0)->teleportMode), NULL, 0 }, // teleportMode
+};
+
+
+bool ClothingActorParam::mBuiltFlag = false;
+NvParameterized::MutexType ClothingActorParam::mBuiltFlagMutex;
+
+ClothingActorParam::ClothingActorParam(NvParameterized::Traits* traits, void* buf, int32_t* refCount) :
+ NvParameters(traits, buf, refCount)
+{
+ //mParameterizedTraits->registerFactory(className(), &ClothingActorParamFactoryInst);
+
+ if (!buf) //Do not init data if it is inplace-deserialized
+ {
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+ initDefaults();
+ }
+}
+
+ClothingActorParam::~ClothingActorParam()
+{
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+}
+
+void ClothingActorParam::destroy()
+{
+ // We cache these fields here to avoid overwrite in destructor
+ bool doDeallocateSelf = mDoDeallocateSelf;
+ NvParameterized::Traits* traits = mParameterizedTraits;
+ int32_t* refCount = mRefCount;
+ void* buf = mBuffer;
+
+ this->~ClothingActorParam();
+
+ NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf);
+}
+
+const NvParameterized::DefinitionImpl* ClothingActorParam::getParameterDefinitionTree(void)
+{
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+const NvParameterized::DefinitionImpl* ClothingActorParam::getParameterDefinitionTree(void) const
+{
+ ClothingActorParam* tmpParam = const_cast<ClothingActorParam*>(this);
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ tmpParam->buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+NvParameterized::ErrorType ClothingActorParam::getParameterHandle(const char* long_name, Handle& handle) const
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+NvParameterized::ErrorType ClothingActorParam::getParameterHandle(const char* long_name, Handle& handle)
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+void ClothingActorParam::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const
+{
+ ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<ClothingActorParam::ParametersStruct*>(&parameters()), handle, offset);
+}
+
+
+/* Dynamic Handle Indices */
+/* [0] - overrideMaterialNames (not an array of structs) */
+
+void ClothingActorParam::freeParameterDefinitionTable(NvParameterized::Traits* traits)
+{
+ if (!traits)
+ {
+ return;
+ }
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ return;
+ }
+
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+
+ if (!mBuiltFlag)
+ {
+ return;
+ }
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ ParamDefTable[i].~DefinitionImpl();
+ }
+
+ traits->free(ParamDefTable);
+
+ mBuiltFlag = false;
+}
+
+#define PDEF_PTR(index) (&ParamDefTable[index])
+
+void ClothingActorParam::buildTree(void)
+{
+
+ uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs;
+ ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize));
+ memset(ParamDefTable, 0, allocSize);
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=0, longName=""
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0];
+ ParamDef->init("", TYPE_STRUCT, "STRUCT", true);
+
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=1, longName="globalPose"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1];
+ ParamDef->init("globalPose", TYPE_MAT44, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("shortDescription", "The pose where the clothing asset will be put into the scene", true);
+ ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=2, longName="useHardwareCloth"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2];
+ ParamDef->init("useHardwareCloth", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Turns on hardware acceleration for the cloth simulation", true);
+ ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=3, longName="flags"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3];
+ ParamDef->init("flags", TYPE_STRUCT, "ClothingActorFlags", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "A selection of flags, can be updated at runtime.", true);
+ ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=4, longName="flags.ParallelCpuSkinning"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4];
+ ParamDef->init("ParallelCpuSkinning", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "All graphical vertices without correspondence to physical vertices or\ntriangles are skinned normally. This flag specifies whether this happens\nduring Physics scene simulation, or after.\nNote: If this flag is set, an inconsistency can arise when calling\nNxClothingActor::updateRenderResource in between NxApexScene::simulate\nand NxApexScene::fetchResults. As a workaround, you should only call\nNxClothingActor::updateRenderResources _after_ NxApexScene::fetchResults\nhas terminated.\n", true);
+ HintTable[1].init("shortDescription", "Determines whether or not to perform CPU skinning in parallel", true);
+ ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=5, longName="flags.RecomputeNormals"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5];
+ ParamDef->init("RecomputeNormals", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "This usually leads to better looking results, but is more expensive to\ncompute. Default is off.\n", true);
+ HintTable[1].init("shortDescription", "Fully recomputes the normals on the final mesh.", true);
+ ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=6, longName="flags.RecomputeTangents"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6];
+ ParamDef->init("RecomputeTangents", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "RecomputeTangents can only be set to false if less than half of the graphics mesh vertices have an exact\nmatch in the physics mesh. Otherwise it's always on.\n", true);
+ HintTable[1].init("shortDescription", "Fully recomputes the tangents on the final mesh.", true);
+ ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=7, longName="flags.Visualize"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7];
+ ParamDef->init("Visualize", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Determines whether or not to display debug visualization for this clothing actor", true);
+ ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=8, longName="flags.CorrectSimulationNormals"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8];
+ ParamDef->init("CorrectSimulationNormals", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "The MaxDistance=0 vertices can have a perturbed simulation normal. This usually\nhappens only for meshes where the MaxDistance=0 vertices are somewhere in the\nmiddle separating a simulated and non-simulated region. The normal for those\nvertices will be computed only by the simulated triangles which can lead to\nwrong results.\nThis solution will use the normals from the original simulation mesh and skin\nthem with respect to the local pose.\n", true);
+ HintTable[1].init("shortDescription", "", true);
+ ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=9, longName="flags.ComputeRenderData"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9];
+ ParamDef->init("ComputeRenderData", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "If set to false no skinning is done for this actor. Disable if all skinning is done outside of APEX.", true);
+ ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=10, longName="flags.ComputePhysicsMeshNormals"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[10];
+ ParamDef->init("ComputePhysicsMeshNormals", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "If set to false the normals on the physics mesh are not computed. Disable skinning and normal calculation is done outside of APEX.", true);
+ ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=11, longName="fallbackSkinning"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[11];
+ ParamDef->init("fallbackSkinning", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Performs the regular boneweighted skinning on the CPU before giving the\ndata out through the rendering API.\n", true);
+ HintTable[1].init("shortDescription", "Performs skinning in software", true);
+ ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=12, longName="slowStart"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[12];
+ ParamDef->init("slowStart", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "The first time a NxClothingActor starts to be simulated is with full max\ndistance. This prevents starting with full max distance and instead blending\nin as it will do the second time.\n", true);
+ HintTable[1].init("shortDescription", "Prevents from having full max distance right from the start", true);
+ ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=13, longName="useInternalBoneOrder"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[13];
+ ParamDef->init("useInternalBoneOrder", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("longDescription", "If this is set to true the bone buffers in updateState and the actor\ndescriptor have to be given in the same order as the bones are stored\ninternally in the asset. This can be queried using\nNxClothingAsset::getNumUsedBones and NxClothingAsset::getBoneName or\nNxClothingAsset::getBoneMapping.\n\nIf this is set to false, the bone buffers can be provided in the order as\nthey are stored in the application. This is either the bone order at\nauthoring time, or NxClothingAsset::remapBoneIndex can be called for each\nbone to let APEX know about the current ordering in the game. Note that\nthis is only recommended if the application already uses physx::PxMat44\n(or something binary equivalent) and does not have to convert the matrices.\n", true);
+ HintTable[2].init("shortDescription", "Expect internally ordered bone arrays in updateState call.", true);
+ ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=14, longName="updateStateWithGlobalMatrices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[14];
+ ParamDef->init("updateStateWithGlobalMatrices", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Depending on what matrices are present, the state can be updated using\nglobal world or object space bone matrices or composite matrices. The\ncomposite matrix can be generated by multiplying the world or object space\nmatrix by the inverse bone bine pose.\n\nNote: If there are problems which might be caused by bind poses being\ndifferent in the ClothingAsset and in the game's animation system, changing\nthis to true (and thus providing global pose matrices) might fix the problem.\n", true);
+ HintTable[1].init("shortDescription", "Use world space matrices instead of composite (relative to bind pose) in NxClothingActor::updateState().", true);
+ ParamDefTable[14].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=15, longName="uvChannelForTangentUpdate"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[15];
+ ParamDef->init("uvChannelForTangentUpdate", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Tangent update is done based on one UV channel. This allows selection of what\nUV channel is being used.\n", true);
+ HintTable[1].init("shortDescription", "This UV channel is used for updating tangent space", true);
+ ParamDefTable[15].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=16, longName="maxDistanceBlendTime"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[16];
+ ParamDef->init("maxDistanceBlendTime", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Note: This also influences how quickly different physical LoDs can be switched", true);
+ HintTable[1].init("shortDescription", "Time in seconds how long it takes to go from zero maxDistance to full maxDistance", true);
+ ParamDefTable[16].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=17, longName="clothingMaterialIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[17];
+ ParamDef->init("clothingMaterialIndex", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Use this material from the assets material library", true);
+ ParamDefTable[17].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=18, longName="windParams"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[18];
+ ParamDef->init("windParams", TYPE_STRUCT, "WindParameters", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The per-actor wind parameters", true);
+ ParamDefTable[18].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=19, longName="windParams.Velocity"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[19];
+ ParamDef->init("Velocity", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The target velocity each vertex tries to achieve.", true);
+ ParamDefTable[19].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=20, longName="windParams.Adaption"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[20];
+ ParamDef->init("Adaption", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "This is roughly the inverse of the time in seconds it takes to adapt to the wind velocity.", true);
+ HintTable[1].init("shortDescription", "The rate of adaption. The higher this value, the faster the cloth reaches the wind velocity. Set to 0 to turn off wind.", true);
+ ParamDefTable[20].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=21, longName="maxDistanceScale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[21];
+ ParamDef->init("maxDistanceScale", TYPE_STRUCT, "MaxDistanceScale", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Maximum distance scale", true);
+ ParamDefTable[21].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=22, longName="maxDistanceScale.Scale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[22];
+ ParamDef->init("Scale", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Scale", true);
+ ParamDefTable[22].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=23, longName="maxDistanceScale.Multipliable"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[23];
+ ParamDef->init("Multipliable", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Multipliable", true);
+ ParamDefTable[23].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=24, longName="userData"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[24];
+ ParamDef->init("userData", TYPE_U64, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[24].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("shortDescription", "Optional user data pointer associated with the clothing actor", true);
+ ParamDefTable[24].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=25, longName="boneMatrices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[25];
+ ParamDef->init("boneMatrices", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[25].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("longDescription", "These matrices are sometimes referred to as composite matrices. They are the\nmultiplication of the current world space bone pose with the inverse bind\npose in world space.\nNote: If \'updateStateWithGlobalMatrices\' is set to true, these must be\nglobal poses instead.\n", true);
+ HintTable[2].init("shortDescription", "An Array of matrices with the full transform for each bone", true);
+ ParamDefTable[25].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=26, longName="boneMatrices[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[26];
+ ParamDef->init("boneMatrices", TYPE_MAT44, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[26].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("longDescription", "These matrices are sometimes referred to as composite matrices. They are the\nmultiplication of the current world space bone pose with the inverse bind\npose in world space.\nNote: If \'updateStateWithGlobalMatrices\' is set to true, these must be\nglobal poses instead.\n", true);
+ HintTable[2].init("shortDescription", "An Array of matrices with the full transform for each bone", true);
+ ParamDefTable[26].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=27, longName="clothDescTemplate"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[27];
+ ParamDef->init("clothDescTemplate", TYPE_STRUCT, "ClothDescTemplate", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Contains the parameters the application can override on the NxClothDesc when created", true);
+ ParamDefTable[27].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=28, longName="clothDescTemplate.collisionResponseCoefficient"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[28];
+ ParamDef->init("collisionResponseCoefficient", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "This is only needed if the twoway interaction flag is set in the clothing asset.", true);
+ HintTable[1].init("shortDescription", "Defines a factor for the impulse transfer from cloth to colliding rigid bodies.", true);
+ ParamDefTable[28].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=29, longName="clothDescTemplate.collisionGroup"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[29];
+ ParamDef->init("collisionGroup", TYPE_U16, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Sets which collision group this cloth is part of.", true);
+ ParamDefTable[29].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=30, longName="clothDescTemplate.groupsMask"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[30];
+ ParamDef->init("groupsMask", TYPE_STRUCT, "GroupsMask", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Sets the 128-bit mask used for collision filtering.", true);
+ ParamDefTable[30].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=31, longName="clothDescTemplate.groupsMask.bits0"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[31];
+ ParamDef->init("bits0", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "First part of 128-bit group mask", true);
+ ParamDefTable[31].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=32, longName="clothDescTemplate.groupsMask.bits1"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[32];
+ ParamDef->init("bits1", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Second part of 128-bit group mask", true);
+ ParamDefTable[32].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=33, longName="clothDescTemplate.groupsMask.bits2"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[33];
+ ParamDef->init("bits2", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Third part of 128-bit group mask", true);
+ ParamDefTable[33].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=34, longName="clothDescTemplate.groupsMask.bits3"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[34];
+ ParamDef->init("bits3", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Fourth part of 128-bit group mask", true);
+ ParamDefTable[34].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=35, longName="clothDescTemplate.validBounds"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[35];
+ ParamDef->init("validBounds", TYPE_BOUNDS3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Only works if the flag NX_CLF_VALIDBOUNDS is set.", true);
+ HintTable[1].init("shortDescription", "Defines the volume outside of which cloth particle are automatically removed from the simulation. ", true);
+ ParamDefTable[35].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=36, longName="clothDescTemplate.compartment"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[36];
+ ParamDef->init("compartment", TYPE_U64, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[36].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("longDescription", "Must be either a pointer to an NxCompartment of type NX_SCT_CLOTH or\nNX_SCT_SOFTBODY, or NULL. A NULL compartment means creating NX_CLF_HARDWARE\ncloth in the first available cloth compartment (a default cloth compartment\nis created if none exists). Software cloth with a NULL compartment is\ncreated in the scene proper.\n", true);
+ HintTable[2].init("shortDescription", "The compartment to place the cloth in.", true);
+ ParamDefTable[36].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=37, longName="clothDescTemplate.userData"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[37];
+ ParamDef->init("userData", TYPE_U64, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[37].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("shortDescription", "Optional user data pointer.", true);
+ ParamDefTable[37].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=38, longName="shapeDescTemplate"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[38];
+ ParamDef->init("shapeDescTemplate", TYPE_STRUCT, "ShapeDescTemplate", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Contains the parameters the application can override on any actor shapes created", true);
+ ParamDefTable[38].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=39, longName="shapeDescTemplate.flags"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[39];
+ ParamDef->init("flags", TYPE_STRUCT, "ShapeDescFlags", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Shape description flags", true);
+ ParamDefTable[39].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=40, longName="shapeDescTemplate.flags.NX_SF_VISUALIZATION"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[40];
+ ParamDef->init("NX_SF_VISUALIZATION", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Enable debug renderer for this shape", true);
+ ParamDefTable[40].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=41, longName="shapeDescTemplate.flags.NX_SF_DISABLE_COLLISION"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[41];
+ ParamDef->init("NX_SF_DISABLE_COLLISION", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Disable collision detection for this shape (counterpart of NX_AF_DISABLE_COLLISION)", true);
+ ParamDefTable[41].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=42, longName="shapeDescTemplate.flags.NX_SF_DISABLE_RAYCASTING"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[42];
+ ParamDef->init("NX_SF_DISABLE_RAYCASTING", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Disable raycasting for this shape", true);
+ ParamDefTable[42].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=43, longName="shapeDescTemplate.flags.NX_SF_DYNAMIC_DYNAMIC_CCD"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[43];
+ ParamDef->init("NX_SF_DYNAMIC_DYNAMIC_CCD", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Enable dynamic-dynamic CCD for this shape. Used only when CCD is globally enabled and shape have a CCD skeleton.", true);
+ ParamDefTable[43].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=44, longName="shapeDescTemplate.flags.NX_SF_DISABLE_SCENE_QUERIES"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[44];
+ ParamDef->init("NX_SF_DISABLE_SCENE_QUERIES", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Setting this to true will make the non-compartment CPU cloth not work.", true);
+ HintTable[1].init("shortDescription", "Disable participation in ray casts, overlap tests and sweeps.", true);
+ ParamDefTable[44].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=45, longName="shapeDescTemplate.collisionGroup"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[45];
+ ParamDef->init("collisionGroup", TYPE_U16, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Default group is 0. Maximum possible group is 31. Collision groups are sets\nof shapes which may or may not be set to collision detect with each other;\nthis can be set using NxScene::setGroupCollisionFlag()\nSleeping: Does NOT wake the associated actor up automatically.\n", true);
+ HintTable[1].init("shortDescription", "Sets which collision group this shape is part of.", true);
+ ParamDefTable[45].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=46, longName="shapeDescTemplate.groupsMask"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[46];
+ ParamDef->init("groupsMask", TYPE_STRUCT, "GroupsMask", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Sets the 128-bit mask used for collision filtering.", true);
+ ParamDefTable[46].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=47, longName="shapeDescTemplate.groupsMask.bits0"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[47];
+ ParamDef->init("bits0", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "First part of 128-bit group mask", true);
+ ParamDefTable[47].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=48, longName="shapeDescTemplate.groupsMask.bits1"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[48];
+ ParamDef->init("bits1", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Second part of 128-bit group mask", true);
+ ParamDefTable[48].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=49, longName="shapeDescTemplate.groupsMask.bits2"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[49];
+ ParamDef->init("bits2", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Third part of 128-bit group mask", true);
+ ParamDefTable[49].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=50, longName="shapeDescTemplate.groupsMask.bits3"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[50];
+ ParamDef->init("bits3", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Fourth part of 128-bit group mask", true);
+ ParamDefTable[50].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=51, longName="shapeDescTemplate.materialIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[51];
+ ParamDef->init("materialIndex", TYPE_U16, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The material index of the shape.", true);
+ ParamDefTable[51].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=52, longName="shapeDescTemplate.userData"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[52];
+ ParamDef->init("userData", TYPE_U64, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[52].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("shortDescription", "Optional user data pointer", true);
+ ParamDefTable[52].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=53, longName="shapeDescTemplate.name"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[53];
+ ParamDef->init("name", TYPE_U64, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[53].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("shortDescription", "Name of the shapes; must be set by the application and must be a persistent pointer.", true);
+ ParamDefTable[53].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=54, longName="actorDescTemplate"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[54];
+ ParamDef->init("actorDescTemplate", TYPE_STRUCT, "ActorDescTemplate", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Contains the parameters the application can override on any actors created", true);
+ ParamDefTable[54].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=55, longName="actorDescTemplate.userData"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[55];
+ ParamDef->init("userData", TYPE_U64, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[55].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("shortDescription", "Optional user data pointer", true);
+ ParamDefTable[55].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=56, longName="actorDescTemplate.name"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[56];
+ ParamDef->init("name", TYPE_U64, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[56].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("shortDescription", "Optional name string for the shape; must be set by the application and must be a persistent pointer.", true);
+ ParamDefTable[56].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=57, longName="actorScale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[57];
+ ParamDef->init("actorScale", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Setting globalPose doesn't change the actor scale, actorScale should be set separately.\n", true);
+ HintTable[1].init("shortDescription", "Scales the actor relative to the asset.", true);
+ ParamDefTable[57].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=58, longName="runtimeCooked"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[58];
+ ParamDef->init("runtimeCooked", TYPE_REF, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ ParamDefTable[58].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Data cooked at runtime", true);
+ ParamDefTable[58].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+ static const char* const RefVariantVals[] = { "ClothingCookedParam" };
+ ParamDefTable[58].setRefVariantVals((const char**)RefVariantVals, 1);
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=59, longName="morphDisplacements"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[59];
+ ParamDef->init("morphDisplacements", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Displacements according to the current morph target.", true);
+ ParamDefTable[59].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=60, longName="morphDisplacements[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[60];
+ ParamDef->init("morphDisplacements", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Displacements according to the current morph target.", true);
+ ParamDefTable[60].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=61, longName="morphPhysicalMeshNewPositions"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[61];
+ ParamDef->init("morphPhysicalMeshNewPositions", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "New positions for the physical meshes and convex collision volumes.", true);
+ ParamDefTable[61].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=62, longName="morphPhysicalMeshNewPositions[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[62];
+ ParamDef->init("morphPhysicalMeshNewPositions", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "New positions for the physical meshes and convex collision volumes.", true);
+ ParamDefTable[62].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=63, longName="morphGraphicalMeshNewPositions"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[63];
+ ParamDef->init("morphGraphicalMeshNewPositions", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "New positions of all submeshes of all graphical meshes.", true);
+ ParamDefTable[63].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=64, longName="morphGraphicalMeshNewPositions[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[64];
+ ParamDef->init("morphGraphicalMeshNewPositions", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "New positions of all submeshes of all graphical meshes.", true);
+ ParamDefTable[64].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=65, longName="allowAdaptiveTargetFrequency"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[65];
+ ParamDef->init("allowAdaptiveTargetFrequency", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Slightly modifies gravity to avoid high frequency jittering due to variable time steps.", true);
+ ParamDefTable[65].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=66, longName="useVelocityClamping"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[66];
+ ParamDef->init("useVelocityClamping", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Enable/disable velocity clamping", true);
+ ParamDefTable[66].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=67, longName="vertexVelocityClamp"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[67];
+ ParamDef->init("vertexVelocityClamp", TYPE_BOUNDS3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Vertex velocity clamping values", true);
+ ParamDefTable[67].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=68, longName="pressure"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[68];
+ ParamDef->init("pressure", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Set pressure of cloth, only works on closed meshes.", true);
+ ParamDefTable[68].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=69, longName="multiplyGlobalPoseIntoBones"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[69];
+ ParamDef->init("multiplyGlobalPoseIntoBones", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Enable/disable multiplying global pose into bones", true);
+ ParamDefTable[69].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=70, longName="overrideMaterialNames"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[70];
+ ParamDef->init("overrideMaterialNames", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Replacement material names for the ones provided by the render mesh asset inside the clothing asset.", true);
+ ParamDefTable[70].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ static const uint8_t dynHandleIndices[1] = { 0, };
+ ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1);
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=71, longName="overrideMaterialNames[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[71];
+ ParamDef->init("overrideMaterialNames", TYPE_STRING, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Replacement material names for the ones provided by the render mesh asset inside the clothing asset.", true);
+ ParamDefTable[71].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=72, longName="simulationBackend"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[72];
+ ParamDef->init("simulationBackend", TYPE_ENUM, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Select which backend should be used. 'ForceNative' will only work when running with the 2.8.x PhysX SDK", true);
+ ParamDefTable[72].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+ static const char* const EnumVals[] = { "Default", "ForceNative", "ForceEmbedded" };
+ ParamDefTable[72].setEnumVals((const char**)EnumVals, 3);
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=73, longName="freezeByLOD"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[73];
+ ParamDef->init("freezeByLOD", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Cloth state frozen when LoD turns off simulation of the actor, instead of returning to the animated state.", true);
+ ParamDefTable[73].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=74, longName="localSpaceSim"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[74];
+ ParamDef->init("localSpaceSim", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "If this flag is enabled the simulation is done at origin, however the cloth is rendered at its global position.\nThe simulation of the actor is transformed such that the root bone ends up at origin. The scale of the actor is maintained during the simulation.\nIf a 3.x physX simulation backend is used, it is possible to add the inertia effects to the simulation, through\nthe inertiaScale parameter of the clothing material. So with an inertiaScale of 1.0 there should be no visible\ndifference between local space and global space simulation.\nKnown issues:\n- PhysX 2.8.4 does not support inertiaScale (it corresponds to inertiaScale=0.0f). So if localSpaceSim is enabled there's no inertia effect when the global pose of the clothing actor changes.\n- With 2.8.4 this only works for clothing on 1 character, without world collision. This is because collision volumes would interfere with the cloth that is simulated at origin.\nThis is not a problem in 3.x because there collision only happens with the collision volumes specifically defined for the clothing actor.\n", true);
+ HintTable[1].init("shortDescription", "Do simulation in local space.", true);
+ ParamDefTable[74].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=75, longName="teleportMode"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[75];
+ ParamDef->init("teleportMode", TYPE_I32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "0 = ClothingTeleportMode::Continuous\n1 = ClothingTeleportMode::Teleport\n2 = ClothingTeleportMode::TeleportAndReset\n", true);
+ HintTable[1].init("shortDescription", "Buffered teleport state for the next simulate call, gets set in updateState, is reset to Continuous during simulate().", true);
+ ParamDefTable[75].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // SetChildren for: nodeIndex=0, longName=""
+ {
+ static Definition* Children[32];
+ Children[0] = PDEF_PTR(1);
+ Children[1] = PDEF_PTR(2);
+ Children[2] = PDEF_PTR(3);
+ Children[3] = PDEF_PTR(11);
+ Children[4] = PDEF_PTR(12);
+ Children[5] = PDEF_PTR(13);
+ Children[6] = PDEF_PTR(14);
+ Children[7] = PDEF_PTR(15);
+ Children[8] = PDEF_PTR(16);
+ Children[9] = PDEF_PTR(17);
+ Children[10] = PDEF_PTR(18);
+ Children[11] = PDEF_PTR(21);
+ Children[12] = PDEF_PTR(24);
+ Children[13] = PDEF_PTR(25);
+ Children[14] = PDEF_PTR(27);
+ Children[15] = PDEF_PTR(38);
+ Children[16] = PDEF_PTR(54);
+ Children[17] = PDEF_PTR(57);
+ Children[18] = PDEF_PTR(58);
+ Children[19] = PDEF_PTR(59);
+ Children[20] = PDEF_PTR(61);
+ Children[21] = PDEF_PTR(63);
+ Children[22] = PDEF_PTR(65);
+ Children[23] = PDEF_PTR(66);
+ Children[24] = PDEF_PTR(67);
+ Children[25] = PDEF_PTR(68);
+ Children[26] = PDEF_PTR(69);
+ Children[27] = PDEF_PTR(70);
+ Children[28] = PDEF_PTR(72);
+ Children[29] = PDEF_PTR(73);
+ Children[30] = PDEF_PTR(74);
+ Children[31] = PDEF_PTR(75);
+
+ ParamDefTable[0].setChildren(Children, 32);
+ }
+
+ // SetChildren for: nodeIndex=3, longName="flags"
+ {
+ static Definition* Children[7];
+ Children[0] = PDEF_PTR(4);
+ Children[1] = PDEF_PTR(5);
+ Children[2] = PDEF_PTR(6);
+ Children[3] = PDEF_PTR(7);
+ Children[4] = PDEF_PTR(8);
+ Children[5] = PDEF_PTR(9);
+ Children[6] = PDEF_PTR(10);
+
+ ParamDefTable[3].setChildren(Children, 7);
+ }
+
+ // SetChildren for: nodeIndex=18, longName="windParams"
+ {
+ static Definition* Children[2];
+ Children[0] = PDEF_PTR(19);
+ Children[1] = PDEF_PTR(20);
+
+ ParamDefTable[18].setChildren(Children, 2);
+ }
+
+ // SetChildren for: nodeIndex=21, longName="maxDistanceScale"
+ {
+ static Definition* Children[2];
+ Children[0] = PDEF_PTR(22);
+ Children[1] = PDEF_PTR(23);
+
+ ParamDefTable[21].setChildren(Children, 2);
+ }
+
+ // SetChildren for: nodeIndex=25, longName="boneMatrices"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(26);
+
+ ParamDefTable[25].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=27, longName="clothDescTemplate"
+ {
+ static Definition* Children[6];
+ Children[0] = PDEF_PTR(28);
+ Children[1] = PDEF_PTR(29);
+ Children[2] = PDEF_PTR(30);
+ Children[3] = PDEF_PTR(35);
+ Children[4] = PDEF_PTR(36);
+ Children[5] = PDEF_PTR(37);
+
+ ParamDefTable[27].setChildren(Children, 6);
+ }
+
+ // SetChildren for: nodeIndex=30, longName="clothDescTemplate.groupsMask"
+ {
+ static Definition* Children[4];
+ Children[0] = PDEF_PTR(31);
+ Children[1] = PDEF_PTR(32);
+ Children[2] = PDEF_PTR(33);
+ Children[3] = PDEF_PTR(34);
+
+ ParamDefTable[30].setChildren(Children, 4);
+ }
+
+ // SetChildren for: nodeIndex=38, longName="shapeDescTemplate"
+ {
+ static Definition* Children[6];
+ Children[0] = PDEF_PTR(39);
+ Children[1] = PDEF_PTR(45);
+ Children[2] = PDEF_PTR(46);
+ Children[3] = PDEF_PTR(51);
+ Children[4] = PDEF_PTR(52);
+ Children[5] = PDEF_PTR(53);
+
+ ParamDefTable[38].setChildren(Children, 6);
+ }
+
+ // SetChildren for: nodeIndex=39, longName="shapeDescTemplate.flags"
+ {
+ static Definition* Children[5];
+ Children[0] = PDEF_PTR(40);
+ Children[1] = PDEF_PTR(41);
+ Children[2] = PDEF_PTR(42);
+ Children[3] = PDEF_PTR(43);
+ Children[4] = PDEF_PTR(44);
+
+ ParamDefTable[39].setChildren(Children, 5);
+ }
+
+ // SetChildren for: nodeIndex=46, longName="shapeDescTemplate.groupsMask"
+ {
+ static Definition* Children[4];
+ Children[0] = PDEF_PTR(47);
+ Children[1] = PDEF_PTR(48);
+ Children[2] = PDEF_PTR(49);
+ Children[3] = PDEF_PTR(50);
+
+ ParamDefTable[46].setChildren(Children, 4);
+ }
+
+ // SetChildren for: nodeIndex=54, longName="actorDescTemplate"
+ {
+ static Definition* Children[2];
+ Children[0] = PDEF_PTR(55);
+ Children[1] = PDEF_PTR(56);
+
+ ParamDefTable[54].setChildren(Children, 2);
+ }
+
+ // SetChildren for: nodeIndex=59, longName="morphDisplacements"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(60);
+
+ ParamDefTable[59].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=61, longName="morphPhysicalMeshNewPositions"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(62);
+
+ ParamDefTable[61].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=63, longName="morphGraphicalMeshNewPositions"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(64);
+
+ ParamDefTable[63].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=70, longName="overrideMaterialNames"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(71);
+
+ ParamDefTable[70].setChildren(Children, 1);
+ }
+
+ mBuiltFlag = true;
+
+}
+void ClothingActorParam::initStrings(void)
+{
+}
+
+void ClothingActorParam::initDynamicArrays(void)
+{
+ boneMatrices.buf = NULL;
+ boneMatrices.isAllocated = true;
+ boneMatrices.elementSize = sizeof(physx::PxMat44);
+ boneMatrices.arraySizes[0] = 0;
+ morphDisplacements.buf = NULL;
+ morphDisplacements.isAllocated = true;
+ morphDisplacements.elementSize = sizeof(physx::PxVec3);
+ morphDisplacements.arraySizes[0] = 0;
+ morphPhysicalMeshNewPositions.buf = NULL;
+ morphPhysicalMeshNewPositions.isAllocated = true;
+ morphPhysicalMeshNewPositions.elementSize = sizeof(physx::PxVec3);
+ morphPhysicalMeshNewPositions.arraySizes[0] = 0;
+ morphGraphicalMeshNewPositions.buf = NULL;
+ morphGraphicalMeshNewPositions.isAllocated = true;
+ morphGraphicalMeshNewPositions.elementSize = sizeof(physx::PxVec3);
+ morphGraphicalMeshNewPositions.arraySizes[0] = 0;
+ overrideMaterialNames.buf = NULL;
+ overrideMaterialNames.isAllocated = true;
+ overrideMaterialNames.elementSize = sizeof(NvParameterized::DummyStringStruct);
+ overrideMaterialNames.arraySizes[0] = 0;
+}
+
+void ClothingActorParam::initDefaults(void)
+{
+
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+ globalPose = physx::PxMat44(physx::PxVec4(1.0f));
+ useHardwareCloth = bool(true);
+ flags.ParallelCpuSkinning = bool(true);
+ flags.RecomputeNormals = bool(false);
+ flags.RecomputeTangents = bool(false);
+ flags.Visualize = bool(true);
+ flags.CorrectSimulationNormals = bool(true);
+ flags.ComputeRenderData = bool(true);
+ flags.ComputePhysicsMeshNormals = bool(true);
+ fallbackSkinning = bool(false);
+ slowStart = bool(true);
+ useInternalBoneOrder = bool(false);
+ updateStateWithGlobalMatrices = bool(false);
+ uvChannelForTangentUpdate = uint32_t(0);
+ maxDistanceBlendTime = float(1.0);
+ clothingMaterialIndex = uint32_t(0);
+ windParams.Velocity = physx::PxVec3(0.0f);
+ windParams.Adaption = float(0.0f);
+ maxDistanceScale.Scale = float(1.0f);
+ maxDistanceScale.Multipliable = bool(false);
+ userData = uint64_t(0);
+ clothDescTemplate.collisionResponseCoefficient = float(0.2);
+ clothDescTemplate.collisionGroup = uint16_t(0);
+ clothDescTemplate.groupsMask.bits0 = uint32_t(0);
+ clothDescTemplate.groupsMask.bits1 = uint32_t(0);
+ clothDescTemplate.groupsMask.bits2 = uint32_t(0);
+ clothDescTemplate.groupsMask.bits3 = uint32_t(0);
+ clothDescTemplate.validBounds = physx::PxBounds3(physx::PxVec3(PX_MAX_F32), physx::PxVec3(-PX_MAX_F32));
+ clothDescTemplate.compartment = uint64_t(0);
+ shapeDescTemplate.flags.NX_SF_VISUALIZATION = bool(true);
+ shapeDescTemplate.flags.NX_SF_DISABLE_COLLISION = bool(false);
+ shapeDescTemplate.flags.NX_SF_DISABLE_RAYCASTING = bool(true);
+ shapeDescTemplate.flags.NX_SF_DYNAMIC_DYNAMIC_CCD = bool(false);
+ shapeDescTemplate.flags.NX_SF_DISABLE_SCENE_QUERIES = bool(false);
+ shapeDescTemplate.collisionGroup = uint16_t(0);
+ shapeDescTemplate.groupsMask.bits0 = uint32_t(0);
+ shapeDescTemplate.groupsMask.bits1 = uint32_t(0);
+ shapeDescTemplate.groupsMask.bits2 = uint32_t(0);
+ shapeDescTemplate.groupsMask.bits3 = uint32_t(0);
+ shapeDescTemplate.materialIndex = uint16_t(0);
+ shapeDescTemplate.userData = uint64_t(0);
+ shapeDescTemplate.name = uint64_t(0);
+ actorDescTemplate.userData = uint64_t(0);
+ actorDescTemplate.name = uint64_t(0);
+ actorScale = float(1.0);
+ allowAdaptiveTargetFrequency = bool(true);
+ useVelocityClamping = bool(false);
+ vertexVelocityClamp = physx::PxBounds3(physx::PxVec3(-PX_MAX_F32), physx::PxVec3(PX_MAX_F32));
+ pressure = float(-1.0);
+ multiplyGlobalPoseIntoBones = bool(true);
+ simulationBackend = (const char*)"Default";
+ freezeByLOD = bool(false);
+ localSpaceSim = bool(false);
+ teleportMode = int32_t(0);
+
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+}
+
+void ClothingActorParam::initReferences(void)
+{
+ runtimeCooked = NULL;
+
+}
+
+void ClothingActorParam::freeDynamicArrays(void)
+{
+ if (boneMatrices.isAllocated && boneMatrices.buf)
+ {
+ mParameterizedTraits->free(boneMatrices.buf);
+ }
+ if (morphDisplacements.isAllocated && morphDisplacements.buf)
+ {
+ mParameterizedTraits->free(morphDisplacements.buf);
+ }
+ if (morphPhysicalMeshNewPositions.isAllocated && morphPhysicalMeshNewPositions.buf)
+ {
+ mParameterizedTraits->free(morphPhysicalMeshNewPositions.buf);
+ }
+ if (morphGraphicalMeshNewPositions.isAllocated && morphGraphicalMeshNewPositions.buf)
+ {
+ mParameterizedTraits->free(morphGraphicalMeshNewPositions.buf);
+ }
+ if (overrideMaterialNames.isAllocated && overrideMaterialNames.buf)
+ {
+ mParameterizedTraits->free(overrideMaterialNames.buf);
+ }
+}
+
+void ClothingActorParam::freeStrings(void)
+{
+
+ for (int i = 0; i < overrideMaterialNames.arraySizes[0]; ++i)
+ {
+ if (overrideMaterialNames.buf[i].isAllocated && overrideMaterialNames.buf[i].buf)
+ {
+ mParameterizedTraits->strfree((char*)overrideMaterialNames.buf[i].buf);
+ }
+ }
+}
+
+void ClothingActorParam::freeReferences(void)
+{
+ if (runtimeCooked)
+ {
+ runtimeCooked->destroy();
+ }
+
+}
+
+} // namespace clothing
+} // namespace nvidia
diff --git a/APEX_1.4/module/clothing/src/autogen/ClothingAssetParameters.cpp b/APEX_1.4/module/clothing/src/autogen/ClothingAssetParameters.cpp
new file mode 100644
index 00000000..eee0c7f2
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/autogen/ClothingAssetParameters.cpp
@@ -0,0 +1,2046 @@
+// 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-2015 NVIDIA Corporation. All rights reserved.
+
+// This file was generated by NvParameterized/scripts/GenParameterized.pl
+
+
+#include "ClothingAssetParameters.h"
+#include <string.h>
+#include <stdlib.h>
+
+using namespace NvParameterized;
+
+namespace nvidia
+{
+namespace clothing
+{
+
+using namespace ClothingAssetParametersNS;
+
+const char* const ClothingAssetParametersFactory::vptr =
+ NvParameterized::getVptr<ClothingAssetParameters, ClothingAssetParameters::ClassAlignment>();
+
+const uint32_t NumParamDefs = 60;
+static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs];
+
+
+static const size_t ParamLookupChildrenTable[] =
+{
+ 1, 3, 5, 15, 24, 25, 26, 27, 35, 37, 42, 44, 49, 51, 55, 56, 57, 58, 59, 2, 4, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 28, 29, 30, 31, 32,
+ 33, 34, 36, 38, 39, 40, 41, 43, 45, 46, 47, 48, 50, 52, 53, 54,
+};
+
+#define TENUM(type) nvidia::##type
+#define CHILDREN(index) &ParamLookupChildrenTable[index]
+static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] =
+{
+ { TYPE_STRUCT, false, 0, CHILDREN(0), 19 },
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->physicalMeshes), CHILDREN(19), 1 }, // physicalMeshes
+ { TYPE_REF, false, 1 * sizeof(NvParameterized::Interface*), NULL, 0 }, // physicalMeshes[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->graphicalLods), CHILDREN(20), 1 }, // graphicalLods
+ { TYPE_REF, false, 1 * sizeof(NvParameterized::Interface*), NULL, 0 }, // graphicalLods[]
+ { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->simulation), CHILDREN(21), 9 }, // simulation
+ { TYPE_U32, false, (size_t)(&((SimulationParams_Type*)0)->hierarchicalLevels), NULL, 0 }, // simulation.hierarchicalLevels
+ { TYPE_F32, false, (size_t)(&((SimulationParams_Type*)0)->thickness), NULL, 0 }, // simulation.thickness
+ { TYPE_F32, false, (size_t)(&((SimulationParams_Type*)0)->virtualParticleDensity), NULL, 0 }, // simulation.virtualParticleDensity
+ { TYPE_VEC3, false, (size_t)(&((SimulationParams_Type*)0)->gravityDirection), NULL, 0 }, // simulation.gravityDirection
+ { TYPE_F32, false, (size_t)(&((SimulationParams_Type*)0)->sleepLinearVelocity), NULL, 0 }, // simulation.sleepLinearVelocity
+ { TYPE_BOOL, false, (size_t)(&((SimulationParams_Type*)0)->disableCCD), NULL, 0 }, // simulation.disableCCD
+ { TYPE_BOOL, false, (size_t)(&((SimulationParams_Type*)0)->untangling), NULL, 0 }, // simulation.untangling
+ { TYPE_BOOL, false, (size_t)(&((SimulationParams_Type*)0)->twowayInteraction), NULL, 0 }, // simulation.twowayInteraction
+ { TYPE_F32, false, (size_t)(&((SimulationParams_Type*)0)->restLengthScale), NULL, 0 }, // simulation.restLengthScale
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->bones), CHILDREN(30), 1 }, // bones
+ { TYPE_STRUCT, false, 1 * sizeof(BoneEntry_Type), CHILDREN(31), 7 }, // bones[]
+ { TYPE_I32, false, (size_t)(&((BoneEntry_Type*)0)->internalIndex), NULL, 0 }, // bones[].internalIndex
+ { TYPE_I32, false, (size_t)(&((BoneEntry_Type*)0)->externalIndex), NULL, 0 }, // bones[].externalIndex
+ { TYPE_U32, false, (size_t)(&((BoneEntry_Type*)0)->numMeshReferenced), NULL, 0 }, // bones[].numMeshReferenced
+ { TYPE_U32, false, (size_t)(&((BoneEntry_Type*)0)->numRigidBodiesReferenced), NULL, 0 }, // bones[].numRigidBodiesReferenced
+ { TYPE_I32, false, (size_t)(&((BoneEntry_Type*)0)->parentIndex), NULL, 0 }, // bones[].parentIndex
+ { TYPE_MAT44, false, (size_t)(&((BoneEntry_Type*)0)->bindPose), NULL, 0 }, // bones[].bindPose
+ { TYPE_STRING, false, (size_t)(&((BoneEntry_Type*)0)->name), NULL, 0 }, // bones[].name
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->bonesReferenced), NULL, 0 }, // bonesReferenced
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->bonesReferencedByMesh), NULL, 0 }, // bonesReferencedByMesh
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->rootBoneIndex), NULL, 0 }, // rootBoneIndex
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->boneActors), CHILDREN(38), 1 }, // boneActors
+ { TYPE_STRUCT, false, 1 * sizeof(ActorEntry_Type), CHILDREN(39), 6 }, // boneActors[]
+ { TYPE_I32, false, (size_t)(&((ActorEntry_Type*)0)->boneIndex), NULL, 0 }, // boneActors[].boneIndex
+ { TYPE_U32, false, (size_t)(&((ActorEntry_Type*)0)->convexVerticesStart), NULL, 0 }, // boneActors[].convexVerticesStart
+ { TYPE_U32, false, (size_t)(&((ActorEntry_Type*)0)->convexVerticesCount), NULL, 0 }, // boneActors[].convexVerticesCount
+ { TYPE_F32, false, (size_t)(&((ActorEntry_Type*)0)->capsuleRadius), NULL, 0 }, // boneActors[].capsuleRadius
+ { TYPE_F32, false, (size_t)(&((ActorEntry_Type*)0)->capsuleHeight), NULL, 0 }, // boneActors[].capsuleHeight
+ { TYPE_MAT44, false, (size_t)(&((ActorEntry_Type*)0)->localPose), NULL, 0 }, // boneActors[].localPose
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->boneVertices), CHILDREN(45), 1 }, // boneVertices
+ { TYPE_VEC3, false, 1 * sizeof(physx::PxVec3), NULL, 0 }, // boneVertices[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->boneSpheres), CHILDREN(46), 1 }, // boneSpheres
+ { TYPE_STRUCT, false, 1 * sizeof(BoneSphere_Type), CHILDREN(47), 3 }, // boneSpheres[]
+ { TYPE_I32, false, (size_t)(&((BoneSphere_Type*)0)->boneIndex), NULL, 0 }, // boneSpheres[].boneIndex
+ { TYPE_F32, false, (size_t)(&((BoneSphere_Type*)0)->radius), NULL, 0 }, // boneSpheres[].radius
+ { TYPE_VEC3, false, (size_t)(&((BoneSphere_Type*)0)->localPos), NULL, 0 }, // boneSpheres[].localPos
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->boneSphereConnections), CHILDREN(50), 1 }, // boneSphereConnections
+ { TYPE_U16, false, 1 * sizeof(uint16_t), NULL, 0 }, // boneSphereConnections[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->bonePlanes), CHILDREN(51), 1 }, // bonePlanes
+ { TYPE_STRUCT, false, 1 * sizeof(BonePlane_Type), CHILDREN(52), 3 }, // bonePlanes[]
+ { TYPE_I32, false, (size_t)(&((BonePlane_Type*)0)->boneIndex), NULL, 0 }, // bonePlanes[].boneIndex
+ { TYPE_VEC3, false, (size_t)(&((BonePlane_Type*)0)->n), NULL, 0 }, // bonePlanes[].n
+ { TYPE_F32, false, (size_t)(&((BonePlane_Type*)0)->d), NULL, 0 }, // bonePlanes[].d
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->collisionConvexes), CHILDREN(55), 1 }, // collisionConvexes
+ { TYPE_U32, false, 1 * sizeof(uint32_t), NULL, 0 }, // collisionConvexes[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->cookedData), CHILDREN(56), 1 }, // cookedData
+ { TYPE_STRUCT, false, 1 * sizeof(CookedEntry_Type), CHILDREN(57), 2 }, // cookedData[]
+ { TYPE_F32, false, (size_t)(&((CookedEntry_Type*)0)->scale), NULL, 0 }, // cookedData[].scale
+ { TYPE_REF, false, (size_t)(&((CookedEntry_Type*)0)->cookedData), NULL, 0 }, // cookedData[].cookedData
+ { TYPE_BOUNDS3, false, (size_t)(&((ParametersStruct*)0)->boundingBox), NULL, 0 }, // boundingBox
+ { TYPE_REF, false, (size_t)(&((ParametersStruct*)0)->materialLibrary), NULL, 0 }, // materialLibrary
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->materialIndex), NULL, 0 }, // materialIndex
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->interCollisionChannels), NULL, 0 }, // interCollisionChannels
+ { TYPE_STRING, false, (size_t)(&((ParametersStruct*)0)->toolString), NULL, 0 }, // toolString
+};
+
+
+bool ClothingAssetParameters::mBuiltFlag = false;
+NvParameterized::MutexType ClothingAssetParameters::mBuiltFlagMutex;
+
+ClothingAssetParameters::ClothingAssetParameters(NvParameterized::Traits* traits, void* buf, int32_t* refCount) :
+ NvParameters(traits, buf, refCount)
+{
+ //mParameterizedTraits->registerFactory(className(), &ClothingAssetParametersFactoryInst);
+
+ if (!buf) //Do not init data if it is inplace-deserialized
+ {
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+ initDefaults();
+ }
+}
+
+ClothingAssetParameters::~ClothingAssetParameters()
+{
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+}
+
+void ClothingAssetParameters::destroy()
+{
+ // We cache these fields here to avoid overwrite in destructor
+ bool doDeallocateSelf = mDoDeallocateSelf;
+ NvParameterized::Traits* traits = mParameterizedTraits;
+ int32_t* refCount = mRefCount;
+ void* buf = mBuffer;
+
+ this->~ClothingAssetParameters();
+
+ NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf);
+}
+
+const NvParameterized::DefinitionImpl* ClothingAssetParameters::getParameterDefinitionTree(void)
+{
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+const NvParameterized::DefinitionImpl* ClothingAssetParameters::getParameterDefinitionTree(void) const
+{
+ ClothingAssetParameters* tmpParam = const_cast<ClothingAssetParameters*>(this);
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ tmpParam->buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+NvParameterized::ErrorType ClothingAssetParameters::getParameterHandle(const char* long_name, Handle& handle) const
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+NvParameterized::ErrorType ClothingAssetParameters::getParameterHandle(const char* long_name, Handle& handle)
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+void ClothingAssetParameters::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const
+{
+ ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<ClothingAssetParameters::ParametersStruct*>(&parameters()), handle, offset);
+}
+
+
+/* Dynamic Handle Indices */
+/* [0] - physicalMeshes (not an array of structs) */
+/* [0] - graphicalLods (not an array of structs) */
+/* [1,6] - bones.name */
+/* [1,1] - cookedData.cookedData */
+
+void ClothingAssetParameters::freeParameterDefinitionTable(NvParameterized::Traits* traits)
+{
+ if (!traits)
+ {
+ return;
+ }
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ return;
+ }
+
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+
+ if (!mBuiltFlag)
+ {
+ return;
+ }
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ ParamDefTable[i].~DefinitionImpl();
+ }
+
+ traits->free(ParamDefTable);
+
+ mBuiltFlag = false;
+}
+
+#define PDEF_PTR(index) (&ParamDefTable[index])
+
+void ClothingAssetParameters::buildTree(void)
+{
+
+ uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs;
+ ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize));
+ memset(ParamDefTable, 0, allocSize);
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=0, longName=""
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0];
+ ParamDef->init("", TYPE_STRUCT, "STRUCT", true);
+
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=1, longName="physicalMeshes"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1];
+ ParamDef->init("physicalMeshes", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ HintTable[1].init("longDescription", "These are used for multiple graphical LoDs.", true);
+ HintTable[2].init("shortDescription", "An Array of physical meshes", true);
+ ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+ static const char* const RefVariantVals[] = { "ClothingPhysicalMeshParameters" };
+ ParamDefTable[1].setRefVariantVals((const char**)RefVariantVals, 1);
+
+
+ ParamDef->setArraySize(-1);
+ static const uint8_t dynHandleIndices[1] = { 0, };
+ ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1);
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=2, longName="physicalMeshes[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2];
+ ParamDef->init("physicalMeshes", TYPE_REF, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ HintTable[1].init("longDescription", "These are used for multiple graphical LoDs.", true);
+ HintTable[2].init("shortDescription", "An Array of physical meshes", true);
+ ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+ static const char* const RefVariantVals[] = { "ClothingPhysicalMeshParameters" };
+ ParamDefTable[2].setRefVariantVals((const char**)RefVariantVals, 1);
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=3, longName="graphicalLods"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3];
+ ParamDef->init("graphicalLods", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ HintTable[1].init("longDescription", "Each LoD contains a graphical mesh and a reference to a physical mesh.", true);
+ HintTable[2].init("shortDescription", "An array of graphical Lods.", true);
+ ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+ static const char* const RefVariantVals[] = { "ClothingGraphicalLodParameters" };
+ ParamDefTable[3].setRefVariantVals((const char**)RefVariantVals, 1);
+
+
+ ParamDef->setArraySize(-1);
+ static const uint8_t dynHandleIndices[1] = { 0, };
+ ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1);
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=4, longName="graphicalLods[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4];
+ ParamDef->init("graphicalLods", TYPE_REF, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ HintTable[1].init("longDescription", "Each LoD contains a graphical mesh and a reference to a physical mesh.", true);
+ HintTable[2].init("shortDescription", "An array of graphical Lods.", true);
+ ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+ static const char* const RefVariantVals[] = { "ClothingGraphicalLodParameters" };
+ ParamDefTable[4].setRefVariantVals((const char**)RefVariantVals, 1);
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=5, longName="simulation"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5];
+ ParamDef->init("simulation", TYPE_STRUCT, "SimulationParams", true);
+
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=6, longName="simulation.hierarchicalLevels"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6];
+ ParamDef->init("hierarchicalLevels", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Corresponds to NxClothMeshDesc::numHierarchyLevels.\nThis is orthogonal to the Hard Stretch Limitation in the Clothing Material.\n", true);
+ HintTable[1].init("shortDescription", "The number of cloth hierarhies. Only used to prevent stretching", true);
+ ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=7, longName="simulation.thickness"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7];
+ ParamDef->init("thickness", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Each cloth particle will minimaly have as much distance to any collision volume.\nMost stable when this value corresponds roughly half the average edge length.\nCan be increased to prevent penetration artifacts.\n", true);
+ HintTable[1].init("shortDescription", "Minimal amount of separation between cloth particles and collision volumes.", true);
+ ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=8, longName="simulation.virtualParticleDensity"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8];
+ ParamDef->init("virtualParticleDensity", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "0 will create no virtual particles. 1 will create 3 virtual particles for every triangle. Everything else is in between.", true);
+ HintTable[1].init("shortDescription", "Select the amount of virtual particles generated.", true);
+ ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=9, longName="simulation.gravityDirection"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9];
+ ParamDef->init("gravityDirection", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Direction of gravity for this asset.", true);
+ ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=10, longName="simulation.sleepLinearVelocity"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[10];
+ ParamDef->init("sleepLinearVelocity", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Most clothing doesn't need it, but it might be useful for smaller assets like flags and the like.", true);
+ HintTable[1].init("shortDescription", "Clothing will fall asleep if every vertex is slower than this velocity", true);
+ ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=11, longName="simulation.disableCCD"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[11];
+ ParamDef->init("disableCCD", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "When turning off CCD, cloth particles can tunnel through fast moving collision volumes. But sometimes\nill turning collision volumes can excert large velocities on particles. This can help prevent it.\n", true);
+ HintTable[1].init("shortDescription", "Turn off CCD when colliding cloth particles with collision volumes", true);
+ ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=12, longName="simulation.untangling"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[12];
+ ParamDef->init("untangling", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "This feature is highly experimental and still rather slow. Only use when self-collision could not\nhelp adequately.\n", true);
+ HintTable[1].init("shortDescription", "EXPERIMENTAL: Untangle Cloth when it's entangled.", true);
+ ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=13, longName="simulation.twowayInteraction"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[13];
+ ParamDef->init("twowayInteraction", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "For clothing this is normally not needed, as clothing should only follow the kinematic shapes. Needed when interacting\nwith dynamic rigid bodies that need to be influenced by clothing.\n", true);
+ HintTable[1].init("shortDescription", "Make use of twoway interaction", true);
+ ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=14, longName="simulation.restLengthScale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[14];
+ ParamDef->init("restLengthScale", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Scale for cloth rest lengths.", true);
+ ParamDefTable[14].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=15, longName="bones"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[15];
+ ParamDef->init("bones", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Each bone contains a bind pose and reference counters.", true);
+ HintTable[1].init("shortDescription", "Array of Bones", true);
+ ParamDefTable[15].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ static const uint8_t dynHandleIndices[2] = { 1, 6, };
+ ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 2);
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=16, longName="bones[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[16];
+ ParamDef->init("bones", TYPE_STRUCT, "BoneEntry", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Each bone contains a bind pose and reference counters.", true);
+ HintTable[1].init("shortDescription", "Array of Bones", true);
+ ParamDefTable[16].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=17, longName="bones[].internalIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[17];
+ ParamDef->init("internalIndex", TYPE_I32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "This usually corresponds to the array position this element is at.", true);
+ HintTable[1].init("shortDescription", "The index used internally for this bone.", true);
+ ParamDefTable[17].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=18, longName="bones[].externalIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[18];
+ ParamDef->init("externalIndex", TYPE_I32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The index that was given by the application", true);
+ ParamDefTable[18].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=19, longName="bones[].numMeshReferenced"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[19];
+ ParamDef->init("numMeshReferenced", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The number of mesh vertices that have a non-zero weight to this bone.", true);
+ ParamDefTable[19].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=20, longName="bones[].numRigidBodiesReferenced"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[20];
+ ParamDef->init("numRigidBodiesReferenced", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The number of collision volumes attached to this bone", true);
+ ParamDefTable[20].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=21, longName="bones[].parentIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[21];
+ ParamDef->init("parentIndex", TYPE_I32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The (internal) index of the parent bone", true);
+ ParamDefTable[21].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=22, longName="bones[].bindPose"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[22];
+ ParamDef->init("bindPose", TYPE_MAT44, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The matrix this bone has in the default pose", true);
+ ParamDefTable[22].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=23, longName="bones[].name"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[23];
+ ParamDef->init("name", TYPE_STRING, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The name of this bone", true);
+ ParamDefTable[23].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=24, longName="bonesReferenced"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[24];
+ ParamDef->init("bonesReferenced", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Any bone in the bones array beyond this number is completely useless.", true);
+ HintTable[1].init("shortDescription", "Number of bones actually used by any of the meshes or collision volumes.", true);
+ ParamDefTable[24].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=25, longName="bonesReferencedByMesh"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[25];
+ ParamDef->init("bonesReferencedByMesh", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Bones beyond this index can be used for collision volumes or not at all. This number is smaller or\nequal the 'bonesReferenced' number.\n", true);
+ HintTable[1].init("shortDescription", "Number of bones actually used by any of the meshes", true);
+ ParamDefTable[25].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=26, longName="rootBoneIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[26];
+ ParamDef->init("rootBoneIndex", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Internal bone index with either parent=-1 or one bone with minimal distance to root when root is not inside the used bones", true);
+ ParamDefTable[26].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=27, longName="boneActors"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[27];
+ ParamDef->init("boneActors", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Each collision volume belongs to a bone and contains a description of its shape.", true);
+ HintTable[1].init("shortDescription", "Array of collision volumes", true);
+ ParamDefTable[27].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=28, longName="boneActors[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[28];
+ ParamDef->init("boneActors", TYPE_STRUCT, "ActorEntry", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Each collision volume belongs to a bone and contains a description of its shape.", true);
+ HintTable[1].init("shortDescription", "Array of collision volumes", true);
+ ParamDefTable[28].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=29, longName="boneActors[].boneIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[29];
+ ParamDef->init("boneIndex", TYPE_I32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The (internal) index this collision volume is attached to", true);
+ ParamDefTable[29].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=30, longName="boneActors[].convexVerticesStart"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[30];
+ ParamDef->init("convexVerticesStart", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Index into the boneVertices array where the list of vertices for this shape starts.", true);
+ ParamDefTable[30].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=31, longName="boneActors[].convexVerticesCount"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[31];
+ ParamDef->init("convexVerticesCount", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The number vertices that make up this convex.", true);
+ ParamDefTable[31].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=32, longName="boneActors[].capsuleRadius"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[32];
+ ParamDef->init("capsuleRadius", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The radius of the capsule that describes this collision volume.", true);
+ ParamDefTable[32].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=33, longName="boneActors[].capsuleHeight"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[33];
+ ParamDef->init("capsuleHeight", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The height of the capsule that describes this collision volume.", true);
+ ParamDefTable[33].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=34, longName="boneActors[].localPose"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[34];
+ ParamDef->init("localPose", TYPE_MAT44, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The pose this collision volume has relative to the bone.", true);
+ ParamDefTable[34].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=35, longName="boneVertices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[35];
+ ParamDef->init("boneVertices", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "All convexes use the same array but different parts of it.", true);
+ HintTable[1].init("shortDescription", "Array of vertices that belong to one or more convex collision volumes", true);
+ ParamDefTable[35].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=36, longName="boneVertices[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[36];
+ ParamDef->init("boneVertices", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "All convexes use the same array but different parts of it.", true);
+ HintTable[1].init("shortDescription", "Array of vertices that belong to one or more convex collision volumes", true);
+ ParamDefTable[36].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=37, longName="boneSpheres"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[37];
+ ParamDef->init("boneSpheres", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "The spheres are connected to tapered capsules by the boneSphereConnections array.", true);
+ HintTable[1].init("shortDescription", "Array of spheres that describe the tapered capsules for clothing collision in PhysX3.", true);
+ ParamDefTable[37].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=38, longName="boneSpheres[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[38];
+ ParamDef->init("boneSpheres", TYPE_STRUCT, "BoneSphere", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "The spheres are connected to tapered capsules by the boneSphereConnections array.", true);
+ HintTable[1].init("shortDescription", "Array of spheres that describe the tapered capsules for clothing collision in PhysX3.", true);
+ ParamDefTable[38].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=39, longName="boneSpheres[].boneIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[39];
+ ParamDef->init("boneIndex", TYPE_I32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The (internal) index this collision volume is attached to", true);
+ ParamDefTable[39].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=40, longName="boneSpheres[].radius"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[40];
+ ParamDef->init("radius", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The radius of the sphere that describes this collision volume.", true);
+ ParamDefTable[40].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=41, longName="boneSpheres[].localPos"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[41];
+ ParamDef->init("localPos", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The position this collision volume has relative to the bone.", true);
+ ParamDefTable[41].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=42, longName="boneSphereConnections"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[42];
+ ParamDef->init("boneSphereConnections", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "This is an array of pairs, so the size must be dividible by 2.", true);
+ HintTable[1].init("shortDescription", "Array of indices into the boneSpheres array to describe pairs of spheres that form a capsule.", true);
+ ParamDefTable[42].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=43, longName="boneSphereConnections[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[43];
+ ParamDef->init("boneSphereConnections", TYPE_U16, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "This is an array of pairs, so the size must be dividible by 2.", true);
+ HintTable[1].init("shortDescription", "Array of indices into the boneSpheres array to describe pairs of spheres that form a capsule.", true);
+ ParamDefTable[43].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=44, longName="bonePlanes"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[44];
+ ParamDef->init("bonePlanes", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Array of planes used for collision convexes.", true);
+ ParamDefTable[44].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=45, longName="bonePlanes[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[45];
+ ParamDef->init("bonePlanes", TYPE_STRUCT, "BonePlane", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Array of planes used for collision convexes.", true);
+ ParamDefTable[45].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=46, longName="bonePlanes[].boneIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[46];
+ ParamDef->init("boneIndex", TYPE_I32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The (internal) index this collision volume is attached to", true);
+ ParamDefTable[46].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=47, longName="bonePlanes[].n"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[47];
+ ParamDef->init("n", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Plane normal.", true);
+ ParamDefTable[47].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=48, longName="bonePlanes[].d"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[48];
+ ParamDef->init("d", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Plane distance from origin.", true);
+ ParamDefTable[48].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=49, longName="collisionConvexes"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[49];
+ ParamDef->init("collisionConvexes", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Each entry is a bitmap that describes which bonePlanes are used to define a convex.", true);
+ ParamDefTable[49].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=50, longName="collisionConvexes[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[50];
+ ParamDef->init("collisionConvexes", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Each entry is a bitmap that describes which bonePlanes are used to define a convex.", true);
+ ParamDefTable[50].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=51, longName="cookedData"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[51];
+ ParamDef->init("cookedData", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[51].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Various versions of cooked data", true);
+ ParamDefTable[51].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ static const uint8_t dynHandleIndices[2] = { 1, 1, };
+ ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 2);
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=52, longName="cookedData[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[52];
+ ParamDef->init("cookedData", TYPE_STRUCT, "CookedEntry", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[52].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Various versions of cooked data", true);
+ ParamDefTable[52].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=53, longName="cookedData[].scale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[53];
+ ParamDef->init("scale", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "", true);
+ ParamDefTable[53].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=54, longName="cookedData[].cookedData"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[54];
+ ParamDef->init("cookedData", TYPE_REF, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ ParamDefTable[54].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Data cooked at runtime", true);
+ ParamDefTable[54].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+ static const char* const RefVariantVals[] = { "ClothingCookedParam", "ClothingCookedPhysX3Param" };
+ ParamDefTable[54].setRefVariantVals((const char**)RefVariantVals, 2);
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=55, longName="boundingBox"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[55];
+ ParamDef->init("boundingBox", TYPE_BOUNDS3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "This contains the simulated as well as the animated vertices.", true);
+ HintTable[1].init("shortDescription", "The Bounding-Box of the Asset", true);
+ ParamDefTable[55].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=56, longName="materialLibrary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[56];
+ ParamDef->init("materialLibrary", TYPE_REF, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ ParamDefTable[56].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "The Material Library for this asset", true);
+ ParamDefTable[56].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+ static const char* const RefVariantVals[] = { "ClothingMaterialLibraryParameters" };
+ ParamDefTable[56].setRefVariantVals((const char**)RefVariantVals, 1);
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=57, longName="materialIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[57];
+ ParamDef->init("materialIndex", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Default index for the material in the library", true);
+ ParamDefTable[57].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=58, longName="interCollisionChannels"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[58];
+ ParamDef->init("interCollisionChannels", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Experimental. Each bit of the represents a channel, so there can be a maximum of 32 channels.\nClothingActors that have at least one channel in common will collide, if inter-collision is enabled in the module.\n(3.x simulation only)\n", true);
+ HintTable[1].init("shortDescription", "Experimental. Collision Channels for inter-collision", true);
+ ParamDefTable[58].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=59, longName="toolString"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[59];
+ ParamDef->init("toolString", TYPE_STRING, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Describes the authoring tool.", true);
+ ParamDefTable[59].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // SetChildren for: nodeIndex=0, longName=""
+ {
+ static Definition* Children[19];
+ Children[0] = PDEF_PTR(1);
+ Children[1] = PDEF_PTR(3);
+ Children[2] = PDEF_PTR(5);
+ Children[3] = PDEF_PTR(15);
+ Children[4] = PDEF_PTR(24);
+ Children[5] = PDEF_PTR(25);
+ Children[6] = PDEF_PTR(26);
+ Children[7] = PDEF_PTR(27);
+ Children[8] = PDEF_PTR(35);
+ Children[9] = PDEF_PTR(37);
+ Children[10] = PDEF_PTR(42);
+ Children[11] = PDEF_PTR(44);
+ Children[12] = PDEF_PTR(49);
+ Children[13] = PDEF_PTR(51);
+ Children[14] = PDEF_PTR(55);
+ Children[15] = PDEF_PTR(56);
+ Children[16] = PDEF_PTR(57);
+ Children[17] = PDEF_PTR(58);
+ Children[18] = PDEF_PTR(59);
+
+ ParamDefTable[0].setChildren(Children, 19);
+ }
+
+ // SetChildren for: nodeIndex=1, longName="physicalMeshes"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(2);
+
+ ParamDefTable[1].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=3, longName="graphicalLods"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(4);
+
+ ParamDefTable[3].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=5, longName="simulation"
+ {
+ static Definition* Children[9];
+ Children[0] = PDEF_PTR(6);
+ Children[1] = PDEF_PTR(7);
+ Children[2] = PDEF_PTR(8);
+ Children[3] = PDEF_PTR(9);
+ Children[4] = PDEF_PTR(10);
+ Children[5] = PDEF_PTR(11);
+ Children[6] = PDEF_PTR(12);
+ Children[7] = PDEF_PTR(13);
+ Children[8] = PDEF_PTR(14);
+
+ ParamDefTable[5].setChildren(Children, 9);
+ }
+
+ // SetChildren for: nodeIndex=15, longName="bones"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(16);
+
+ ParamDefTable[15].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=16, longName="bones[]"
+ {
+ static Definition* Children[7];
+ Children[0] = PDEF_PTR(17);
+ Children[1] = PDEF_PTR(18);
+ Children[2] = PDEF_PTR(19);
+ Children[3] = PDEF_PTR(20);
+ Children[4] = PDEF_PTR(21);
+ Children[5] = PDEF_PTR(22);
+ Children[6] = PDEF_PTR(23);
+
+ ParamDefTable[16].setChildren(Children, 7);
+ }
+
+ // SetChildren for: nodeIndex=27, longName="boneActors"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(28);
+
+ ParamDefTable[27].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=28, longName="boneActors[]"
+ {
+ static Definition* Children[6];
+ Children[0] = PDEF_PTR(29);
+ Children[1] = PDEF_PTR(30);
+ Children[2] = PDEF_PTR(31);
+ Children[3] = PDEF_PTR(32);
+ Children[4] = PDEF_PTR(33);
+ Children[5] = PDEF_PTR(34);
+
+ ParamDefTable[28].setChildren(Children, 6);
+ }
+
+ // SetChildren for: nodeIndex=35, longName="boneVertices"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(36);
+
+ ParamDefTable[35].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=37, longName="boneSpheres"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(38);
+
+ ParamDefTable[37].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=38, longName="boneSpheres[]"
+ {
+ static Definition* Children[3];
+ Children[0] = PDEF_PTR(39);
+ Children[1] = PDEF_PTR(40);
+ Children[2] = PDEF_PTR(41);
+
+ ParamDefTable[38].setChildren(Children, 3);
+ }
+
+ // SetChildren for: nodeIndex=42, longName="boneSphereConnections"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(43);
+
+ ParamDefTable[42].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=44, longName="bonePlanes"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(45);
+
+ ParamDefTable[44].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=45, longName="bonePlanes[]"
+ {
+ static Definition* Children[3];
+ Children[0] = PDEF_PTR(46);
+ Children[1] = PDEF_PTR(47);
+ Children[2] = PDEF_PTR(48);
+
+ ParamDefTable[45].setChildren(Children, 3);
+ }
+
+ // SetChildren for: nodeIndex=49, longName="collisionConvexes"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(50);
+
+ ParamDefTable[49].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=51, longName="cookedData"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(52);
+
+ ParamDefTable[51].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=52, longName="cookedData[]"
+ {
+ static Definition* Children[2];
+ Children[0] = PDEF_PTR(53);
+ Children[1] = PDEF_PTR(54);
+
+ ParamDefTable[52].setChildren(Children, 2);
+ }
+
+ mBuiltFlag = true;
+
+}
+void ClothingAssetParameters::initStrings(void)
+{
+ toolString.isAllocated = true;
+ toolString.buf = NULL;
+}
+
+void ClothingAssetParameters::initDynamicArrays(void)
+{
+ physicalMeshes.buf = NULL;
+ physicalMeshes.isAllocated = true;
+ physicalMeshes.elementSize = sizeof(NvParameterized::Interface*);
+ physicalMeshes.arraySizes[0] = 0;
+ graphicalLods.buf = NULL;
+ graphicalLods.isAllocated = true;
+ graphicalLods.elementSize = sizeof(NvParameterized::Interface*);
+ graphicalLods.arraySizes[0] = 0;
+ bones.buf = NULL;
+ bones.isAllocated = true;
+ bones.elementSize = sizeof(BoneEntry_Type);
+ bones.arraySizes[0] = 0;
+ boneActors.buf = NULL;
+ boneActors.isAllocated = true;
+ boneActors.elementSize = sizeof(ActorEntry_Type);
+ boneActors.arraySizes[0] = 0;
+ boneVertices.buf = NULL;
+ boneVertices.isAllocated = true;
+ boneVertices.elementSize = sizeof(physx::PxVec3);
+ boneVertices.arraySizes[0] = 0;
+ boneSpheres.buf = NULL;
+ boneSpheres.isAllocated = true;
+ boneSpheres.elementSize = sizeof(BoneSphere_Type);
+ boneSpheres.arraySizes[0] = 0;
+ boneSphereConnections.buf = NULL;
+ boneSphereConnections.isAllocated = true;
+ boneSphereConnections.elementSize = sizeof(uint16_t);
+ boneSphereConnections.arraySizes[0] = 0;
+ bonePlanes.buf = NULL;
+ bonePlanes.isAllocated = true;
+ bonePlanes.elementSize = sizeof(BonePlane_Type);
+ bonePlanes.arraySizes[0] = 0;
+ collisionConvexes.buf = NULL;
+ collisionConvexes.isAllocated = true;
+ collisionConvexes.elementSize = sizeof(uint32_t);
+ collisionConvexes.arraySizes[0] = 0;
+ cookedData.buf = NULL;
+ cookedData.isAllocated = true;
+ cookedData.elementSize = sizeof(CookedEntry_Type);
+ cookedData.arraySizes[0] = 0;
+}
+
+void ClothingAssetParameters::initDefaults(void)
+{
+
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+ simulation.hierarchicalLevels = uint32_t(0);
+ simulation.thickness = float(0.01);
+ simulation.virtualParticleDensity = float(0.0);
+ simulation.gravityDirection = physx::PxVec3(physx::PxVec3(0.0f));
+ simulation.sleepLinearVelocity = float(0.0);
+ simulation.disableCCD = bool(false);
+ simulation.untangling = bool(false);
+ simulation.twowayInteraction = bool(false);
+ simulation.restLengthScale = float(1.0);
+ bonesReferenced = uint32_t(0);
+ bonesReferencedByMesh = uint32_t(0);
+ rootBoneIndex = uint32_t(0);
+ boundingBox = physx::PxBounds3(physx::PxVec3(0.0f), physx::PxVec3(0.0f));
+ materialIndex = uint32_t(0);
+ interCollisionChannels = uint32_t(0);
+
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+}
+
+void ClothingAssetParameters::initReferences(void)
+{
+ materialLibrary = NULL;
+
+}
+
+void ClothingAssetParameters::freeDynamicArrays(void)
+{
+ if (physicalMeshes.isAllocated && physicalMeshes.buf)
+ {
+ mParameterizedTraits->free(physicalMeshes.buf);
+ }
+ if (graphicalLods.isAllocated && graphicalLods.buf)
+ {
+ mParameterizedTraits->free(graphicalLods.buf);
+ }
+ if (bones.isAllocated && bones.buf)
+ {
+ mParameterizedTraits->free(bones.buf);
+ }
+ if (boneActors.isAllocated && boneActors.buf)
+ {
+ mParameterizedTraits->free(boneActors.buf);
+ }
+ if (boneVertices.isAllocated && boneVertices.buf)
+ {
+ mParameterizedTraits->free(boneVertices.buf);
+ }
+ if (boneSpheres.isAllocated && boneSpheres.buf)
+ {
+ mParameterizedTraits->free(boneSpheres.buf);
+ }
+ if (boneSphereConnections.isAllocated && boneSphereConnections.buf)
+ {
+ mParameterizedTraits->free(boneSphereConnections.buf);
+ }
+ if (bonePlanes.isAllocated && bonePlanes.buf)
+ {
+ mParameterizedTraits->free(bonePlanes.buf);
+ }
+ if (collisionConvexes.isAllocated && collisionConvexes.buf)
+ {
+ mParameterizedTraits->free(collisionConvexes.buf);
+ }
+ if (cookedData.isAllocated && cookedData.buf)
+ {
+ mParameterizedTraits->free(cookedData.buf);
+ }
+}
+
+void ClothingAssetParameters::freeStrings(void)
+{
+
+ for (int i = 0; i < bones.arraySizes[0]; ++i)
+ {
+ if (bones.buf[i].name.isAllocated && bones.buf[i].name.buf)
+ {
+ mParameterizedTraits->strfree((char*)bones.buf[i].name.buf);
+ }
+ }
+
+ if (toolString.isAllocated && toolString.buf)
+ {
+ mParameterizedTraits->strfree((char*)toolString.buf);
+ }
+}
+
+void ClothingAssetParameters::freeReferences(void)
+{
+
+ for (int i = 0; i < physicalMeshes.arraySizes[0]; ++i)
+ {
+ if (physicalMeshes.buf[i])
+ {
+ physicalMeshes.buf[i]->destroy();
+ }
+ }
+
+ for (int i = 0; i < graphicalLods.arraySizes[0]; ++i)
+ {
+ if (graphicalLods.buf[i])
+ {
+ graphicalLods.buf[i]->destroy();
+ }
+ }
+
+ for (int i = 0; i < cookedData.arraySizes[0]; i++)
+ {
+ if (cookedData.buf[i].cookedData)
+ {
+ cookedData.buf[i].cookedData->destroy();
+ }
+ }
+ if (materialLibrary)
+ {
+ materialLibrary->destroy();
+ }
+
+}
+
+} // namespace clothing
+} // namespace nvidia
diff --git a/APEX_1.4/module/clothing/src/autogen/ClothingCookedParam.cpp b/APEX_1.4/module/clothing/src/autogen/ClothingCookedParam.cpp
new file mode 100644
index 00000000..9a7b91ee
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/autogen/ClothingCookedParam.cpp
@@ -0,0 +1,970 @@
+// 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-2015 NVIDIA Corporation. All rights reserved.
+
+// This file was generated by NvParameterized/scripts/GenParameterized.pl
+
+
+#include "ClothingCookedParam.h"
+#include <string.h>
+#include <stdlib.h>
+
+using namespace NvParameterized;
+
+namespace nvidia
+{
+namespace clothing
+{
+
+using namespace ClothingCookedParamNS;
+
+const char* const ClothingCookedParamFactory::vptr =
+ NvParameterized::getVptr<ClothingCookedParam, ClothingCookedParam::ClassAlignment>();
+
+const uint32_t NumParamDefs = 24;
+static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs];
+
+
+static const size_t ParamLookupChildrenTable[] =
+{
+ 1, 2, 4, 6, 15, 17, 18, 20, 22, 3, 5, 7, 8, 9, 10, 11, 12, 13, 14, 16, 19, 21, 23,
+};
+
+#define TENUM(type) nvidia::##type
+#define CHILDREN(index) &ParamLookupChildrenTable[index]
+static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] =
+{
+ { TYPE_STRUCT, false, 0, CHILDREN(0), 9 },
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->actorScale), NULL, 0 }, // actorScale
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->convexCookedData), CHILDREN(9), 1 }, // convexCookedData
+ { TYPE_U8, false, 1 * sizeof(uint8_t), NULL, 0 }, // convexCookedData[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->convexMeshPointers), CHILDREN(10), 1 }, // convexMeshPointers
+ { TYPE_POINTER, false, 1 * sizeof(void*), NULL, 0 }, // convexMeshPointers[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->cookedPhysicalMeshes), CHILDREN(11), 1 }, // cookedPhysicalMeshes
+ { TYPE_STRUCT, false, 1 * sizeof(CookedPhysicalMesh_Type), CHILDREN(12), 7 }, // cookedPhysicalMeshes[]
+ { TYPE_U32, false, (size_t)(&((CookedPhysicalMesh_Type*)0)->physicalMeshId), NULL, 0 }, // cookedPhysicalMeshes[].physicalMeshId
+ { TYPE_U32, false, (size_t)(&((CookedPhysicalMesh_Type*)0)->cookedDataOffset), NULL, 0 }, // cookedPhysicalMeshes[].cookedDataOffset
+ { TYPE_U32, false, (size_t)(&((CookedPhysicalMesh_Type*)0)->cookedDataLength), NULL, 0 }, // cookedPhysicalMeshes[].cookedDataLength
+ { TYPE_POINTER, false, (size_t)(&((CookedPhysicalMesh_Type*)0)->deformableMeshPointer), NULL, 0 }, // cookedPhysicalMeshes[].deformableMeshPointer
+ { TYPE_U32, false, (size_t)(&((CookedPhysicalMesh_Type*)0)->deformableInvParticleWeightsOffset), NULL, 0 }, // cookedPhysicalMeshes[].deformableInvParticleWeightsOffset
+ { TYPE_U32, false, (size_t)(&((CookedPhysicalMesh_Type*)0)->virtualParticleIndicesOffset), NULL, 0 }, // cookedPhysicalMeshes[].virtualParticleIndicesOffset
+ { TYPE_U32, false, (size_t)(&((CookedPhysicalMesh_Type*)0)->virtualParticleIndicesLength), NULL, 0 }, // cookedPhysicalMeshes[].virtualParticleIndicesLength
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->deformableCookedData), CHILDREN(19), 1 }, // deformableCookedData
+ { TYPE_U8, false, 1 * sizeof(uint8_t), NULL, 0 }, // deformableCookedData[]
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->cookedDataVersion), NULL, 0 }, // cookedDataVersion
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->deformableInvParticleWeights), CHILDREN(20), 1 }, // deformableInvParticleWeights
+ { TYPE_F32, false, 1 * sizeof(float), NULL, 0 }, // deformableInvParticleWeights[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->virtualParticleIndices), CHILDREN(21), 1 }, // virtualParticleIndices
+ { TYPE_U32, false, 1 * sizeof(uint32_t), NULL, 0 }, // virtualParticleIndices[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->virtualParticleWeights), CHILDREN(22), 1 }, // virtualParticleWeights
+ { TYPE_VEC3, false, 1 * sizeof(physx::PxVec3), NULL, 0 }, // virtualParticleWeights[]
+};
+
+
+bool ClothingCookedParam::mBuiltFlag = false;
+NvParameterized::MutexType ClothingCookedParam::mBuiltFlagMutex;
+
+ClothingCookedParam::ClothingCookedParam(NvParameterized::Traits* traits, void* buf, int32_t* refCount) :
+ NvParameters(traits, buf, refCount)
+{
+ //mParameterizedTraits->registerFactory(className(), &ClothingCookedParamFactoryInst);
+
+ if (!buf) //Do not init data if it is inplace-deserialized
+ {
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+ initDefaults();
+ }
+}
+
+ClothingCookedParam::~ClothingCookedParam()
+{
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+}
+
+void ClothingCookedParam::destroy()
+{
+ // We cache these fields here to avoid overwrite in destructor
+ bool doDeallocateSelf = mDoDeallocateSelf;
+ NvParameterized::Traits* traits = mParameterizedTraits;
+ int32_t* refCount = mRefCount;
+ void* buf = mBuffer;
+
+ this->~ClothingCookedParam();
+
+ NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf);
+}
+
+const NvParameterized::DefinitionImpl* ClothingCookedParam::getParameterDefinitionTree(void)
+{
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+const NvParameterized::DefinitionImpl* ClothingCookedParam::getParameterDefinitionTree(void) const
+{
+ ClothingCookedParam* tmpParam = const_cast<ClothingCookedParam*>(this);
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ tmpParam->buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+NvParameterized::ErrorType ClothingCookedParam::getParameterHandle(const char* long_name, Handle& handle) const
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+NvParameterized::ErrorType ClothingCookedParam::getParameterHandle(const char* long_name, Handle& handle)
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+void ClothingCookedParam::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const
+{
+ ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<ClothingCookedParam::ParametersStruct*>(&parameters()), handle, offset);
+}
+
+
+/* Dynamic Handle Indices */
+
+void ClothingCookedParam::freeParameterDefinitionTable(NvParameterized::Traits* traits)
+{
+ if (!traits)
+ {
+ return;
+ }
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ return;
+ }
+
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+
+ if (!mBuiltFlag)
+ {
+ return;
+ }
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ ParamDefTable[i].~DefinitionImpl();
+ }
+
+ traits->free(ParamDefTable);
+
+ mBuiltFlag = false;
+}
+
+#define PDEF_PTR(index) (&ParamDefTable[index])
+
+void ClothingCookedParam::buildTree(void)
+{
+
+ uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs;
+ ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize));
+ memset(ParamDefTable, 0, allocSize);
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=0, longName=""
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0];
+ ParamDef->init("", TYPE_STRUCT, "STRUCT", true);
+
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=1, longName="actorScale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1];
+ ParamDef->init("actorScale", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Actor scale", true);
+ ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=2, longName="convexCookedData"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2];
+ ParamDef->init("convexCookedData", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "All convexes are checked into the same buffer, one after the other.\n", true);
+ HintTable[1].init("shortDescription", "The cooked data for all the convex meshes.", true);
+ ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=3, longName="convexCookedData[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3];
+ ParamDef->init("convexCookedData", TYPE_U8, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "All convexes are checked into the same buffer, one after the other.\n", true);
+ HintTable[1].init("shortDescription", "The cooked data for all the convex meshes.", true);
+ ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=4, longName="convexMeshPointers"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4];
+ ParamDef->init("convexMeshPointers", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Convex mesh pointers", true);
+ ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=5, longName="convexMeshPointers[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5];
+ ParamDef->init("convexMeshPointers", TYPE_POINTER, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Convex mesh pointers", true);
+ ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=6, longName="cookedPhysicalMeshes"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6];
+ ParamDef->init("cookedPhysicalMeshes", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Cooked physical meshes", true);
+ ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=7, longName="cookedPhysicalMeshes[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7];
+ ParamDef->init("cookedPhysicalMeshes", TYPE_STRUCT, "CookedPhysicalMesh", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Cooked physical meshes", true);
+ ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=8, longName="cookedPhysicalMeshes[].physicalMeshId"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8];
+ ParamDef->init("physicalMeshId", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Physical mesh ID", true);
+ ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=9, longName="cookedPhysicalMeshes[].cookedDataOffset"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9];
+ ParamDef->init("cookedDataOffset", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Cooked data offset", true);
+ ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=10, longName="cookedPhysicalMeshes[].cookedDataLength"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[10];
+ ParamDef->init("cookedDataLength", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Cooked data length", true);
+ ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=11, longName="cookedPhysicalMeshes[].deformableMeshPointer"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[11];
+ ParamDef->init("deformableMeshPointer", TYPE_POINTER, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Deformable mesh pointer", true);
+ ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=12, longName="cookedPhysicalMeshes[].deformableInvParticleWeightsOffset"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[12];
+ ParamDef->init("deformableInvParticleWeightsOffset", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable inverse particle weights offset", true);
+ ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=13, longName="cookedPhysicalMeshes[].virtualParticleIndicesOffset"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[13];
+ ParamDef->init("virtualParticleIndicesOffset", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Virtual particle indices offset", true);
+ ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=14, longName="cookedPhysicalMeshes[].virtualParticleIndicesLength"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[14];
+ ParamDef->init("virtualParticleIndicesLength", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Virtual particle indices length", true);
+ ParamDefTable[14].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=15, longName="deformableCookedData"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[15];
+ ParamDef->init("deformableCookedData", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable cooked data", true);
+ ParamDefTable[15].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=16, longName="deformableCookedData[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[16];
+ ParamDef->init("deformableCookedData", TYPE_U8, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable cooked data", true);
+ ParamDefTable[16].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=17, longName="cookedDataVersion"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[17];
+ ParamDef->init("cookedDataVersion", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "When loading into a different PhysX version, it will cook again on loading.", true);
+ HintTable[1].init("shortDescription", "The PhysX SDK Version this data was cooked from", true);
+ ParamDefTable[17].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=18, longName="deformableInvParticleWeights"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[18];
+ ParamDef->init("deformableInvParticleWeights", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable inverse particle weights", true);
+ ParamDefTable[18].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=19, longName="deformableInvParticleWeights[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[19];
+ ParamDef->init("deformableInvParticleWeights", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable inverse particle weights", true);
+ ParamDefTable[19].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=20, longName="virtualParticleIndices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[20];
+ ParamDef->init("virtualParticleIndices", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Virtual particle indices", true);
+ ParamDefTable[20].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=21, longName="virtualParticleIndices[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[21];
+ ParamDef->init("virtualParticleIndices", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Virtual particle indices", true);
+ ParamDefTable[21].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=22, longName="virtualParticleWeights"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[22];
+ ParamDef->init("virtualParticleWeights", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Virtual particle weights", true);
+ ParamDefTable[22].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=23, longName="virtualParticleWeights[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[23];
+ ParamDef->init("virtualParticleWeights", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Virtual particle weights", true);
+ ParamDefTable[23].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // SetChildren for: nodeIndex=0, longName=""
+ {
+ static Definition* Children[9];
+ Children[0] = PDEF_PTR(1);
+ Children[1] = PDEF_PTR(2);
+ Children[2] = PDEF_PTR(4);
+ Children[3] = PDEF_PTR(6);
+ Children[4] = PDEF_PTR(15);
+ Children[5] = PDEF_PTR(17);
+ Children[6] = PDEF_PTR(18);
+ Children[7] = PDEF_PTR(20);
+ Children[8] = PDEF_PTR(22);
+
+ ParamDefTable[0].setChildren(Children, 9);
+ }
+
+ // SetChildren for: nodeIndex=2, longName="convexCookedData"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(3);
+
+ ParamDefTable[2].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=4, longName="convexMeshPointers"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(5);
+
+ ParamDefTable[4].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=6, longName="cookedPhysicalMeshes"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(7);
+
+ ParamDefTable[6].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=7, longName="cookedPhysicalMeshes[]"
+ {
+ static Definition* Children[7];
+ Children[0] = PDEF_PTR(8);
+ Children[1] = PDEF_PTR(9);
+ Children[2] = PDEF_PTR(10);
+ Children[3] = PDEF_PTR(11);
+ Children[4] = PDEF_PTR(12);
+ Children[5] = PDEF_PTR(13);
+ Children[6] = PDEF_PTR(14);
+
+ ParamDefTable[7].setChildren(Children, 7);
+ }
+
+ // SetChildren for: nodeIndex=15, longName="deformableCookedData"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(16);
+
+ ParamDefTable[15].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=18, longName="deformableInvParticleWeights"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(19);
+
+ ParamDefTable[18].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=20, longName="virtualParticleIndices"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(21);
+
+ ParamDefTable[20].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=22, longName="virtualParticleWeights"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(23);
+
+ ParamDefTable[22].setChildren(Children, 1);
+ }
+
+ mBuiltFlag = true;
+
+}
+void ClothingCookedParam::initStrings(void)
+{
+}
+
+void ClothingCookedParam::initDynamicArrays(void)
+{
+ convexCookedData.buf = NULL;
+ convexCookedData.isAllocated = true;
+ convexCookedData.elementSize = sizeof(uint8_t);
+ convexCookedData.arraySizes[0] = 0;
+ convexMeshPointers.buf = NULL;
+ convexMeshPointers.isAllocated = true;
+ convexMeshPointers.elementSize = sizeof(void*);
+ convexMeshPointers.arraySizes[0] = 0;
+ cookedPhysicalMeshes.buf = NULL;
+ cookedPhysicalMeshes.isAllocated = true;
+ cookedPhysicalMeshes.elementSize = sizeof(CookedPhysicalMesh_Type);
+ cookedPhysicalMeshes.arraySizes[0] = 0;
+ deformableCookedData.buf = NULL;
+ deformableCookedData.isAllocated = true;
+ deformableCookedData.elementSize = sizeof(uint8_t);
+ deformableCookedData.arraySizes[0] = 0;
+ deformableInvParticleWeights.buf = NULL;
+ deformableInvParticleWeights.isAllocated = true;
+ deformableInvParticleWeights.elementSize = sizeof(float);
+ deformableInvParticleWeights.arraySizes[0] = 0;
+ virtualParticleIndices.buf = NULL;
+ virtualParticleIndices.isAllocated = true;
+ virtualParticleIndices.elementSize = sizeof(uint32_t);
+ virtualParticleIndices.arraySizes[0] = 0;
+ virtualParticleWeights.buf = NULL;
+ virtualParticleWeights.isAllocated = true;
+ virtualParticleWeights.elementSize = sizeof(physx::PxVec3);
+ virtualParticleWeights.arraySizes[0] = 0;
+}
+
+void ClothingCookedParam::initDefaults(void)
+{
+
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+ actorScale = float(1.0f);
+ cookedDataVersion = uint32_t(0);
+
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+}
+
+void ClothingCookedParam::initReferences(void)
+{
+}
+
+void ClothingCookedParam::freeDynamicArrays(void)
+{
+ if (convexCookedData.isAllocated && convexCookedData.buf)
+ {
+ mParameterizedTraits->free(convexCookedData.buf);
+ }
+ if (convexMeshPointers.isAllocated && convexMeshPointers.buf)
+ {
+ mParameterizedTraits->free(convexMeshPointers.buf);
+ }
+ if (cookedPhysicalMeshes.isAllocated && cookedPhysicalMeshes.buf)
+ {
+ mParameterizedTraits->free(cookedPhysicalMeshes.buf);
+ }
+ if (deformableCookedData.isAllocated && deformableCookedData.buf)
+ {
+ mParameterizedTraits->free(deformableCookedData.buf);
+ }
+ if (deformableInvParticleWeights.isAllocated && deformableInvParticleWeights.buf)
+ {
+ mParameterizedTraits->free(deformableInvParticleWeights.buf);
+ }
+ if (virtualParticleIndices.isAllocated && virtualParticleIndices.buf)
+ {
+ mParameterizedTraits->free(virtualParticleIndices.buf);
+ }
+ if (virtualParticleWeights.isAllocated && virtualParticleWeights.buf)
+ {
+ mParameterizedTraits->free(virtualParticleWeights.buf);
+ }
+}
+
+void ClothingCookedParam::freeStrings(void)
+{
+}
+
+void ClothingCookedParam::freeReferences(void)
+{
+}
+
+} // namespace clothing
+} // namespace nvidia
diff --git a/APEX_1.4/module/clothing/src/autogen/ClothingCookedPhysX3Param.cpp b/APEX_1.4/module/clothing/src/autogen/ClothingCookedPhysX3Param.cpp
new file mode 100644
index 00000000..7e01986e
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/autogen/ClothingCookedPhysX3Param.cpp
@@ -0,0 +1,1557 @@
+// 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-2015 NVIDIA Corporation. All rights reserved.
+
+// This file was generated by NvParameterized/scripts/GenParameterized.pl
+
+
+#include "ClothingCookedPhysX3Param.h"
+#include <string.h>
+#include <stdlib.h>
+
+using namespace NvParameterized;
+
+namespace nvidia
+{
+namespace clothing
+{
+
+using namespace ClothingCookedPhysX3ParamNS;
+
+const char* const ClothingCookedPhysX3ParamFactory::vptr =
+ NvParameterized::getVptr<ClothingCookedPhysX3Param, ClothingCookedPhysX3Param::ClassAlignment>();
+
+const uint32_t NumParamDefs = 43;
+static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs];
+
+
+static const size_t ParamLookupChildrenTable[] =
+{
+ 1, 2, 3, 5, 7, 9, 11, 13, 21, 26, 28, 30, 32, 34, 36, 37, 38, 42, 4, 6, 8, 10, 12,
+ 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 27, 29, 31, 33, 35, 39, 40, 41,
+};
+
+#define TENUM(type) nvidia::##type
+#define CHILDREN(index) &ParamLookupChildrenTable[index]
+static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] =
+{
+ { TYPE_STRUCT, false, 0, CHILDREN(0), 18 },
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->physicalMeshId), NULL, 0 }, // physicalMeshId
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->numVertices), NULL, 0 }, // numVertices
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->deformableRestLengths), CHILDREN(18), 1 }, // deformableRestLengths
+ { TYPE_F32, false, 1 * sizeof(float), NULL, 0 }, // deformableRestLengths[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->deformableIndices), CHILDREN(19), 1 }, // deformableIndices
+ { TYPE_U32, false, 1 * sizeof(uint32_t), NULL, 0 }, // deformableIndices[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->selfCollisionIndices), CHILDREN(20), 1 }, // selfCollisionIndices
+ { TYPE_U32, false, 1 * sizeof(uint32_t), NULL, 0 }, // selfCollisionIndices[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->selfCollisionNormalIndices), CHILDREN(21), 1 }, // selfCollisionNormalIndices
+ { TYPE_U32, false, 1 * sizeof(uint32_t), NULL, 0 }, // selfCollisionNormalIndices[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->selfCollisionNormalSetSizes), CHILDREN(22), 1 }, // selfCollisionNormalSetSizes
+ { TYPE_U32, false, 1 * sizeof(uint32_t), NULL, 0 }, // selfCollisionNormalSetSizes[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->deformableSets), CHILDREN(23), 1 }, // deformableSets
+ { TYPE_STRUCT, false, 1 * sizeof(SetDesc_Type), CHILDREN(24), 6 }, // deformableSets[]
+ { TYPE_U32, false, (size_t)(&((SetDesc_Type*)0)->fiberEnd), NULL, 0 }, // deformableSets[].fiberEnd
+ { TYPE_U32, false, (size_t)(&((SetDesc_Type*)0)->longestFiber), NULL, 0 }, // deformableSets[].longestFiber
+ { TYPE_U32, false, (size_t)(&((SetDesc_Type*)0)->shortestFiber), NULL, 0 }, // deformableSets[].shortestFiber
+ { TYPE_U32, false, (size_t)(&((SetDesc_Type*)0)->numEdges), NULL, 0 }, // deformableSets[].numEdges
+ { TYPE_F32, false, (size_t)(&((SetDesc_Type*)0)->avgEdgeLength), NULL, 0 }, // deformableSets[].avgEdgeLength
+ { TYPE_U32, false, (size_t)(&((SetDesc_Type*)0)->avgFiberLength), NULL, 0 }, // deformableSets[].avgFiberLength
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->deformablePhaseDescs), CHILDREN(30), 1 }, // deformablePhaseDescs
+ { TYPE_STRUCT, false, 1 * sizeof(PhaseDesc_Type), CHILDREN(31), 3 }, // deformablePhaseDescs[]
+ { TYPE_U32, false, (size_t)(&((PhaseDesc_Type*)0)->phaseType), NULL, 0 }, // deformablePhaseDescs[].phaseType
+ { TYPE_U32, false, (size_t)(&((PhaseDesc_Type*)0)->setIndex), NULL, 0 }, // deformablePhaseDescs[].setIndex
+ { TYPE_U32, false, (size_t)(&((PhaseDesc_Type*)0)->restValueOffset), NULL, 0 }, // deformablePhaseDescs[].restValueOffset
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->tetherAnchors), CHILDREN(34), 1 }, // tetherAnchors
+ { TYPE_U32, false, 1 * sizeof(uint32_t), NULL, 0 }, // tetherAnchors[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->tetherLengths), CHILDREN(35), 1 }, // tetherLengths
+ { TYPE_F32, false, 1 * sizeof(float), NULL, 0 }, // tetherLengths[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->deformableInvVertexWeights), CHILDREN(36), 1 }, // deformableInvVertexWeights
+ { TYPE_F32, false, 1 * sizeof(float), NULL, 0 }, // deformableInvVertexWeights[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->virtualParticleIndices), CHILDREN(37), 1 }, // virtualParticleIndices
+ { TYPE_U32, false, 1 * sizeof(uint32_t), NULL, 0 }, // virtualParticleIndices[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->virtualParticleWeights), CHILDREN(38), 1 }, // virtualParticleWeights
+ { TYPE_F32, false, 1 * sizeof(float), NULL, 0 }, // virtualParticleWeights[]
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->cookedDataVersion), NULL, 0 }, // cookedDataVersion
+ { TYPE_POINTER, false, (size_t)(&((ParametersStruct*)0)->fabricCPU), NULL, 0 }, // fabricCPU
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->fabricGPU), CHILDREN(39), 1 }, // fabricGPU
+ { TYPE_STRUCT, false, 1 * sizeof(FabricGPU_Type), CHILDREN(40), 2 }, // fabricGPU[]
+ { TYPE_POINTER, false, (size_t)(&((FabricGPU_Type*)0)->fabricGPU), NULL, 0 }, // fabricGPU[].fabricGPU
+ { TYPE_POINTER, false, (size_t)(&((FabricGPU_Type*)0)->factory), NULL, 0 }, // fabricGPU[].factory
+ { TYPE_REF, false, (size_t)(&((ParametersStruct*)0)->nextCookedData), NULL, 0 }, // nextCookedData
+};
+
+
+bool ClothingCookedPhysX3Param::mBuiltFlag = false;
+NvParameterized::MutexType ClothingCookedPhysX3Param::mBuiltFlagMutex;
+
+ClothingCookedPhysX3Param::ClothingCookedPhysX3Param(NvParameterized::Traits* traits, void* buf, int32_t* refCount) :
+ NvParameters(traits, buf, refCount)
+{
+ //mParameterizedTraits->registerFactory(className(), &ClothingCookedPhysX3ParamFactoryInst);
+
+ if (!buf) //Do not init data if it is inplace-deserialized
+ {
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+ initDefaults();
+ }
+}
+
+ClothingCookedPhysX3Param::~ClothingCookedPhysX3Param()
+{
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+}
+
+void ClothingCookedPhysX3Param::destroy()
+{
+ // We cache these fields here to avoid overwrite in destructor
+ bool doDeallocateSelf = mDoDeallocateSelf;
+ NvParameterized::Traits* traits = mParameterizedTraits;
+ int32_t* refCount = mRefCount;
+ void* buf = mBuffer;
+
+ this->~ClothingCookedPhysX3Param();
+
+ NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf);
+}
+
+const NvParameterized::DefinitionImpl* ClothingCookedPhysX3Param::getParameterDefinitionTree(void)
+{
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+const NvParameterized::DefinitionImpl* ClothingCookedPhysX3Param::getParameterDefinitionTree(void) const
+{
+ ClothingCookedPhysX3Param* tmpParam = const_cast<ClothingCookedPhysX3Param*>(this);
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ tmpParam->buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+NvParameterized::ErrorType ClothingCookedPhysX3Param::getParameterHandle(const char* long_name, Handle& handle) const
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+NvParameterized::ErrorType ClothingCookedPhysX3Param::getParameterHandle(const char* long_name, Handle& handle)
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+void ClothingCookedPhysX3Param::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const
+{
+ ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<ClothingCookedPhysX3Param::ParametersStruct*>(&parameters()), handle, offset);
+}
+
+
+/* Dynamic Handle Indices */
+
+void ClothingCookedPhysX3Param::freeParameterDefinitionTable(NvParameterized::Traits* traits)
+{
+ if (!traits)
+ {
+ return;
+ }
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ return;
+ }
+
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+
+ if (!mBuiltFlag)
+ {
+ return;
+ }
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ ParamDefTable[i].~DefinitionImpl();
+ }
+
+ traits->free(ParamDefTable);
+
+ mBuiltFlag = false;
+}
+
+#define PDEF_PTR(index) (&ParamDefTable[index])
+
+void ClothingCookedPhysX3Param::buildTree(void)
+{
+
+ uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs;
+ ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize));
+ memset(ParamDefTable, 0, allocSize);
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=0, longName=""
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0];
+ ParamDef->init("", TYPE_STRUCT, "STRUCT", true);
+
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=1, longName="physicalMeshId"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1];
+ ParamDef->init("physicalMeshId", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Physical mesh ID", true);
+ ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=2, longName="numVertices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2];
+ ParamDef->init("numVertices", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Vertex count", true);
+ ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=3, longName="deformableRestLengths"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3];
+ ParamDef->init("deformableRestLengths", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable rest lengths", true);
+ ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=4, longName="deformableRestLengths[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4];
+ ParamDef->init("deformableRestLengths", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable rest lengths", true);
+ ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=5, longName="deformableIndices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5];
+ ParamDef->init("deformableIndices", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable indices", true);
+ ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=6, longName="deformableIndices[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6];
+ ParamDef->init("deformableIndices", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable indices", true);
+ ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=7, longName="selfCollisionIndices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7];
+ ParamDef->init("selfCollisionIndices", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Self collision indices", true);
+ ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=8, longName="selfCollisionIndices[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8];
+ ParamDef->init("selfCollisionIndices", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Self collision indices", true);
+ ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=9, longName="selfCollisionNormalIndices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9];
+ ParamDef->init("selfCollisionNormalIndices", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Self collision normal indices", true);
+ ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=10, longName="selfCollisionNormalIndices[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[10];
+ ParamDef->init("selfCollisionNormalIndices", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Self collision normal indices", true);
+ ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=11, longName="selfCollisionNormalSetSizes"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[11];
+ ParamDef->init("selfCollisionNormalSetSizes", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Self collision normal set sizes", true);
+ ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=12, longName="selfCollisionNormalSetSizes[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[12];
+ ParamDef->init("selfCollisionNormalSetSizes", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Self collision normal set sizes", true);
+ ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=13, longName="deformableSets"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[13];
+ ParamDef->init("deformableSets", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable sets", true);
+ ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=14, longName="deformableSets[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[14];
+ ParamDef->init("deformableSets", TYPE_STRUCT, "SetDesc", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable sets", true);
+ ParamDefTable[14].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=15, longName="deformableSets[].fiberEnd"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[15];
+ ParamDef->init("fiberEnd", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Fiber end", true);
+ ParamDefTable[15].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=16, longName="deformableSets[].longestFiber"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[16];
+ ParamDef->init("longestFiber", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Longest fiber", true);
+ ParamDefTable[16].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=17, longName="deformableSets[].shortestFiber"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[17];
+ ParamDef->init("shortestFiber", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Shortest fiber", true);
+ ParamDefTable[17].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=18, longName="deformableSets[].numEdges"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[18];
+ ParamDef->init("numEdges", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Edge count", true);
+ ParamDefTable[18].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=19, longName="deformableSets[].avgEdgeLength"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[19];
+ ParamDef->init("avgEdgeLength", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Average edge length", true);
+ ParamDefTable[19].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=20, longName="deformableSets[].avgFiberLength"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[20];
+ ParamDef->init("avgFiberLength", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Average fiber length", true);
+ ParamDefTable[20].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=21, longName="deformablePhaseDescs"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[21];
+ ParamDef->init("deformablePhaseDescs", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable phase descriptions", true);
+ ParamDefTable[21].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=22, longName="deformablePhaseDescs[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[22];
+ ParamDef->init("deformablePhaseDescs", TYPE_STRUCT, "PhaseDesc", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable phase descriptions", true);
+ ParamDefTable[22].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=23, longName="deformablePhaseDescs[].phaseType"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[23];
+ ParamDef->init("phaseType", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Phase type", true);
+ ParamDefTable[23].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=24, longName="deformablePhaseDescs[].setIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[24];
+ ParamDef->init("setIndex", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Set index", true);
+ ParamDefTable[24].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=25, longName="deformablePhaseDescs[].restValueOffset"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[25];
+ ParamDef->init("restValueOffset", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Rest value offset", true);
+ ParamDefTable[25].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=26, longName="tetherAnchors"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[26];
+ ParamDef->init("tetherAnchors", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Tether anchors", true);
+ ParamDefTable[26].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=27, longName="tetherAnchors[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[27];
+ ParamDef->init("tetherAnchors", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Tether anchors", true);
+ ParamDefTable[27].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=28, longName="tetherLengths"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[28];
+ ParamDef->init("tetherLengths", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Tether lengths", true);
+ ParamDefTable[28].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=29, longName="tetherLengths[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[29];
+ ParamDef->init("tetherLengths", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Tether lengths", true);
+ ParamDefTable[29].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=30, longName="deformableInvVertexWeights"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[30];
+ ParamDef->init("deformableInvVertexWeights", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable inverse vertex weights", true);
+ ParamDefTable[30].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=31, longName="deformableInvVertexWeights[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[31];
+ ParamDef->init("deformableInvVertexWeights", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Deformable inverse vertex weights", true);
+ ParamDefTable[31].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=32, longName="virtualParticleIndices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[32];
+ ParamDef->init("virtualParticleIndices", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Virtual particle indices", true);
+ ParamDefTable[32].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=33, longName="virtualParticleIndices[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[33];
+ ParamDef->init("virtualParticleIndices", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Virtual particle indices", true);
+ ParamDefTable[33].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=34, longName="virtualParticleWeights"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[34];
+ ParamDef->init("virtualParticleWeights", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Virtual particle weights", true);
+ ParamDefTable[34].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=35, longName="virtualParticleWeights[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[35];
+ ParamDef->init("virtualParticleWeights", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Virtual particle weights", true);
+ ParamDefTable[35].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=36, longName="cookedDataVersion"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[36];
+ ParamDef->init("cookedDataVersion", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Cooked data version", true);
+ ParamDefTable[36].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=37, longName="fabricCPU"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[37];
+ ParamDef->init("fabricCPU", TYPE_POINTER, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ ParamDefTable[37].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Fabric CPU pointer", true);
+ ParamDefTable[37].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=38, longName="fabricGPU"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[38];
+ ParamDef->init("fabricGPU", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ ParamDefTable[38].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Fabric GPU array", true);
+ ParamDefTable[38].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=39, longName="fabricGPU[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[39];
+ ParamDef->init("fabricGPU", TYPE_STRUCT, "FabricGPU", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ ParamDefTable[39].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Fabric GPU array", true);
+ ParamDefTable[39].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=40, longName="fabricGPU[].fabricGPU"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[40];
+ ParamDef->init("fabricGPU", TYPE_POINTER, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ ParamDefTable[40].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Runtime pointer to shared fabric.", true);
+ ParamDefTable[40].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=41, longName="fabricGPU[].factory"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[41];
+ ParamDef->init("factory", TYPE_POINTER, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ ParamDefTable[41].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Runtime pointer to the factory the fabric has been created with.", true);
+ ParamDefTable[41].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=42, longName="nextCookedData"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[42];
+ ParamDef->init("nextCookedData", TYPE_REF, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ ParamDefTable[42].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Daisy-chain together multiple cooked data objects", true);
+ ParamDefTable[42].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+ static const char* const RefVariantVals[] = { "ClothingCookedPhysX3Param" };
+ ParamDefTable[42].setRefVariantVals((const char**)RefVariantVals, 1);
+
+
+
+ }
+
+ // SetChildren for: nodeIndex=0, longName=""
+ {
+ static Definition* Children[18];
+ Children[0] = PDEF_PTR(1);
+ Children[1] = PDEF_PTR(2);
+ Children[2] = PDEF_PTR(3);
+ Children[3] = PDEF_PTR(5);
+ Children[4] = PDEF_PTR(7);
+ Children[5] = PDEF_PTR(9);
+ Children[6] = PDEF_PTR(11);
+ Children[7] = PDEF_PTR(13);
+ Children[8] = PDEF_PTR(21);
+ Children[9] = PDEF_PTR(26);
+ Children[10] = PDEF_PTR(28);
+ Children[11] = PDEF_PTR(30);
+ Children[12] = PDEF_PTR(32);
+ Children[13] = PDEF_PTR(34);
+ Children[14] = PDEF_PTR(36);
+ Children[15] = PDEF_PTR(37);
+ Children[16] = PDEF_PTR(38);
+ Children[17] = PDEF_PTR(42);
+
+ ParamDefTable[0].setChildren(Children, 18);
+ }
+
+ // SetChildren for: nodeIndex=3, longName="deformableRestLengths"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(4);
+
+ ParamDefTable[3].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=5, longName="deformableIndices"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(6);
+
+ ParamDefTable[5].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=7, longName="selfCollisionIndices"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(8);
+
+ ParamDefTable[7].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=9, longName="selfCollisionNormalIndices"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(10);
+
+ ParamDefTable[9].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=11, longName="selfCollisionNormalSetSizes"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(12);
+
+ ParamDefTable[11].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=13, longName="deformableSets"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(14);
+
+ ParamDefTable[13].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=14, longName="deformableSets[]"
+ {
+ static Definition* Children[6];
+ Children[0] = PDEF_PTR(15);
+ Children[1] = PDEF_PTR(16);
+ Children[2] = PDEF_PTR(17);
+ Children[3] = PDEF_PTR(18);
+ Children[4] = PDEF_PTR(19);
+ Children[5] = PDEF_PTR(20);
+
+ ParamDefTable[14].setChildren(Children, 6);
+ }
+
+ // SetChildren for: nodeIndex=21, longName="deformablePhaseDescs"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(22);
+
+ ParamDefTable[21].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=22, longName="deformablePhaseDescs[]"
+ {
+ static Definition* Children[3];
+ Children[0] = PDEF_PTR(23);
+ Children[1] = PDEF_PTR(24);
+ Children[2] = PDEF_PTR(25);
+
+ ParamDefTable[22].setChildren(Children, 3);
+ }
+
+ // SetChildren for: nodeIndex=26, longName="tetherAnchors"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(27);
+
+ ParamDefTable[26].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=28, longName="tetherLengths"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(29);
+
+ ParamDefTable[28].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=30, longName="deformableInvVertexWeights"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(31);
+
+ ParamDefTable[30].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=32, longName="virtualParticleIndices"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(33);
+
+ ParamDefTable[32].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=34, longName="virtualParticleWeights"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(35);
+
+ ParamDefTable[34].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=38, longName="fabricGPU"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(39);
+
+ ParamDefTable[38].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=39, longName="fabricGPU[]"
+ {
+ static Definition* Children[2];
+ Children[0] = PDEF_PTR(40);
+ Children[1] = PDEF_PTR(41);
+
+ ParamDefTable[39].setChildren(Children, 2);
+ }
+
+ mBuiltFlag = true;
+
+}
+void ClothingCookedPhysX3Param::initStrings(void)
+{
+}
+
+void ClothingCookedPhysX3Param::initDynamicArrays(void)
+{
+ deformableRestLengths.buf = NULL;
+ deformableRestLengths.isAllocated = true;
+ deformableRestLengths.elementSize = sizeof(float);
+ deformableRestLengths.arraySizes[0] = 0;
+ deformableIndices.buf = NULL;
+ deformableIndices.isAllocated = true;
+ deformableIndices.elementSize = sizeof(uint32_t);
+ deformableIndices.arraySizes[0] = 0;
+ selfCollisionIndices.buf = NULL;
+ selfCollisionIndices.isAllocated = true;
+ selfCollisionIndices.elementSize = sizeof(uint32_t);
+ selfCollisionIndices.arraySizes[0] = 0;
+ selfCollisionNormalIndices.buf = NULL;
+ selfCollisionNormalIndices.isAllocated = true;
+ selfCollisionNormalIndices.elementSize = sizeof(uint32_t);
+ selfCollisionNormalIndices.arraySizes[0] = 0;
+ selfCollisionNormalSetSizes.buf = NULL;
+ selfCollisionNormalSetSizes.isAllocated = true;
+ selfCollisionNormalSetSizes.elementSize = sizeof(uint32_t);
+ selfCollisionNormalSetSizes.arraySizes[0] = 0;
+ deformableSets.buf = NULL;
+ deformableSets.isAllocated = true;
+ deformableSets.elementSize = sizeof(SetDesc_Type);
+ deformableSets.arraySizes[0] = 0;
+ deformablePhaseDescs.buf = NULL;
+ deformablePhaseDescs.isAllocated = true;
+ deformablePhaseDescs.elementSize = sizeof(PhaseDesc_Type);
+ deformablePhaseDescs.arraySizes[0] = 0;
+ tetherAnchors.buf = NULL;
+ tetherAnchors.isAllocated = true;
+ tetherAnchors.elementSize = sizeof(uint32_t);
+ tetherAnchors.arraySizes[0] = 0;
+ tetherLengths.buf = NULL;
+ tetherLengths.isAllocated = true;
+ tetherLengths.elementSize = sizeof(float);
+ tetherLengths.arraySizes[0] = 0;
+ deformableInvVertexWeights.buf = NULL;
+ deformableInvVertexWeights.isAllocated = true;
+ deformableInvVertexWeights.elementSize = sizeof(float);
+ deformableInvVertexWeights.arraySizes[0] = 0;
+ virtualParticleIndices.buf = NULL;
+ virtualParticleIndices.isAllocated = true;
+ virtualParticleIndices.elementSize = sizeof(uint32_t);
+ virtualParticleIndices.arraySizes[0] = 0;
+ virtualParticleWeights.buf = NULL;
+ virtualParticleWeights.isAllocated = true;
+ virtualParticleWeights.elementSize = sizeof(float);
+ virtualParticleWeights.arraySizes[0] = 0;
+ fabricGPU.buf = NULL;
+ fabricGPU.isAllocated = true;
+ fabricGPU.elementSize = sizeof(FabricGPU_Type);
+ fabricGPU.arraySizes[0] = 0;
+}
+
+void ClothingCookedPhysX3Param::initDefaults(void)
+{
+
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+ physicalMeshId = uint32_t(0);
+ numVertices = uint32_t(0);
+ cookedDataVersion = uint32_t(0);
+ fabricCPU = NULL;
+
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+}
+
+void ClothingCookedPhysX3Param::initReferences(void)
+{
+ nextCookedData = NULL;
+
+}
+
+void ClothingCookedPhysX3Param::freeDynamicArrays(void)
+{
+ if (deformableRestLengths.isAllocated && deformableRestLengths.buf)
+ {
+ mParameterizedTraits->free(deformableRestLengths.buf);
+ }
+ if (deformableIndices.isAllocated && deformableIndices.buf)
+ {
+ mParameterizedTraits->free(deformableIndices.buf);
+ }
+ if (selfCollisionIndices.isAllocated && selfCollisionIndices.buf)
+ {
+ mParameterizedTraits->free(selfCollisionIndices.buf);
+ }
+ if (selfCollisionNormalIndices.isAllocated && selfCollisionNormalIndices.buf)
+ {
+ mParameterizedTraits->free(selfCollisionNormalIndices.buf);
+ }
+ if (selfCollisionNormalSetSizes.isAllocated && selfCollisionNormalSetSizes.buf)
+ {
+ mParameterizedTraits->free(selfCollisionNormalSetSizes.buf);
+ }
+ if (deformableSets.isAllocated && deformableSets.buf)
+ {
+ mParameterizedTraits->free(deformableSets.buf);
+ }
+ if (deformablePhaseDescs.isAllocated && deformablePhaseDescs.buf)
+ {
+ mParameterizedTraits->free(deformablePhaseDescs.buf);
+ }
+ if (tetherAnchors.isAllocated && tetherAnchors.buf)
+ {
+ mParameterizedTraits->free(tetherAnchors.buf);
+ }
+ if (tetherLengths.isAllocated && tetherLengths.buf)
+ {
+ mParameterizedTraits->free(tetherLengths.buf);
+ }
+ if (deformableInvVertexWeights.isAllocated && deformableInvVertexWeights.buf)
+ {
+ mParameterizedTraits->free(deformableInvVertexWeights.buf);
+ }
+ if (virtualParticleIndices.isAllocated && virtualParticleIndices.buf)
+ {
+ mParameterizedTraits->free(virtualParticleIndices.buf);
+ }
+ if (virtualParticleWeights.isAllocated && virtualParticleWeights.buf)
+ {
+ mParameterizedTraits->free(virtualParticleWeights.buf);
+ }
+ if (fabricGPU.isAllocated && fabricGPU.buf)
+ {
+ mParameterizedTraits->free(fabricGPU.buf);
+ }
+}
+
+void ClothingCookedPhysX3Param::freeStrings(void)
+{
+}
+
+void ClothingCookedPhysX3Param::freeReferences(void)
+{
+ if (nextCookedData)
+ {
+ nextCookedData->destroy();
+ }
+
+}
+
+} // namespace clothing
+} // namespace nvidia
diff --git a/APEX_1.4/module/clothing/src/autogen/ClothingDebugRenderParams.cpp b/APEX_1.4/module/clothing/src/autogen/ClothingDebugRenderParams.cpp
new file mode 100644
index 00000000..71ceee2e
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/autogen/ClothingDebugRenderParams.cpp
@@ -0,0 +1,1327 @@
+// 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-2015 NVIDIA Corporation. All rights reserved.
+
+// This file was generated by NvParameterized/scripts/GenParameterized.pl
+
+
+#include "ClothingDebugRenderParams.h"
+#include <string.h>
+#include <stdlib.h>
+
+using namespace NvParameterized;
+
+namespace nvidia
+{
+namespace clothing
+{
+
+using namespace ClothingDebugRenderParamsNS;
+
+const char* const ClothingDebugRenderParamsFactory::vptr =
+ NvParameterized::getVptr<ClothingDebugRenderParams, ClothingDebugRenderParams::ClassAlignment>();
+
+const uint32_t NumParamDefs = 42;
+static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs];
+
+
+static const size_t ParamLookupChildrenTable[] =
+{
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+};
+
+#define TENUM(type) nvidia::##type
+#define CHILDREN(index) &ParamLookupChildrenTable[index]
+static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] =
+{
+ { TYPE_STRUCT, false, 0, CHILDREN(0), 41 },
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->Actors), NULL, 0 }, // Actors
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->SkinnedPositions), NULL, 0 }, // SkinnedPositions
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->Backstop), NULL, 0 }, // Backstop
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->BackstopPrecise), NULL, 0 }, // BackstopPrecise
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->MaxDistance), NULL, 0 }, // MaxDistance
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->MaxDistanceInwards), NULL, 0 }, // MaxDistanceInwards
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->SkinMapAll), NULL, 0 }, // SkinMapAll
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->SkinMapBad), NULL, 0 }, // SkinMapBad
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->SkinMapActual), NULL, 0 }, // SkinMapActual
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->SkinMapInvalidBary), NULL, 0 }, // SkinMapInvalidBary
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->PhysicsMeshWire), NULL, 0 }, // PhysicsMeshWire
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->PhysicsMeshSolid), NULL, 0 }, // PhysicsMeshSolid
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->PhysicsMeshNormals), NULL, 0 }, // PhysicsMeshNormals
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->Skeleton), NULL, 0 }, // Skeleton
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->BoneFrames), NULL, 0 }, // BoneFrames
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->BoneNames), NULL, 0 }, // BoneNames
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->Velocities), NULL, 0 }, // Velocities
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->Wind), NULL, 0 }, // Wind
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->GraphicalVertexBones), NULL, 0 }, // GraphicalVertexBones
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->PhysicalVertexBones), NULL, 0 }, // PhysicalVertexBones
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->CollisionShapes), NULL, 0 }, // CollisionShapes
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->CollisionShapesWire), NULL, 0 }, // CollisionShapesWire
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->LengthFibers), NULL, 0 }, // LengthFibers
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->CrossSectionFibers), NULL, 0 }, // CrossSectionFibers
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->BendingFibers), NULL, 0 }, // BendingFibers
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->ShearingFibers), NULL, 0 }, // ShearingFibers
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->ZerostretchFibers), NULL, 0 }, // ZerostretchFibers
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->TethersActive), NULL, 0 }, // TethersActive
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->TethersInactive), NULL, 0 }, // TethersInactive
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->VirtualCollision), NULL, 0 }, // VirtualCollision
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->FiberRange), NULL, 0 }, // FiberRange
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->ShowInLocalSpace), NULL, 0 }, // ShowInLocalSpace
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->GlobalPose), NULL, 0 }, // GlobalPose
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->RecomputeSubmeshes), NULL, 0 }, // RecomputeSubmeshes
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->RecomputeVertices), NULL, 0 }, // RecomputeVertices
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->PhysicsMeshIndices), NULL, 0 }, // PhysicsMeshIndices
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->MassScale), NULL, 0 }, // MassScale
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->SelfCollision), NULL, 0 }, // SelfCollision
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->SelfCollisionWire), NULL, 0 }, // SelfCollisionWire
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->SelfCollisionAttenuation), NULL, 0 }, // SelfCollisionAttenuation
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->SolverMode), NULL, 0 }, // SolverMode
+};
+
+
+bool ClothingDebugRenderParams::mBuiltFlag = false;
+NvParameterized::MutexType ClothingDebugRenderParams::mBuiltFlagMutex;
+
+ClothingDebugRenderParams::ClothingDebugRenderParams(NvParameterized::Traits* traits, void* buf, int32_t* refCount) :
+ NvParameters(traits, buf, refCount)
+{
+ //mParameterizedTraits->registerFactory(className(), &ClothingDebugRenderParamsFactoryInst);
+
+ if (!buf) //Do not init data if it is inplace-deserialized
+ {
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+ initDefaults();
+ }
+}
+
+ClothingDebugRenderParams::~ClothingDebugRenderParams()
+{
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+}
+
+void ClothingDebugRenderParams::destroy()
+{
+ // We cache these fields here to avoid overwrite in destructor
+ bool doDeallocateSelf = mDoDeallocateSelf;
+ NvParameterized::Traits* traits = mParameterizedTraits;
+ int32_t* refCount = mRefCount;
+ void* buf = mBuffer;
+
+ this->~ClothingDebugRenderParams();
+
+ NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf);
+}
+
+const NvParameterized::DefinitionImpl* ClothingDebugRenderParams::getParameterDefinitionTree(void)
+{
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+const NvParameterized::DefinitionImpl* ClothingDebugRenderParams::getParameterDefinitionTree(void) const
+{
+ ClothingDebugRenderParams* tmpParam = const_cast<ClothingDebugRenderParams*>(this);
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ tmpParam->buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+NvParameterized::ErrorType ClothingDebugRenderParams::getParameterHandle(const char* long_name, Handle& handle) const
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+NvParameterized::ErrorType ClothingDebugRenderParams::getParameterHandle(const char* long_name, Handle& handle)
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+void ClothingDebugRenderParams::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const
+{
+ ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<ClothingDebugRenderParams::ParametersStruct*>(&parameters()), handle, offset);
+}
+
+
+/* Dynamic Handle Indices */
+
+void ClothingDebugRenderParams::freeParameterDefinitionTable(NvParameterized::Traits* traits)
+{
+ if (!traits)
+ {
+ return;
+ }
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ return;
+ }
+
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+
+ if (!mBuiltFlag)
+ {
+ return;
+ }
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ ParamDefTable[i].~DefinitionImpl();
+ }
+
+ traits->free(ParamDefTable);
+
+ mBuiltFlag = false;
+}
+
+#define PDEF_PTR(index) (&ParamDefTable[index])
+
+void ClothingDebugRenderParams::buildTree(void)
+{
+
+ uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs;
+ ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize));
+ memset(ParamDefTable, 0, allocSize);
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=0, longName=""
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0];
+ ParamDef->init("", TYPE_STRUCT, "STRUCT", true);
+
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=1, longName="Actors"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1];
+ ParamDef->init("Actors", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Enables/Disables visualization of all clothing actors", true);
+ ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=2, longName="SkinnedPositions"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2];
+ ParamDef->init("SkinnedPositions", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Marks each animation position with a small cross as the centers of the spheres in which the simulated vertices are allowed to move. Blue for static vertices, black to white for increasing max distance.", true);
+ ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=3, longName="Backstop"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3];
+ ParamDef->init("Backstop", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The part of the mesh with backstop is solidly rendered. Red for front faces, blue for back faces.", true);
+ ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=4, longName="BackstopPrecise"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4];
+ ParamDef->init("BackstopPrecise", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Draws small segments of the backstop sphere for each simulation vertex. (scalable)", true);
+ ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=5, longName="MaxDistance"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5];
+ ParamDef->init("MaxDistance", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Draws a line from the skinned position along the skinned normal with the length of the max distance this vertex is allowed to move. Note that the LoD mechanism can scale down the Max Distance of the asset.", true);
+ ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=6, longName="MaxDistanceInwards"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6];
+ ParamDef->init("MaxDistanceInwards", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Same as MaxDistance but to the other side. Bounded by backstop. The length of the line is either Max Distance or sphere collision distance, depending on which is smaller and restricts the motion of the vertex.", true);
+ ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=7, longName="SkinMapAll"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7];
+ ParamDef->init("SkinMapAll", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Draws the full support mesh for mesh-mesh skinning.", true);
+ ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=8, longName="SkinMapBad"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8];
+ ParamDef->init("SkinMapBad", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Draws the support mesh for mesh-mesh skinning. But only for vertices that actually lie outside of the support mesh and could cause problems", true);
+ ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=9, longName="SkinMapActual"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9];
+ ParamDef->init("SkinMapActual", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Draws the actual support mesh for mesh-mesh skinning (only the parts that are effectively used).", true);
+ ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=10, longName="SkinMapInvalidBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[10];
+ ParamDef->init("SkinMapInvalidBary", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Draws physical triangles and corresponding graphical vertices that have invalid barycentric coordinates in the mesh skinning map. Red: invalid position bary. Purple: invalid normal bary. Blue: invalid tangent bary.", true);
+ ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=11, longName="PhysicsMeshWire"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[11];
+ ParamDef->init("PhysicsMeshWire", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ HintTable[2].init("shortDescription", "Draws the simulation mesh, only the active region. From yellow to red, the closer a vertex gets to its max distance. (scalable)", true);
+ ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=12, longName="PhysicsMeshSolid"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[12];
+ ParamDef->init("PhysicsMeshSolid", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ HintTable[2].init("shortDescription", "Same as PhysicsMeshWire but with solid triangles.", true);
+ ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=13, longName="PhysicsMeshNormals"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[13];
+ ParamDef->init("PhysicsMeshNormals", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Displays the normals of the physics mesh (base for mesh-mesh skinning).", true);
+ ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=14, longName="Skeleton"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[14];
+ ParamDef->init("Skeleton", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Draws lines from parent to child bones. Active bones are displayed in purple, passive in blue. Only the subset of bones that have a vertex from any of the meshes or a collision volume bound to them will be visible.", true);
+ ParamDefTable[14].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=15, longName="BoneFrames"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[15];
+ ParamDef->init("BoneFrames", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Draws the frame of each bone. (scalable)", true);
+ ParamDefTable[15].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=16, longName="BoneNames"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[16];
+ ParamDef->init("BoneNames", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Displays the name of each bone. (scalable)", true);
+ ParamDefTable[16].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=17, longName="Velocities"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[17];
+ ParamDef->init("Velocities", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Draws lines for each simulated vertex' velocity. (scalable)", true);
+ ParamDefTable[17].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=18, longName="Wind"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[18];
+ ParamDef->init("Wind", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Draws lines for each simulated vertex' velocity change due to wind, velocity callback or pressure. (scalable)", true);
+ ParamDefTable[18].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=19, longName="GraphicalVertexBones"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[19];
+ ParamDef->init("GraphicalVertexBones", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Draws colored lines from each graphical vertex to the bones it uses for skinning. White to black for decreasing weights.", true);
+ ParamDefTable[19].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=20, longName="PhysicalVertexBones"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[20];
+ ParamDef->init("PhysicalVertexBones", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Draws colored lines from each simulation vertex to the bones it uses for skinning. White to black for decreasing weights.", true);
+ ParamDefTable[20].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=21, longName="CollisionShapes"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[21];
+ ParamDef->init("CollisionShapes", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Draws solid capsules and spheres for the collision shapes.", true);
+ ParamDefTable[21].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=22, longName="CollisionShapesWire"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[22];
+ ParamDef->init("CollisionShapesWire", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Draws wire capsules and spheres for the collision shapes.", true);
+ ParamDefTable[22].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=23, longName="LengthFibers"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[23];
+ ParamDef->init("LengthFibers", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Show the vertical stretching fibers.", true);
+ ParamDefTable[23].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=24, longName="CrossSectionFibers"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[24];
+ ParamDef->init("CrossSectionFibers", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Show the horizontal stretching fibers.", true);
+ ParamDefTable[24].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=25, longName="BendingFibers"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[25];
+ ParamDef->init("BendingFibers", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Show the bending fibers.", true);
+ ParamDefTable[25].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=26, longName="ShearingFibers"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[26];
+ ParamDef->init("ShearingFibers", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Show the shearing fibers.", true);
+ ParamDefTable[26].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=27, longName="ZerostretchFibers"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[27];
+ ParamDef->init("ZerostretchFibers", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Show the zero-stretch phases.", true);
+ ParamDefTable[27].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=28, longName="TethersActive"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[28];
+ ParamDef->init("TethersActive", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Show the tether constraitns, only active ones (0.99 their length and longer).", true);
+ ParamDefTable[28].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=29, longName="TethersInactive"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[29];
+ ParamDef->init("TethersInactive", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Show the tether constraints, only inactive ones (less than 0.99 their length).", true);
+ ParamDefTable[29].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=30, longName="VirtualCollision"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[30];
+ ParamDef->init("VirtualCollision", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Show the virtual particles. Each has 3 lines to the vertices it connects to.", true);
+ ParamDefTable[30].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=31, longName="FiberRange"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[31];
+ ParamDef->init("FiberRange", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Combined with fiber debug rendering this visualizes the range where the stiffness of the chosen fiber type is scaled down. It shows how much the cloth is allowed to compress/stretch.", true);
+ ParamDefTable[31].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=32, longName="ShowInLocalSpace"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[32];
+ ParamDef->init("ShowInLocalSpace", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Enables/Disables debug rendering in local space (experts only!)", true);
+ ParamDefTable[32].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=33, longName="GlobalPose"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[33];
+ ParamDef->init("GlobalPose", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Shows the internally stored global pose transform", true);
+ ParamDefTable[33].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=34, longName="RecomputeSubmeshes"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[34];
+ ParamDef->init("RecomputeSubmeshes", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Shows the internal reordering of the render mesh asset into physical submeshes and non-simulated parts in shades of gray. This is used to split the cpu skinned part from the skinned part that is skinned the physics mesh.", true);
+ ParamDefTable[34].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=35, longName="RecomputeVertices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[35];
+ ParamDef->init("RecomputeVertices", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Shows the position of the reordered render vertices that are being skinned to the physics mesh. Vertices attached to simulated triangles are rendered orange. Additional vertices along the border are rendered purple, they are needed to prevent visible seams from normal and tangent calculations.", true);
+ ParamDefTable[35].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=36, longName="PhysicsMeshIndices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[36];
+ ParamDef->init("PhysicsMeshIndices", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Shows the indices of the physics mesh", true);
+ ParamDefTable[36].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=37, longName="MassScale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[37];
+ ParamDef->init("MassScale", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Shows red crosses for particles where the mass is scaled for collision purpose", true);
+ ParamDefTable[37].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=38, longName="SelfCollision"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[38];
+ ParamDef->init("SelfCollision", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Shows spheres that represent the self collision thickness", true);
+ ParamDefTable[38].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=39, longName="SelfCollisionWire"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[39];
+ ParamDef->init("SelfCollisionWire", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Shows spheres that represent the self collision thickness", true);
+ ParamDefTable[39].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=40, longName="SelfCollisionAttenuation"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[40];
+ ParamDef->init("SelfCollisionAttenuation", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "All connections are drawn that have an attenuation smaller than the given value.\n0.0f disables the visualization, 1.0f shows all attenuated pairs.\n", true);
+ HintTable[1].init("shortDescription", "Draws a line between vertices where selfcollision is reduced or turned off.", true);
+ ParamDefTable[40].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=41, longName="SolverMode"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[41];
+ ParamDef->init("SolverMode", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Shared: Fastest path. It means previous and current positions fit onto shared memory on the GPU.\nMixed: Only slightly slower than Shared. Current positions fit onto shared memory, previous positions need to be streamed in.\nGlobal: Significantly slower than Shared and Mixed. All data is read from global GPU memory. Try to reduce the vertex count and/or split up the asset.\n", true);
+ HintTable[1].init("shortDescription", "Displays which solver is used (2.x or 3.x), wether it runs on GPU, and if the simulation data fits into shared memory.", true);
+ ParamDefTable[41].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // SetChildren for: nodeIndex=0, longName=""
+ {
+ static Definition* Children[41];
+ Children[0] = PDEF_PTR(1);
+ Children[1] = PDEF_PTR(2);
+ Children[2] = PDEF_PTR(3);
+ Children[3] = PDEF_PTR(4);
+ Children[4] = PDEF_PTR(5);
+ Children[5] = PDEF_PTR(6);
+ Children[6] = PDEF_PTR(7);
+ Children[7] = PDEF_PTR(8);
+ Children[8] = PDEF_PTR(9);
+ Children[9] = PDEF_PTR(10);
+ Children[10] = PDEF_PTR(11);
+ Children[11] = PDEF_PTR(12);
+ Children[12] = PDEF_PTR(13);
+ Children[13] = PDEF_PTR(14);
+ Children[14] = PDEF_PTR(15);
+ Children[15] = PDEF_PTR(16);
+ Children[16] = PDEF_PTR(17);
+ Children[17] = PDEF_PTR(18);
+ Children[18] = PDEF_PTR(19);
+ Children[19] = PDEF_PTR(20);
+ Children[20] = PDEF_PTR(21);
+ Children[21] = PDEF_PTR(22);
+ Children[22] = PDEF_PTR(23);
+ Children[23] = PDEF_PTR(24);
+ Children[24] = PDEF_PTR(25);
+ Children[25] = PDEF_PTR(26);
+ Children[26] = PDEF_PTR(27);
+ Children[27] = PDEF_PTR(28);
+ Children[28] = PDEF_PTR(29);
+ Children[29] = PDEF_PTR(30);
+ Children[30] = PDEF_PTR(31);
+ Children[31] = PDEF_PTR(32);
+ Children[32] = PDEF_PTR(33);
+ Children[33] = PDEF_PTR(34);
+ Children[34] = PDEF_PTR(35);
+ Children[35] = PDEF_PTR(36);
+ Children[36] = PDEF_PTR(37);
+ Children[37] = PDEF_PTR(38);
+ Children[38] = PDEF_PTR(39);
+ Children[39] = PDEF_PTR(40);
+ Children[40] = PDEF_PTR(41);
+
+ ParamDefTable[0].setChildren(Children, 41);
+ }
+
+ mBuiltFlag = true;
+
+}
+void ClothingDebugRenderParams::initStrings(void)
+{
+}
+
+void ClothingDebugRenderParams::initDynamicArrays(void)
+{
+}
+
+void ClothingDebugRenderParams::initDefaults(void)
+{
+
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+ Actors = bool(true);
+ SkinnedPositions = float(0);
+ Backstop = bool(false);
+ BackstopPrecise = float(0);
+ MaxDistance = bool(0);
+ MaxDistanceInwards = bool(0);
+ SkinMapAll = bool(0);
+ SkinMapBad = bool(0);
+ SkinMapActual = bool(0);
+ SkinMapInvalidBary = bool(0);
+ PhysicsMeshWire = float(0);
+ PhysicsMeshSolid = float(0);
+ PhysicsMeshNormals = float(0);
+ Skeleton = bool(0);
+ BoneFrames = float(0);
+ BoneNames = float(0);
+ Velocities = float(0);
+ Wind = float(0);
+ GraphicalVertexBones = bool(0);
+ PhysicalVertexBones = bool(0);
+ CollisionShapes = bool(false);
+ CollisionShapesWire = bool(false);
+ LengthFibers = bool(false);
+ CrossSectionFibers = bool(false);
+ BendingFibers = bool(false);
+ ShearingFibers = bool(false);
+ ZerostretchFibers = bool(false);
+ TethersActive = bool(false);
+ TethersInactive = bool(false);
+ VirtualCollision = bool(false);
+ FiberRange = bool(false);
+ ShowInLocalSpace = bool(false);
+ GlobalPose = bool(false);
+ RecomputeSubmeshes = bool(false);
+ RecomputeVertices = bool(false);
+ PhysicsMeshIndices = bool(false);
+ MassScale = bool(false);
+ SelfCollision = bool(false);
+ SelfCollisionWire = bool(false);
+ SelfCollisionAttenuation = float(false);
+ SolverMode = bool(false);
+
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+}
+
+void ClothingDebugRenderParams::initReferences(void)
+{
+}
+
+void ClothingDebugRenderParams::freeDynamicArrays(void)
+{
+}
+
+void ClothingDebugRenderParams::freeStrings(void)
+{
+}
+
+void ClothingDebugRenderParams::freeReferences(void)
+{
+}
+
+} // namespace clothing
+} // namespace nvidia
diff --git a/APEX_1.4/module/clothing/src/autogen/ClothingGraphicalLodParameters.cpp b/APEX_1.4/module/clothing/src/autogen/ClothingGraphicalLodParameters.cpp
new file mode 100644
index 00000000..59293e7c
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/autogen/ClothingGraphicalLodParameters.cpp
@@ -0,0 +1,1491 @@
+// 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-2015 NVIDIA Corporation. All rights reserved.
+
+// This file was generated by NvParameterized/scripts/GenParameterized.pl
+
+
+#include "ClothingGraphicalLodParameters.h"
+#include <string.h>
+#include <stdlib.h>
+
+using namespace NvParameterized;
+
+namespace nvidia
+{
+namespace clothing
+{
+
+using namespace ClothingGraphicalLodParametersNS;
+
+const char* const ClothingGraphicalLodParametersFactory::vptr =
+ NvParameterized::getVptr<ClothingGraphicalLodParameters, ClothingGraphicalLodParameters::ClassAlignment>();
+
+const uint32_t NumParamDefs = 41;
+static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs];
+
+
+static const size_t ParamLookupChildrenTable[] =
+{
+ 1, 3, 4, 5, 6, 7, 9, 17, 26, 27, 28, 34, 35, 2, 8, 10, 11, 12, 13, 14, 15, 16, 18,
+ 19, 20, 21, 22, 23, 24, 25, 29, 30, 31, 32, 33, 36, 37, 38, 39, 40,
+};
+
+#define TENUM(type) nvidia::##type
+#define CHILDREN(index) &ParamLookupChildrenTable[index]
+static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] =
+{
+ { TYPE_STRUCT, false, 0, CHILDREN(0), 13 },
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->platforms), CHILDREN(13), 1 }, // platforms
+ { TYPE_STRING, false, 1 * sizeof(NvParameterized::DummyStringStruct), NULL, 0 }, // platforms[]
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->lod), NULL, 0 }, // lod
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->physicalMeshId), NULL, 0 }, // physicalMeshId
+ { TYPE_REF, false, (size_t)(&((ParametersStruct*)0)->renderMeshAsset), NULL, 0 }, // renderMeshAsset
+ { TYPE_POINTER, false, (size_t)(&((ParametersStruct*)0)->renderMeshAssetPointer), NULL, 0 }, // renderMeshAssetPointer
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->immediateClothMap), CHILDREN(14), 1 }, // immediateClothMap
+ { TYPE_U32, false, 1 * sizeof(uint32_t), NULL, 0 }, // immediateClothMap[]
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->skinClothMapB), CHILDREN(15), 1 }, // skinClothMapB
+ { TYPE_STRUCT, false, 1 * sizeof(SkinClothMapB_Type), CHILDREN(16), 6 }, // skinClothMapB[]
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapB_Type*)0)->vtxTetraBary), NULL, 0 }, // skinClothMapB[].vtxTetraBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapB_Type*)0)->vertexIndexPlusOffset), NULL, 0 }, // skinClothMapB[].vertexIndexPlusOffset
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapB_Type*)0)->nrmTetraBary), NULL, 0 }, // skinClothMapB[].nrmTetraBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapB_Type*)0)->faceIndex0), NULL, 0 }, // skinClothMapB[].faceIndex0
+ { TYPE_U32, false, (size_t)(&((SkinClothMapB_Type*)0)->tetraIndex), NULL, 0 }, // skinClothMapB[].tetraIndex
+ { TYPE_U32, false, (size_t)(&((SkinClothMapB_Type*)0)->submeshIndex), NULL, 0 }, // skinClothMapB[].submeshIndex
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->skinClothMap), CHILDREN(22), 1 }, // skinClothMap
+ { TYPE_STRUCT, false, 1 * sizeof(SkinClothMapD_Type), CHILDREN(23), 7 }, // skinClothMap[]
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexBary), NULL, 0 }, // skinClothMap[].vertexBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexIndex0), NULL, 0 }, // skinClothMap[].vertexIndex0
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapD_Type*)0)->normalBary), NULL, 0 }, // skinClothMap[].normalBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexIndex1), NULL, 0 }, // skinClothMap[].vertexIndex1
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapD_Type*)0)->tangentBary), NULL, 0 }, // skinClothMap[].tangentBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexIndex2), NULL, 0 }, // skinClothMap[].vertexIndex2
+ { TYPE_U32, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexIndexPlusOffset), NULL, 0 }, // skinClothMap[].vertexIndexPlusOffset
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->skinClothMapThickness), NULL, 0 }, // skinClothMapThickness
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->skinClothMapOffset), NULL, 0 }, // skinClothMapOffset
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->tetraMap), CHILDREN(30), 1 }, // tetraMap
+ { TYPE_STRUCT, false, 1 * sizeof(TetraLink_Type), CHILDREN(31), 4 }, // tetraMap[]
+ { TYPE_VEC3, false, (size_t)(&((TetraLink_Type*)0)->vertexBary), NULL, 0 }, // tetraMap[].vertexBary
+ { TYPE_U32, false, (size_t)(&((TetraLink_Type*)0)->tetraIndex0), NULL, 0 }, // tetraMap[].tetraIndex0
+ { TYPE_VEC3, false, (size_t)(&((TetraLink_Type*)0)->normalBary), NULL, 0 }, // tetraMap[].normalBary
+ { TYPE_U32, false, (size_t)(&((TetraLink_Type*)0)->_dummyForAlignment), NULL, 0 }, // tetraMap[]._dummyForAlignment
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->renderMeshAssetSorting), NULL, 0 }, // renderMeshAssetSorting
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->physicsMeshPartitioning), CHILDREN(35), 1 }, // physicsMeshPartitioning
+ { TYPE_STRUCT, false, 1 * sizeof(PhysicsMeshPartitioning_Type), CHILDREN(36), 4 }, // physicsMeshPartitioning[]
+ { TYPE_U32, false, (size_t)(&((PhysicsMeshPartitioning_Type*)0)->graphicalSubmesh), NULL, 0 }, // physicsMeshPartitioning[].graphicalSubmesh
+ { TYPE_U32, false, (size_t)(&((PhysicsMeshPartitioning_Type*)0)->numSimulatedVertices), NULL, 0 }, // physicsMeshPartitioning[].numSimulatedVertices
+ { TYPE_U32, false, (size_t)(&((PhysicsMeshPartitioning_Type*)0)->numSimulatedVerticesAdditional), NULL, 0 }, // physicsMeshPartitioning[].numSimulatedVerticesAdditional
+ { TYPE_U32, false, (size_t)(&((PhysicsMeshPartitioning_Type*)0)->numSimulatedIndices), NULL, 0 }, // physicsMeshPartitioning[].numSimulatedIndices
+};
+
+
+bool ClothingGraphicalLodParameters::mBuiltFlag = false;
+NvParameterized::MutexType ClothingGraphicalLodParameters::mBuiltFlagMutex;
+
+ClothingGraphicalLodParameters::ClothingGraphicalLodParameters(NvParameterized::Traits* traits, void* buf, int32_t* refCount) :
+ NvParameters(traits, buf, refCount)
+{
+ //mParameterizedTraits->registerFactory(className(), &ClothingGraphicalLodParametersFactoryInst);
+
+ if (!buf) //Do not init data if it is inplace-deserialized
+ {
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+ initDefaults();
+ }
+}
+
+ClothingGraphicalLodParameters::~ClothingGraphicalLodParameters()
+{
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+}
+
+void ClothingGraphicalLodParameters::destroy()
+{
+ // We cache these fields here to avoid overwrite in destructor
+ bool doDeallocateSelf = mDoDeallocateSelf;
+ NvParameterized::Traits* traits = mParameterizedTraits;
+ int32_t* refCount = mRefCount;
+ void* buf = mBuffer;
+
+ this->~ClothingGraphicalLodParameters();
+
+ NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf);
+}
+
+const NvParameterized::DefinitionImpl* ClothingGraphicalLodParameters::getParameterDefinitionTree(void)
+{
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+const NvParameterized::DefinitionImpl* ClothingGraphicalLodParameters::getParameterDefinitionTree(void) const
+{
+ ClothingGraphicalLodParameters* tmpParam = const_cast<ClothingGraphicalLodParameters*>(this);
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ tmpParam->buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+NvParameterized::ErrorType ClothingGraphicalLodParameters::getParameterHandle(const char* long_name, Handle& handle) const
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+NvParameterized::ErrorType ClothingGraphicalLodParameters::getParameterHandle(const char* long_name, Handle& handle)
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+void ClothingGraphicalLodParameters::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const
+{
+ ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<ClothingGraphicalLodParameters::ParametersStruct*>(&parameters()), handle, offset);
+}
+
+
+/* Dynamic Handle Indices */
+/* [0] - platforms (not an array of structs) */
+
+void ClothingGraphicalLodParameters::freeParameterDefinitionTable(NvParameterized::Traits* traits)
+{
+ if (!traits)
+ {
+ return;
+ }
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ return;
+ }
+
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+
+ if (!mBuiltFlag)
+ {
+ return;
+ }
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ ParamDefTable[i].~DefinitionImpl();
+ }
+
+ traits->free(ParamDefTable);
+
+ mBuiltFlag = false;
+}
+
+#define PDEF_PTR(index) (&ParamDefTable[index])
+
+void ClothingGraphicalLodParameters::buildTree(void)
+{
+
+ uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs;
+ ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize));
+ memset(ParamDefTable, 0, allocSize);
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=0, longName=""
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0];
+ ParamDef->init("", TYPE_STRUCT, "STRUCT", true);
+
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=1, longName="platforms"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1];
+ ParamDef->init("platforms", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "The assets can be prepared for different platforms. This string specifies for which\nplatforms this LOD is kept in the asset.\n", true);
+ HintTable[1].init("shortDescription", "Platforms on this lod is used.", true);
+ ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ static const uint8_t dynHandleIndices[1] = { 0, };
+ ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 1);
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=2, longName="platforms[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2];
+ ParamDef->init("platforms", TYPE_STRING, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "The assets can be prepared for different platforms. This string specifies for which\nplatforms this LOD is kept in the asset.\n", true);
+ HintTable[1].init("shortDescription", "Platforms on this lod is used.", true);
+ ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=3, longName="lod"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3];
+ ParamDef->init("lod", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Even for a small number of LoDs, the LoD value does not have to be continuous. An Asset\ncan have 3 LoDs at leve 0, 3 and 6.\n", true);
+ HintTable[1].init("shortDescription", "The actual LoD value", true);
+ ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=4, longName="physicalMeshId"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4];
+ ParamDef->init("physicalMeshId", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "This indexes a physical mesh from the physicalMesh Array in the ClothingAsset. Different\ngraphical LoDs can share a physical mesh.\n", true);
+ HintTable[1].init("shortDescription", "Index of the physical mesh used for this graphical mesh.", true);
+ ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=5, longName="renderMeshAsset"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5];
+ ParamDef->init("renderMeshAsset", TYPE_REF, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("INCLUDED", uint64_t(1), true);
+ HintTable[1].init("longDescription", "Each LoD must have a unique render mesh asset.\n", true);
+ HintTable[2].init("shortDescription", "The render mesh asset used for this LoD level", true);
+ ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+ static const char* const RefVariantVals[] = { "RenderMeshAssetParameters" };
+ ParamDefTable[5].setRefVariantVals((const char**)RefVariantVals, 1);
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=6, longName="renderMeshAssetPointer"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6];
+ ParamDef->init("renderMeshAssetPointer", TYPE_POINTER, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ HintTable[1].init("TYPE", "NiApexRenderMeshAsset", true);
+ ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ HintTable[1].init("TYPE", "NiApexRenderMeshAsset", true);
+ HintTable[2].init("shortDescription", "Render mesh asset pointer", true);
+ ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=7, longName="immediateClothMap"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7];
+ ParamDef->init("immediateClothMap", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "If some vertices can not be mapped properly, they will use the skinClothMapB to tie to the physical mesh.\n", true);
+ HintTable[2].init("shortDescription", "Directly map some of the physically simulated vertices on the graphical mesh", true);
+ ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=8, longName="immediateClothMap[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8];
+ ParamDef->init("immediateClothMap", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "If some vertices can not be mapped properly, they will use the skinClothMapB to tie to the physical mesh.\n", true);
+ HintTable[2].init("shortDescription", "Directly map some of the physically simulated vertices on the graphical mesh", true);
+ ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=9, longName="skinClothMapB"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9];
+ ParamDef->init("skinClothMapB", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "Usually maps only a subset of all vertices to the physical mesh. The others can be done through the immediateClothMap.\n", true);
+ HintTable[2].init("shortDescription", "Map each graphical vertex onto a physically simulated triangle through barycentric coordinates and implicit tetrahedrons.", true);
+ ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=10, longName="skinClothMapB[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[10];
+ ParamDef->init("skinClothMapB", TYPE_STRUCT, "SkinClothMapB", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "Usually maps only a subset of all vertices to the physical mesh. The others can be done through the immediateClothMap.\n", true);
+ HintTable[2].init("shortDescription", "Map each graphical vertex onto a physically simulated triangle through barycentric coordinates and implicit tetrahedrons.", true);
+ ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=11, longName="skinClothMapB[].vtxTetraBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[11];
+ ParamDef->init("vtxTetraBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate into the implicit tetrahedron.", true);
+ ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=12, longName="skinClothMapB[].vertexIndexPlusOffset"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[12];
+ ParamDef->init("vertexIndexPlusOffset", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The vertex index in the graphical mesh (the target index).", true);
+ ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=13, longName="skinClothMapB[].nrmTetraBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[13];
+ ParamDef->init("nrmTetraBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate of (vertex+normal). When vertex is subtracted this will result in the normal again.", true);
+ ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=14, longName="skinClothMapB[].faceIndex0"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[14];
+ ParamDef->init("faceIndex0", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "First index of the 3 consecutive indices making the physical triangle.", true);
+ ParamDefTable[14].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=15, longName="skinClothMapB[].tetraIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[15];
+ ParamDef->init("tetraIndex", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Selects which of the 6 implicit tetrahedrons is used for the mapping.", true);
+ ParamDefTable[15].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=16, longName="skinClothMapB[].submeshIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[16];
+ ParamDef->init("submeshIndex", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ ParamDefTable[16].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ HintTable[1].init("longDescription", "This is only needed during the authoring stage and thus does not need to be serialized.", true);
+ HintTable[2].init("shortDescription", "Index into which Physical Submesh/LoD this element of the mapping belongs to.", true);
+ ParamDefTable[16].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=17, longName="skinClothMap"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[17];
+ ParamDef->init("skinClothMap", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[17].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "Usually maps only a subset of all vertices to the physical mesh. The others can be done through the immediateClothMap.\n", true);
+ HintTable[2].init("shortDescription", "Map each graphical vertex onto a physically simulated triangle through barycentric coordinates.", true);
+ ParamDefTable[17].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=18, longName="skinClothMap[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[18];
+ ParamDef->init("skinClothMap", TYPE_STRUCT, "SkinClothMapD", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[18].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "Usually maps only a subset of all vertices to the physical mesh. The others can be done through the immediateClothMap.\n", true);
+ HintTable[2].init("shortDescription", "Map each graphical vertex onto a physically simulated triangle through barycentric coordinates.", true);
+ ParamDefTable[18].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=19, longName="skinClothMap[].vertexBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[19];
+ ParamDef->init("vertexBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate into the triangle.", true);
+ ParamDefTable[19].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=20, longName="skinClothMap[].vertexIndex0"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[20];
+ ParamDef->init("vertexIndex0", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Vertex index of the physics triangle.", true);
+ ParamDefTable[20].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=21, longName="skinClothMap[].normalBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[21];
+ ParamDef->init("normalBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate of (vertex+normal). When vertex is subtracted this will result in the normal again.", true);
+ ParamDefTable[21].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=22, longName="skinClothMap[].vertexIndex1"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[22];
+ ParamDef->init("vertexIndex1", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Vertex index of the physics triangle.", true);
+ ParamDefTable[22].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=23, longName="skinClothMap[].tangentBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[23];
+ ParamDef->init("tangentBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate of (position+tangent). When position is subtracted this will result in the tangent again.", true);
+ ParamDefTable[23].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=24, longName="skinClothMap[].vertexIndex2"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[24];
+ ParamDef->init("vertexIndex2", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Vertex index of the physics triangle.", true);
+ ParamDefTable[24].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=25, longName="skinClothMap[].vertexIndexPlusOffset"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[25];
+ ParamDef->init("vertexIndexPlusOffset", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The vertex index in the graphical mesh (the target index).", true);
+ ParamDefTable[25].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=26, longName="skinClothMapThickness"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[26];
+ ParamDef->init("skinClothMapThickness", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("READONLY", uint64_t(1), true);
+ ParamDefTable[26].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("READONLY", uint64_t(1), true);
+ HintTable[1].init("longDescription", "The physical mesh is expanded to both directions with this thickness, resulting in the doubled thickness.\nOnly used for Mesh-Mesh Skinning.\n", true);
+ HintTable[2].init("shortDescription", "Thickness of the mesh implicitly defined around the flat physical (triangle) mesh.", true);
+ ParamDefTable[26].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=27, longName="skinClothMapOffset"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[27];
+ ParamDef->init("skinClothMapOffset", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("READONLY", uint64_t(1), true);
+ ParamDefTable[27].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("READONLY", uint64_t(1), true);
+ HintTable[1].init("longDescription", "The length of the normals when added to the vertex to generate the barycentric coordinates.\n", true);
+ HintTable[2].init("shortDescription", "Normal offset of the mesh implicitly defined around the flat physical (triangle) mesh.", true);
+ ParamDefTable[27].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=28, longName="tetraMap"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[28];
+ ParamDef->init("tetraMap", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[28].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "This map is only used when the physical mesh is based on tetrahedrons.\n", true);
+ HintTable[2].init("shortDescription", "Map each graphical vertex onto a physically simulated tetrahedron.", true);
+ ParamDefTable[28].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=29, longName="tetraMap[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[29];
+ ParamDef->init("tetraMap", TYPE_STRUCT, "TetraLink", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[29].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "This map is only used when the physical mesh is based on tetrahedrons.\n", true);
+ HintTable[2].init("shortDescription", "Map each graphical vertex onto a physically simulated tetrahedron.", true);
+ ParamDefTable[29].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=30, longName="tetraMap[].vertexBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[30];
+ ParamDef->init("vertexBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate into the tetrahedron.", true);
+ ParamDefTable[30].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=31, longName="tetraMap[].tetraIndex0"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[31];
+ ParamDef->init("tetraIndex0", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "First index of the 4 consecutive indices making the physical tetrahedron.", true);
+ ParamDefTable[31].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=32, longName="tetraMap[].normalBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[32];
+ ParamDef->init("normalBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate of (vertex+normal). When vertex is subtracted this will result in the normal again.", true);
+ ParamDefTable[32].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=33, longName="tetraMap[]._dummyForAlignment"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[33];
+ ParamDef->init("_dummyForAlignment", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ ParamDefTable[33].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Does not hold any data, only helps the alignment of the struct.", true);
+ ParamDefTable[33].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=34, longName="renderMeshAssetSorting"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[34];
+ ParamDef->init("renderMeshAssetSorting", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Render mesh asset sorting", true);
+ ParamDefTable[34].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=35, longName="physicsMeshPartitioning"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[35];
+ ParamDef->init("physicsMeshPartitioning", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Physics mesh partitioning", true);
+ ParamDefTable[35].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=36, longName="physicsMeshPartitioning[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[36];
+ ParamDef->init("physicsMeshPartitioning", TYPE_STRUCT, "PhysicsMeshPartitioning", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Physics mesh partitioning", true);
+ ParamDefTable[36].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=37, longName="physicsMeshPartitioning[].graphicalSubmesh"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[37];
+ ParamDef->init("graphicalSubmesh", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Graphical submesh", true);
+ ParamDefTable[37].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=38, longName="physicsMeshPartitioning[].numSimulatedVertices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[38];
+ ParamDef->init("numSimulatedVertices", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Simulated vertex count", true);
+ ParamDefTable[38].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=39, longName="physicsMeshPartitioning[].numSimulatedVerticesAdditional"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[39];
+ ParamDef->init("numSimulatedVerticesAdditional", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Simulated additional vertex count", true);
+ ParamDefTable[39].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=40, longName="physicsMeshPartitioning[].numSimulatedIndices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[40];
+ ParamDef->init("numSimulatedIndices", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Simulated index count", true);
+ ParamDefTable[40].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // SetChildren for: nodeIndex=0, longName=""
+ {
+ static Definition* Children[13];
+ Children[0] = PDEF_PTR(1);
+ Children[1] = PDEF_PTR(3);
+ Children[2] = PDEF_PTR(4);
+ Children[3] = PDEF_PTR(5);
+ Children[4] = PDEF_PTR(6);
+ Children[5] = PDEF_PTR(7);
+ Children[6] = PDEF_PTR(9);
+ Children[7] = PDEF_PTR(17);
+ Children[8] = PDEF_PTR(26);
+ Children[9] = PDEF_PTR(27);
+ Children[10] = PDEF_PTR(28);
+ Children[11] = PDEF_PTR(34);
+ Children[12] = PDEF_PTR(35);
+
+ ParamDefTable[0].setChildren(Children, 13);
+ }
+
+ // SetChildren for: nodeIndex=1, longName="platforms"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(2);
+
+ ParamDefTable[1].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=7, longName="immediateClothMap"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(8);
+
+ ParamDefTable[7].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=9, longName="skinClothMapB"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(10);
+
+ ParamDefTable[9].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=10, longName="skinClothMapB[]"
+ {
+ static Definition* Children[6];
+ Children[0] = PDEF_PTR(11);
+ Children[1] = PDEF_PTR(12);
+ Children[2] = PDEF_PTR(13);
+ Children[3] = PDEF_PTR(14);
+ Children[4] = PDEF_PTR(15);
+ Children[5] = PDEF_PTR(16);
+
+ ParamDefTable[10].setChildren(Children, 6);
+ }
+
+ // SetChildren for: nodeIndex=17, longName="skinClothMap"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(18);
+
+ ParamDefTable[17].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=18, longName="skinClothMap[]"
+ {
+ static Definition* Children[7];
+ Children[0] = PDEF_PTR(19);
+ Children[1] = PDEF_PTR(20);
+ Children[2] = PDEF_PTR(21);
+ Children[3] = PDEF_PTR(22);
+ Children[4] = PDEF_PTR(23);
+ Children[5] = PDEF_PTR(24);
+ Children[6] = PDEF_PTR(25);
+
+ ParamDefTable[18].setChildren(Children, 7);
+ }
+
+ // SetChildren for: nodeIndex=28, longName="tetraMap"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(29);
+
+ ParamDefTable[28].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=29, longName="tetraMap[]"
+ {
+ static Definition* Children[4];
+ Children[0] = PDEF_PTR(30);
+ Children[1] = PDEF_PTR(31);
+ Children[2] = PDEF_PTR(32);
+ Children[3] = PDEF_PTR(33);
+
+ ParamDefTable[29].setChildren(Children, 4);
+ }
+
+ // SetChildren for: nodeIndex=35, longName="physicsMeshPartitioning"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(36);
+
+ ParamDefTable[35].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=36, longName="physicsMeshPartitioning[]"
+ {
+ static Definition* Children[4];
+ Children[0] = PDEF_PTR(37);
+ Children[1] = PDEF_PTR(38);
+ Children[2] = PDEF_PTR(39);
+ Children[3] = PDEF_PTR(40);
+
+ ParamDefTable[36].setChildren(Children, 4);
+ }
+
+ mBuiltFlag = true;
+
+}
+void ClothingGraphicalLodParameters::initStrings(void)
+{
+}
+
+void ClothingGraphicalLodParameters::initDynamicArrays(void)
+{
+ platforms.buf = NULL;
+ platforms.isAllocated = true;
+ platforms.elementSize = sizeof(NvParameterized::DummyStringStruct);
+ platforms.arraySizes[0] = 0;
+ immediateClothMap.buf = NULL;
+ immediateClothMap.isAllocated = true;
+ immediateClothMap.elementSize = sizeof(uint32_t);
+ immediateClothMap.arraySizes[0] = 0;
+ skinClothMapB.buf = NULL;
+ skinClothMapB.isAllocated = true;
+ skinClothMapB.elementSize = sizeof(SkinClothMapB_Type);
+ skinClothMapB.arraySizes[0] = 0;
+ skinClothMap.buf = NULL;
+ skinClothMap.isAllocated = true;
+ skinClothMap.elementSize = sizeof(SkinClothMapD_Type);
+ skinClothMap.arraySizes[0] = 0;
+ tetraMap.buf = NULL;
+ tetraMap.isAllocated = true;
+ tetraMap.elementSize = sizeof(TetraLink_Type);
+ tetraMap.arraySizes[0] = 0;
+ physicsMeshPartitioning.buf = NULL;
+ physicsMeshPartitioning.isAllocated = true;
+ physicsMeshPartitioning.elementSize = sizeof(PhysicsMeshPartitioning_Type);
+ physicsMeshPartitioning.arraySizes[0] = 0;
+}
+
+void ClothingGraphicalLodParameters::initDefaults(void)
+{
+
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+ lod = uint32_t(0);
+ physicalMeshId = uint32_t(-1);
+ renderMeshAssetPointer = NULL;
+ skinClothMapThickness = float(0);
+ skinClothMapOffset = float(0);
+ renderMeshAssetSorting = uint32_t(0);
+
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+}
+
+void ClothingGraphicalLodParameters::initReferences(void)
+{
+ renderMeshAsset = NULL;
+
+}
+
+void ClothingGraphicalLodParameters::freeDynamicArrays(void)
+{
+ if (platforms.isAllocated && platforms.buf)
+ {
+ mParameterizedTraits->free(platforms.buf);
+ }
+ if (immediateClothMap.isAllocated && immediateClothMap.buf)
+ {
+ mParameterizedTraits->free(immediateClothMap.buf);
+ }
+ if (skinClothMapB.isAllocated && skinClothMapB.buf)
+ {
+ mParameterizedTraits->free(skinClothMapB.buf);
+ }
+ if (skinClothMap.isAllocated && skinClothMap.buf)
+ {
+ mParameterizedTraits->free(skinClothMap.buf);
+ }
+ if (tetraMap.isAllocated && tetraMap.buf)
+ {
+ mParameterizedTraits->free(tetraMap.buf);
+ }
+ if (physicsMeshPartitioning.isAllocated && physicsMeshPartitioning.buf)
+ {
+ mParameterizedTraits->free(physicsMeshPartitioning.buf);
+ }
+}
+
+void ClothingGraphicalLodParameters::freeStrings(void)
+{
+
+ for (int i = 0; i < platforms.arraySizes[0]; ++i)
+ {
+ if (platforms.buf[i].isAllocated && platforms.buf[i].buf)
+ {
+ mParameterizedTraits->strfree((char*)platforms.buf[i].buf);
+ }
+ }
+}
+
+void ClothingGraphicalLodParameters::freeReferences(void)
+{
+ if (renderMeshAsset)
+ {
+ renderMeshAsset->destroy();
+ }
+
+}
+
+} // namespace clothing
+} // namespace nvidia
diff --git a/APEX_1.4/module/clothing/src/autogen/ClothingMaterialLibraryParameters.cpp b/APEX_1.4/module/clothing/src/autogen/ClothingMaterialLibraryParameters.cpp
new file mode 100644
index 00000000..5a0bf1c8
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/autogen/ClothingMaterialLibraryParameters.cpp
@@ -0,0 +1,1593 @@
+// 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-2015 NVIDIA Corporation. All rights reserved.
+
+// This file was generated by NvParameterized/scripts/GenParameterized.pl
+
+
+#include "ClothingMaterialLibraryParameters.h"
+#include <string.h>
+#include <stdlib.h>
+
+using namespace NvParameterized;
+
+namespace nvidia
+{
+namespace clothing
+{
+
+using namespace ClothingMaterialLibraryParametersNS;
+
+const char* const ClothingMaterialLibraryParametersFactory::vptr =
+ NvParameterized::getVptr<ClothingMaterialLibraryParameters, ClothingMaterialLibraryParameters::ClassAlignment>();
+
+const uint32_t NumParamDefs = 43;
+static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs];
+
+
+static const size_t ParamLookupChildrenTable[] =
+{
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 19, 23, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 12, 13, 14, 16, 17, 18, 20, 21, 22, 24, 25, 26,
+};
+
+#define TENUM(type) nvidia::##type
+#define CHILDREN(index) &ParamLookupChildrenTable[index]
+static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] =
+{
+ { TYPE_STRUCT, false, 0, CHILDREN(0), 1 },
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->materials), CHILDREN(1), 1 }, // materials
+ { TYPE_STRUCT, false, 1 * sizeof(ClothingMaterial_Type), CHILDREN(2), 28 }, // materials[]
+ { TYPE_STRING, false, (size_t)(&((ClothingMaterial_Type*)0)->materialName), NULL, 0 }, // materials[].materialName
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->verticalStretchingStiffness), NULL, 0 }, // materials[].verticalStretchingStiffness
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->horizontalStretchingStiffness), NULL, 0 }, // materials[].horizontalStretchingStiffness
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->bendingStiffness), NULL, 0 }, // materials[].bendingStiffness
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->shearingStiffness), NULL, 0 }, // materials[].shearingStiffness
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->tetherStiffness), NULL, 0 }, // materials[].tetherStiffness
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->tetherLimit), NULL, 0 }, // materials[].tetherLimit
+ { TYPE_BOOL, false, (size_t)(&((ClothingMaterial_Type*)0)->orthoBending), NULL, 0 }, // materials[].orthoBending
+ { TYPE_STRUCT, false, (size_t)(&((ClothingMaterial_Type*)0)->verticalStiffnessScaling), CHILDREN(30), 3 }, // materials[].verticalStiffnessScaling
+ { TYPE_F32, false, (size_t)(&((StiffnessScaling_Type*)0)->compressionRange), NULL, 0 }, // materials[].verticalStiffnessScaling.compressionRange
+ { TYPE_F32, false, (size_t)(&((StiffnessScaling_Type*)0)->stretchRange), NULL, 0 }, // materials[].verticalStiffnessScaling.stretchRange
+ { TYPE_F32, false, (size_t)(&((StiffnessScaling_Type*)0)->scale), NULL, 0 }, // materials[].verticalStiffnessScaling.scale
+ { TYPE_STRUCT, false, (size_t)(&((ClothingMaterial_Type*)0)->horizontalStiffnessScaling), CHILDREN(33), 3 }, // materials[].horizontalStiffnessScaling
+ { TYPE_F32, false, (size_t)(&((StiffnessScaling_Type*)0)->compressionRange), NULL, 0 }, // materials[].horizontalStiffnessScaling.compressionRange
+ { TYPE_F32, false, (size_t)(&((StiffnessScaling_Type*)0)->stretchRange), NULL, 0 }, // materials[].horizontalStiffnessScaling.stretchRange
+ { TYPE_F32, false, (size_t)(&((StiffnessScaling_Type*)0)->scale), NULL, 0 }, // materials[].horizontalStiffnessScaling.scale
+ { TYPE_STRUCT, false, (size_t)(&((ClothingMaterial_Type*)0)->bendingStiffnessScaling), CHILDREN(36), 3 }, // materials[].bendingStiffnessScaling
+ { TYPE_F32, false, (size_t)(&((StiffnessScaling_Type*)0)->compressionRange), NULL, 0 }, // materials[].bendingStiffnessScaling.compressionRange
+ { TYPE_F32, false, (size_t)(&((StiffnessScaling_Type*)0)->stretchRange), NULL, 0 }, // materials[].bendingStiffnessScaling.stretchRange
+ { TYPE_F32, false, (size_t)(&((StiffnessScaling_Type*)0)->scale), NULL, 0 }, // materials[].bendingStiffnessScaling.scale
+ { TYPE_STRUCT, false, (size_t)(&((ClothingMaterial_Type*)0)->shearingStiffnessScaling), CHILDREN(39), 3 }, // materials[].shearingStiffnessScaling
+ { TYPE_F32, false, (size_t)(&((StiffnessScaling_Type*)0)->compressionRange), NULL, 0 }, // materials[].shearingStiffnessScaling.compressionRange
+ { TYPE_F32, false, (size_t)(&((StiffnessScaling_Type*)0)->stretchRange), NULL, 0 }, // materials[].shearingStiffnessScaling.stretchRange
+ { TYPE_F32, false, (size_t)(&((StiffnessScaling_Type*)0)->scale), NULL, 0 }, // materials[].shearingStiffnessScaling.scale
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->damping), NULL, 0 }, // materials[].damping
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->stiffnessFrequency), NULL, 0 }, // materials[].stiffnessFrequency
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->drag), NULL, 0 }, // materials[].drag
+ { TYPE_BOOL, false, (size_t)(&((ClothingMaterial_Type*)0)->comDamping), NULL, 0 }, // materials[].comDamping
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->friction), NULL, 0 }, // materials[].friction
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->massScale), NULL, 0 }, // materials[].massScale
+ { TYPE_U32, false, (size_t)(&((ClothingMaterial_Type*)0)->solverIterations), NULL, 0 }, // materials[].solverIterations
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->solverFrequency), NULL, 0 }, // materials[].solverFrequency
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->gravityScale), NULL, 0 }, // materials[].gravityScale
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->inertiaScale), NULL, 0 }, // materials[].inertiaScale
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->hardStretchLimitation), NULL, 0 }, // materials[].hardStretchLimitation
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->maxDistanceBias), NULL, 0 }, // materials[].maxDistanceBias
+ { TYPE_U32, false, (size_t)(&((ClothingMaterial_Type*)0)->hierarchicalSolverIterations), NULL, 0 }, // materials[].hierarchicalSolverIterations
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->selfcollisionThickness), NULL, 0 }, // materials[].selfcollisionThickness
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->selfcollisionSquashScale), NULL, 0 }, // materials[].selfcollisionSquashScale
+ { TYPE_F32, false, (size_t)(&((ClothingMaterial_Type*)0)->selfcollisionStiffness), NULL, 0 }, // materials[].selfcollisionStiffness
+};
+
+
+bool ClothingMaterialLibraryParameters::mBuiltFlag = false;
+NvParameterized::MutexType ClothingMaterialLibraryParameters::mBuiltFlagMutex;
+
+ClothingMaterialLibraryParameters::ClothingMaterialLibraryParameters(NvParameterized::Traits* traits, void* buf, int32_t* refCount) :
+ NvParameters(traits, buf, refCount)
+{
+ //mParameterizedTraits->registerFactory(className(), &ClothingMaterialLibraryParametersFactoryInst);
+
+ if (!buf) //Do not init data if it is inplace-deserialized
+ {
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+ initDefaults();
+ }
+}
+
+ClothingMaterialLibraryParameters::~ClothingMaterialLibraryParameters()
+{
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+}
+
+void ClothingMaterialLibraryParameters::destroy()
+{
+ // We cache these fields here to avoid overwrite in destructor
+ bool doDeallocateSelf = mDoDeallocateSelf;
+ NvParameterized::Traits* traits = mParameterizedTraits;
+ int32_t* refCount = mRefCount;
+ void* buf = mBuffer;
+
+ this->~ClothingMaterialLibraryParameters();
+
+ NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf);
+}
+
+const NvParameterized::DefinitionImpl* ClothingMaterialLibraryParameters::getParameterDefinitionTree(void)
+{
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+const NvParameterized::DefinitionImpl* ClothingMaterialLibraryParameters::getParameterDefinitionTree(void) const
+{
+ ClothingMaterialLibraryParameters* tmpParam = const_cast<ClothingMaterialLibraryParameters*>(this);
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ tmpParam->buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+NvParameterized::ErrorType ClothingMaterialLibraryParameters::getParameterHandle(const char* long_name, Handle& handle) const
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+NvParameterized::ErrorType ClothingMaterialLibraryParameters::getParameterHandle(const char* long_name, Handle& handle)
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+void ClothingMaterialLibraryParameters::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const
+{
+ ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<ClothingMaterialLibraryParameters::ParametersStruct*>(&parameters()), handle, offset);
+}
+
+
+/* Dynamic Handle Indices */
+/* [1,0] - materials.materialName */
+
+void ClothingMaterialLibraryParameters::freeParameterDefinitionTable(NvParameterized::Traits* traits)
+{
+ if (!traits)
+ {
+ return;
+ }
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ return;
+ }
+
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+
+ if (!mBuiltFlag)
+ {
+ return;
+ }
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ ParamDefTable[i].~DefinitionImpl();
+ }
+
+ traits->free(ParamDefTable);
+
+ mBuiltFlag = false;
+}
+
+#define PDEF_PTR(index) (&ParamDefTable[index])
+
+void ClothingMaterialLibraryParameters::buildTree(void)
+{
+
+ uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs;
+ ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize));
+ memset(ParamDefTable, 0, allocSize);
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=0, longName=""
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0];
+ ParamDef->init("", TYPE_STRUCT, "STRUCT", true);
+
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=1, longName="materials"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1];
+ ParamDef->init("materials", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Array of materials that are part of this library.", true);
+ ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ static const uint8_t dynHandleIndices[2] = { 1, 0, };
+ ParamDef->setDynamicHandleIndicesMap(dynHandleIndices, 2);
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=2, longName="materials[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2];
+ ParamDef->init("materials", TYPE_STRUCT, "ClothingMaterial", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Array of materials that are part of this library.", true);
+ ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=3, longName="materials[].materialName"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3];
+ ParamDef->init("materialName", TYPE_STRING, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Material name", true);
+ ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=4, longName="materials[].verticalStretchingStiffness"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4];
+ ParamDef->init("verticalStretchingStiffness", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ HintTable[2].init("shortDescription", "Vertical stretching stiffness of the cloth in the range (0, 1]. This parameter is ignored by the PhysX 2.8.4 solver.", true);
+ ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=5, longName="materials[].horizontalStretchingStiffness"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5];
+ ParamDef->init("horizontalStretchingStiffness", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ HintTable[2].init("shortDescription", "Horizontal Stretching stiffness of the cloth in the range (0, 1].", true);
+ ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=6, longName="materials[].bendingStiffness"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6];
+ ParamDef->init("bendingStiffness", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ HintTable[2].init("shortDescription", "Bending stiffness of the cloth in the range [0, 1].", true);
+ ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=7, longName="materials[].shearingStiffness"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7];
+ ParamDef->init("shearingStiffness", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ HintTable[2].init("shortDescription", "Shearing stiffness of the cloth in the range [0, 1].", true);
+ ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=8, longName="materials[].tetherStiffness"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8];
+ ParamDef->init("tetherStiffness", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ HintTable[2].init("shortDescription", "Range [0, 1], but should be 0. The higher this value, the more the piece of clothing is allowed to stretch.", true);
+ ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=9, longName="materials[].tetherLimit"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9];
+ ParamDef->init("tetherLimit", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(4.0), true);
+ HintTable[1].init("min", double(1.0), true);
+ ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(4.0), true);
+ HintTable[1].init("min", double(1.0), true);
+ HintTable[2].init("shortDescription", "Range [1, 4], but should be 1. This scales the restlength of the tether constraints.", true);
+ ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=10, longName="materials[].orthoBending"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[10];
+ ParamDef->init("orthoBending", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Bending is modeled via an angular spring between adjacent triangles. This mode is slower but independent of stretching resistance.\n", true);
+ HintTable[1].init("shortDescription", "Enable/disable orthogonal bending resistance.", true);
+ ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=11, longName="materials[].verticalStiffnessScaling"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[11];
+ ParamDef->init("verticalStiffnessScaling", TYPE_STRUCT, "StiffnessScaling", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Vertical stiffness scaling", true);
+ ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=12, longName="materials[].verticalStiffnessScaling.compressionRange"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[12];
+ ParamDef->init("compressionRange", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[4];
+ static Hint* HintPtrTable[4] = { &HintTable[0], &HintTable[1], &HintTable[2], &HintTable[3], };
+ HintTable[0].init("longDescription", "For any edge where the simulated length is within the range [restlength, compressionRange*restlength],\nthe scale will be multiplied on top of the regular stiffness.\nThis is can be used to allow the cloth to compress more easily up to a certain limit.\n", true);
+ HintTable[1].init("max", double(1.0), true);
+ HintTable[2].init("min", double(0.0), true);
+ HintTable[3].init("shortDescription", "Multiplier relative to rest length that defines where the stiffness is scaled down to allow compression.", true);
+ ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 4);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=13, longName="materials[].verticalStiffnessScaling.stretchRange"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[13];
+ ParamDef->init("stretchRange", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("min", double(1.0), true);
+ ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("longDescription", "For any edge where the simulated length is within the range [restlength, stretchRange*restlength],\nthe scale will be multiplied on top of the regular stiffness.\nThis is can be used to allow the cloth to stretch more easily up to a certain limit.\n", true);
+ HintTable[1].init("min", double(1.0), true);
+ HintTable[2].init("shortDescription", "Multiplier relative to rest length that defines the range where the stiffness is scaled down to allow stretching.", true);
+ ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=14, longName="materials[].verticalStiffnessScaling.scale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[14];
+ ParamDef->init("scale", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[14].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ HintTable[2].init("shortDescription", "Stiffness scale [0, 1] applied when inside the scaling range.", true);
+ ParamDefTable[14].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=15, longName="materials[].horizontalStiffnessScaling"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[15];
+ ParamDef->init("horizontalStiffnessScaling", TYPE_STRUCT, "StiffnessScaling", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Horizontal stiffness scaling", true);
+ ParamDefTable[15].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=16, longName="materials[].horizontalStiffnessScaling.compressionRange"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[16];
+ ParamDef->init("compressionRange", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[16].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[4];
+ static Hint* HintPtrTable[4] = { &HintTable[0], &HintTable[1], &HintTable[2], &HintTable[3], };
+ HintTable[0].init("longDescription", "For any edge where the simulated length is within the range [restlength, compressionRange*restlength],\nthe scale will be multiplied on top of the regular stiffness.\nThis is can be used to allow the cloth to compress more easily up to a certain limit.\n", true);
+ HintTable[1].init("max", double(1.0), true);
+ HintTable[2].init("min", double(0.0), true);
+ HintTable[3].init("shortDescription", "Multiplier relative to rest length that defines where the stiffness is scaled down to allow compression.", true);
+ ParamDefTable[16].setHints((const NvParameterized::Hint**)HintPtrTable, 4);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=17, longName="materials[].horizontalStiffnessScaling.stretchRange"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[17];
+ ParamDef->init("stretchRange", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("min", double(1.0), true);
+ ParamDefTable[17].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("longDescription", "For any edge where the simulated length is within the range [restlength, stretchRange*restlength],\nthe scale will be multiplied on top of the regular stiffness.\nThis is can be used to allow the cloth to stretch more easily up to a certain limit.\n", true);
+ HintTable[1].init("min", double(1.0), true);
+ HintTable[2].init("shortDescription", "Multiplier relative to rest length that defines the range where the stiffness is scaled down to allow stretching.", true);
+ ParamDefTable[17].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=18, longName="materials[].horizontalStiffnessScaling.scale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[18];
+ ParamDef->init("scale", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[18].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ HintTable[2].init("shortDescription", "Stiffness scale [0, 1] applied when inside the scaling range.", true);
+ ParamDefTable[18].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=19, longName="materials[].bendingStiffnessScaling"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[19];
+ ParamDef->init("bendingStiffnessScaling", TYPE_STRUCT, "StiffnessScaling", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Bending stiffness scaling", true);
+ ParamDefTable[19].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=20, longName="materials[].bendingStiffnessScaling.compressionRange"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[20];
+ ParamDef->init("compressionRange", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[20].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[4];
+ static Hint* HintPtrTable[4] = { &HintTable[0], &HintTable[1], &HintTable[2], &HintTable[3], };
+ HintTable[0].init("longDescription", "For any edge where the simulated length is within the range [restlength, compressionRange*restlength],\nthe scale will be multiplied on top of the regular stiffness.\nThis is can be used to allow the cloth to compress more easily up to a certain limit.\n", true);
+ HintTable[1].init("max", double(1.0), true);
+ HintTable[2].init("min", double(0.0), true);
+ HintTable[3].init("shortDescription", "Multiplier relative to rest length that defines where the stiffness is scaled down to allow compression.", true);
+ ParamDefTable[20].setHints((const NvParameterized::Hint**)HintPtrTable, 4);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=21, longName="materials[].bendingStiffnessScaling.stretchRange"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[21];
+ ParamDef->init("stretchRange", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("min", double(1.0), true);
+ ParamDefTable[21].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("longDescription", "For any edge where the simulated length is within the range [restlength, stretchRange*restlength],\nthe scale will be multiplied on top of the regular stiffness.\nThis is can be used to allow the cloth to stretch more easily up to a certain limit.\n", true);
+ HintTable[1].init("min", double(1.0), true);
+ HintTable[2].init("shortDescription", "Multiplier relative to rest length that defines the range where the stiffness is scaled down to allow stretching.", true);
+ ParamDefTable[21].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=22, longName="materials[].bendingStiffnessScaling.scale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[22];
+ ParamDef->init("scale", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[22].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ HintTable[2].init("shortDescription", "Stiffness scale [0, 1] applied when inside the scaling range.", true);
+ ParamDefTable[22].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=23, longName="materials[].shearingStiffnessScaling"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[23];
+ ParamDef->init("shearingStiffnessScaling", TYPE_STRUCT, "StiffnessScaling", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Shearing stiffness scaling", true);
+ ParamDefTable[23].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=24, longName="materials[].shearingStiffnessScaling.compressionRange"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[24];
+ ParamDef->init("compressionRange", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[24].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[4];
+ static Hint* HintPtrTable[4] = { &HintTable[0], &HintTable[1], &HintTable[2], &HintTable[3], };
+ HintTable[0].init("longDescription", "For any edge where the simulated length is within the range [restlength, compressionRange*restlength],\nthe scale will be multiplied on top of the regular stiffness.\nThis is can be used to allow the cloth to compress more easily up to a certain limit.\n", true);
+ HintTable[1].init("max", double(1.0), true);
+ HintTable[2].init("min", double(0.0), true);
+ HintTable[3].init("shortDescription", "Multiplier relative to rest length that defines where the stiffness is scaled down to allow compression.", true);
+ ParamDefTable[24].setHints((const NvParameterized::Hint**)HintPtrTable, 4);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=25, longName="materials[].shearingStiffnessScaling.stretchRange"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[25];
+ ParamDef->init("stretchRange", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("min", double(1.0), true);
+ ParamDefTable[25].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("longDescription", "For any edge where the simulated length is within the range [restlength, stretchRange*restlength],\nthe scale will be multiplied on top of the regular stiffness.\nThis is can be used to allow the cloth to stretch more easily up to a certain limit.\n", true);
+ HintTable[1].init("min", double(1.0), true);
+ HintTable[2].init("shortDescription", "Multiplier relative to rest length that defines the range where the stiffness is scaled down to allow stretching.", true);
+ ParamDefTable[25].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=26, longName="materials[].shearingStiffnessScaling.scale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[26];
+ ParamDef->init("scale", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[26].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ HintTable[2].init("shortDescription", "Stiffness scale [0, 1] applied when inside the scaling range.", true);
+ ParamDefTable[26].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=27, longName="materials[].damping"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[27];
+ ParamDef->init("damping", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[27].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ HintTable[2].init("shortDescription", "Spring damping of the cloth in the range [0, 1]", true);
+ ParamDefTable[27].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=28, longName="materials[].stiffnessFrequency"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[28];
+ ParamDef->init("stiffnessFrequency", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(500.0), true);
+ HintTable[1].init("min", double(10.0), true);
+ ParamDefTable[28].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(500.0), true);
+ HintTable[1].init("min", double(10.0), true);
+ HintTable[2].init("shortDescription", "Scales linearity of behavior for the varous stiffness values in the interval (0, 1)", true);
+ ParamDefTable[28].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=29, longName="materials[].drag"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[29];
+ ParamDef->init("drag", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[29].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[4];
+ static Hint* HintPtrTable[4] = { &HintTable[0], &HintTable[1], &HintTable[2], &HintTable[3], };
+ HintTable[0].init("longDescription", "The drag coefficient is the portion of local frame velocity that is applied to each particle.\n", true);
+ HintTable[1].init("max", double(1.0), true);
+ HintTable[2].init("min", double(0.0), true);
+ HintTable[3].init("shortDescription", "Drag coefficient n the range [0, 1]", true);
+ ParamDefTable[29].setHints((const NvParameterized::Hint**)HintPtrTable, 4);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=30, longName="materials[].comDamping"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[30];
+ ParamDef->init("comDamping", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "If set, the global rigid body modes (translation and rotation) are extracted from damping. This way, the cloth\ncan freely move and rotate even under high damping.\n", true);
+ HintTable[1].init("shortDescription", "Enable/disable center of mass damping of internal velocities.", true);
+ ParamDefTable[30].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=31, longName="materials[].friction"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[31];
+ ParamDef->init("friction", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[31].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[4];
+ static Hint* HintPtrTable[4] = { &HintTable[0], &HintTable[1], &HintTable[2], &HintTable[3], };
+ HintTable[0].init("longDescription", "Currently only spheres and capsules impose friction on the colliding particles.", true);
+ HintTable[1].init("max", double(1.0), true);
+ HintTable[2].init("min", double(0.0), true);
+ HintTable[3].init("shortDescription", "Friction coefficient in the range [0, 1]", true);
+ ParamDefTable[31].setHints((const NvParameterized::Hint**)HintPtrTable, 4);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=32, longName="materials[].massScale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[32];
+ ParamDef->init("massScale", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(100.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[32].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("max", double(100.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ HintTable[2].init("shortDescription", "Controls the amount of mass scaling during collision [0, 100]", true);
+ ParamDefTable[32].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=33, longName="materials[].solverIterations"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[33];
+ ParamDef->init("solverIterations", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("min", uint64_t(1), true);
+ ParamDefTable[33].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("longDescription", "Small numbers make the simulation faster while the cloth gets less stiff.\n", true);
+ HintTable[1].init("min", uint64_t(1), true);
+ HintTable[2].init("shortDescription", "Number of solver iterations. For 2.x cloth", true);
+ ParamDefTable[33].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=34, longName="materials[].solverFrequency"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[34];
+ ParamDef->init("solverFrequency", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("min", uint64_t(20), true);
+ ParamDefTable[34].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("longDescription", "Small numbers make the simulation faster while the cloth gets less stiff.\n", true);
+ HintTable[1].init("min", uint64_t(20), true);
+ HintTable[2].init("shortDescription", "Number of solver iterations per second. For 3.x cloth", true);
+ ParamDefTable[34].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=35, longName="materials[].gravityScale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[35];
+ ParamDef->init("gravityScale", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "A value of 0 will make the cloth ignore gravity, a value of 10 will apply 10 times the gravity.\n", true);
+ HintTable[1].init("shortDescription", "Amount of gravity that is applied to the cloth.", true);
+ ParamDefTable[35].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=36, longName="materials[].inertiaScale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[36];
+ ParamDef->init("inertiaScale", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[36].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[4];
+ static Hint* HintPtrTable[4] = { &HintTable[0], &HintTable[1], &HintTable[2], &HintTable[3], };
+ HintTable[0].init("longDescription", "A value of 0 will make the cloth move in global space without inertia, a value of 1 will keep all inertia.\n", true);
+ HintTable[1].init("max", double(1.0), true);
+ HintTable[2].init("min", double(0.0), true);
+ HintTable[3].init("shortDescription", "Amount of inertia that is kept when using local space simulation.", true);
+ ParamDefTable[36].setHints((const NvParameterized::Hint**)HintPtrTable, 4);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=37, longName="materials[].hardStretchLimitation"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[37];
+ ParamDef->init("hardStretchLimitation", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(2.0), true);
+ HintTable[1].init("min", double(0.0), true);
+ ParamDefTable[37].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[4];
+ static Hint* HintPtrTable[4] = { &HintTable[0], &HintTable[1], &HintTable[2], &HintTable[3], };
+ HintTable[0].init("longDescription", "Good values are usually between 1 and 1.1. Any value >= 1 will guarantee that a certain set of edges is not longer\nthan that value times the initial rest length.\n", true);
+ HintTable[1].init("max", double(2.0), true);
+ HintTable[2].init("min", double(0.0), true);
+ HintTable[3].init("shortDescription", "Make cloth simulation less stretchy. A value smaller than 1 will turn it off.", true);
+ ParamDefTable[37].setHints((const NvParameterized::Hint**)HintPtrTable, 4);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=38, longName="materials[].maxDistanceBias"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[38];
+ ParamDef->init("maxDistanceBias", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("max", double(1.0), true);
+ HintTable[1].init("min", double(-1.0), true);
+ ParamDefTable[38].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[4];
+ static Hint* HintPtrTable[4] = { &HintTable[0], &HintTable[1], &HintTable[2], &HintTable[3], };
+ HintTable[0].init("longDescription", "A value smaller than 0 will turn the sphere into a capsule and eventually a line (at value -1) along the normal of the vertex.\nA value bigger than 0 will turn the sphere into a disc.\n", true);
+ HintTable[1].init("max", double(1.0), true);
+ HintTable[2].init("min", double(-1.0), true);
+ HintTable[3].init("shortDescription", "Deform the max distance sphere into a capsule or a disc.", true);
+ ParamDefTable[38].setHints((const NvParameterized::Hint**)HintPtrTable, 4);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=39, longName="materials[].hierarchicalSolverIterations"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[39];
+ ParamDef->init("hierarchicalSolverIterations", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("min", uint64_t(0), true);
+ ParamDefTable[39].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("min", uint64_t(0), true);
+ HintTable[1].init("shortDescription", "Number of iterations of the hierarchical cloth solver.", true);
+ ParamDefTable[39].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=40, longName="materials[].selfcollisionThickness"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[40];
+ ParamDef->init("selfcollisionThickness", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "This feature prevents meshes from self-intersecting. Only works properly when configured properly.", true);
+ HintTable[1].init("shortDescription", "Minimal amount of distance particles will keep of each other.", true);
+ ParamDefTable[40].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=41, longName="materials[].selfcollisionSquashScale"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[41];
+ ParamDef->init("selfcollisionSquashScale", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "This feature prevents self collision thickness becoming too high for low resolution cloth.", true);
+ HintTable[1].init("shortDescription", "Amount of thickness scaling along surface normal.", true);
+ ParamDefTable[41].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=42, longName="materials[].selfcollisionStiffness"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[42];
+ ParamDef->init("selfcollisionStiffness", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "This feature prevents meshes from self-intersecting. Only works properly when configured properly.", true);
+ HintTable[1].init("shortDescription", "Stiffness of self collision solver.", true);
+ ParamDefTable[42].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // SetChildren for: nodeIndex=0, longName=""
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(1);
+
+ ParamDefTable[0].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=1, longName="materials"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(2);
+
+ ParamDefTable[1].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=2, longName="materials[]"
+ {
+ static Definition* Children[28];
+ Children[0] = PDEF_PTR(3);
+ Children[1] = PDEF_PTR(4);
+ Children[2] = PDEF_PTR(5);
+ Children[3] = PDEF_PTR(6);
+ Children[4] = PDEF_PTR(7);
+ Children[5] = PDEF_PTR(8);
+ Children[6] = PDEF_PTR(9);
+ Children[7] = PDEF_PTR(10);
+ Children[8] = PDEF_PTR(11);
+ Children[9] = PDEF_PTR(15);
+ Children[10] = PDEF_PTR(19);
+ Children[11] = PDEF_PTR(23);
+ Children[12] = PDEF_PTR(27);
+ Children[13] = PDEF_PTR(28);
+ Children[14] = PDEF_PTR(29);
+ Children[15] = PDEF_PTR(30);
+ Children[16] = PDEF_PTR(31);
+ Children[17] = PDEF_PTR(32);
+ Children[18] = PDEF_PTR(33);
+ Children[19] = PDEF_PTR(34);
+ Children[20] = PDEF_PTR(35);
+ Children[21] = PDEF_PTR(36);
+ Children[22] = PDEF_PTR(37);
+ Children[23] = PDEF_PTR(38);
+ Children[24] = PDEF_PTR(39);
+ Children[25] = PDEF_PTR(40);
+ Children[26] = PDEF_PTR(41);
+ Children[27] = PDEF_PTR(42);
+
+ ParamDefTable[2].setChildren(Children, 28);
+ }
+
+ // SetChildren for: nodeIndex=11, longName="materials[].verticalStiffnessScaling"
+ {
+ static Definition* Children[3];
+ Children[0] = PDEF_PTR(12);
+ Children[1] = PDEF_PTR(13);
+ Children[2] = PDEF_PTR(14);
+
+ ParamDefTable[11].setChildren(Children, 3);
+ }
+
+ // SetChildren for: nodeIndex=15, longName="materials[].horizontalStiffnessScaling"
+ {
+ static Definition* Children[3];
+ Children[0] = PDEF_PTR(16);
+ Children[1] = PDEF_PTR(17);
+ Children[2] = PDEF_PTR(18);
+
+ ParamDefTable[15].setChildren(Children, 3);
+ }
+
+ // SetChildren for: nodeIndex=19, longName="materials[].bendingStiffnessScaling"
+ {
+ static Definition* Children[3];
+ Children[0] = PDEF_PTR(20);
+ Children[1] = PDEF_PTR(21);
+ Children[2] = PDEF_PTR(22);
+
+ ParamDefTable[19].setChildren(Children, 3);
+ }
+
+ // SetChildren for: nodeIndex=23, longName="materials[].shearingStiffnessScaling"
+ {
+ static Definition* Children[3];
+ Children[0] = PDEF_PTR(24);
+ Children[1] = PDEF_PTR(25);
+ Children[2] = PDEF_PTR(26);
+
+ ParamDefTable[23].setChildren(Children, 3);
+ }
+
+ mBuiltFlag = true;
+
+}
+void ClothingMaterialLibraryParameters::initStrings(void)
+{
+}
+
+void ClothingMaterialLibraryParameters::initDynamicArrays(void)
+{
+ materials.buf = NULL;
+ materials.isAllocated = true;
+ materials.elementSize = sizeof(ClothingMaterial_Type);
+ materials.arraySizes[0] = 0;
+}
+
+void ClothingMaterialLibraryParameters::initDefaults(void)
+{
+
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+}
+
+void ClothingMaterialLibraryParameters::initReferences(void)
+{
+}
+
+void ClothingMaterialLibraryParameters::freeDynamicArrays(void)
+{
+ if (materials.isAllocated && materials.buf)
+ {
+ mParameterizedTraits->free(materials.buf);
+ }
+}
+
+void ClothingMaterialLibraryParameters::freeStrings(void)
+{
+
+ for (int i = 0; i < materials.arraySizes[0]; ++i)
+ {
+ if (materials.buf[i].materialName.isAllocated && materials.buf[i].materialName.buf)
+ {
+ mParameterizedTraits->strfree((char*)materials.buf[i].materialName.buf);
+ }
+ }
+}
+
+void ClothingMaterialLibraryParameters::freeReferences(void)
+{
+}
+
+} // namespace clothing
+} // namespace nvidia
diff --git a/APEX_1.4/module/clothing/src/autogen/ClothingModuleParameters.cpp b/APEX_1.4/module/clothing/src/autogen/ClothingModuleParameters.cpp
new file mode 100644
index 00000000..b6e4e0e6
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/autogen/ClothingModuleParameters.cpp
@@ -0,0 +1,583 @@
+// 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-2015 NVIDIA Corporation. All rights reserved.
+
+// This file was generated by NvParameterized/scripts/GenParameterized.pl
+
+
+#include "ClothingModuleParameters.h"
+#include <string.h>
+#include <stdlib.h>
+
+using namespace NvParameterized;
+
+namespace nvidia
+{
+namespace clothing
+{
+
+using namespace ClothingModuleParametersNS;
+
+const char* const ClothingModuleParametersFactory::vptr =
+ NvParameterized::getVptr<ClothingModuleParameters, ClothingModuleParameters::ClassAlignment>();
+
+const uint32_t NumParamDefs = 12;
+static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs];
+
+
+static const size_t ParamLookupChildrenTable[] =
+{
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+};
+
+#define TENUM(type) nvidia::##type
+#define CHILDREN(index) &ParamLookupChildrenTable[index]
+static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] =
+{
+ { TYPE_STRUCT, false, 0, CHILDREN(0), 11 },
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->maxNumCompartments), NULL, 0 }, // maxNumCompartments
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->maxUnusedPhysXResources), NULL, 0 }, // maxUnusedPhysXResources
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->allowAsyncCooking), NULL, 0 }, // allowAsyncCooking
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->asyncFetchResults), NULL, 0 }, // asyncFetchResults
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->avgSimFrequencyWindow), NULL, 0 }, // avgSimFrequencyWindow
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->allowApexWorkBetweenSubsteps), NULL, 0 }, // allowApexWorkBetweenSubsteps
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->interCollisionDistance), NULL, 0 }, // interCollisionDistance
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->interCollisionStiffness), NULL, 0 }, // interCollisionStiffness
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->interCollisionIterations), NULL, 0 }, // interCollisionIterations
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->sparseSelfCollision), NULL, 0 }, // sparseSelfCollision
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->maxTimeRenderProxyInPool), NULL, 0 }, // maxTimeRenderProxyInPool
+};
+
+
+bool ClothingModuleParameters::mBuiltFlag = false;
+NvParameterized::MutexType ClothingModuleParameters::mBuiltFlagMutex;
+
+ClothingModuleParameters::ClothingModuleParameters(NvParameterized::Traits* traits, void* buf, int32_t* refCount) :
+ NvParameters(traits, buf, refCount)
+{
+ //mParameterizedTraits->registerFactory(className(), &ClothingModuleParametersFactoryInst);
+
+ if (!buf) //Do not init data if it is inplace-deserialized
+ {
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+ initDefaults();
+ }
+}
+
+ClothingModuleParameters::~ClothingModuleParameters()
+{
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+}
+
+void ClothingModuleParameters::destroy()
+{
+ // We cache these fields here to avoid overwrite in destructor
+ bool doDeallocateSelf = mDoDeallocateSelf;
+ NvParameterized::Traits* traits = mParameterizedTraits;
+ int32_t* refCount = mRefCount;
+ void* buf = mBuffer;
+
+ this->~ClothingModuleParameters();
+
+ NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf);
+}
+
+const NvParameterized::DefinitionImpl* ClothingModuleParameters::getParameterDefinitionTree(void)
+{
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+const NvParameterized::DefinitionImpl* ClothingModuleParameters::getParameterDefinitionTree(void) const
+{
+ ClothingModuleParameters* tmpParam = const_cast<ClothingModuleParameters*>(this);
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ tmpParam->buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+NvParameterized::ErrorType ClothingModuleParameters::getParameterHandle(const char* long_name, Handle& handle) const
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+NvParameterized::ErrorType ClothingModuleParameters::getParameterHandle(const char* long_name, Handle& handle)
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+void ClothingModuleParameters::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const
+{
+ ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<ClothingModuleParameters::ParametersStruct*>(&parameters()), handle, offset);
+}
+
+
+/* Dynamic Handle Indices */
+
+void ClothingModuleParameters::freeParameterDefinitionTable(NvParameterized::Traits* traits)
+{
+ if (!traits)
+ {
+ return;
+ }
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ return;
+ }
+
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+
+ if (!mBuiltFlag)
+ {
+ return;
+ }
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ ParamDefTable[i].~DefinitionImpl();
+ }
+
+ traits->free(ParamDefTable);
+
+ mBuiltFlag = false;
+}
+
+#define PDEF_PTR(index) (&ParamDefTable[index])
+
+void ClothingModuleParameters::buildTree(void)
+{
+
+ uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs;
+ ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize));
+ memset(ParamDefTable, 0, allocSize);
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=0, longName=""
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0];
+ ParamDef->init("", TYPE_STRUCT, "STRUCT", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "This class is used for initializing the NxModuleClothing.", true);
+ ParamDefTable[0].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=1, longName="maxNumCompartments"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1];
+ ParamDef->init("maxNumCompartments", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("defaultValueConsoles", uint64_t(0), true);
+ HintTable[1].init("defaultValueWindows", uint64_t(4), true);
+ ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#else
+
+ static HintImpl HintTable[4];
+ static Hint* HintPtrTable[4] = { &HintTable[0], &HintTable[1], &HintTable[2], &HintTable[3], };
+ HintTable[0].init("defaultValueConsoles", uint64_t(0), true);
+ HintTable[1].init("defaultValueWindows", uint64_t(4), true);
+ HintTable[2].init("longDescription", "To parallelize work hw cloth, sw cloth, hw softbodies and sw softbodies are distributed into different compartments. For each type maximally maxNumCompartments compartments are created in a scene.", true);
+ HintTable[3].init("shortDescription", "Maximum number of compartments to distribute the cloths and softbodies of the same type. Works only with PhysX 2.8.4", true);
+ ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 4);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=2, longName="maxUnusedPhysXResources"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2];
+ ParamDef->init("maxUnusedPhysXResources", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Not used instances are generated when NxClothingActors are released or their benefit is not high enough to allow simulation. Then they will return the NxCloth/NxSoftBody and the list of NxActors to their asset where it will be cached until another NxClothingActor needs them.", true);
+ HintTable[1].init("shortDescription", "Maximum number of NxCloth/NxSoftBody instances that are not used.", true);
+ ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=3, longName="allowAsyncCooking"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3];
+ ParamDef->init("allowAsyncCooking", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "This can be turned off if unexpected bugs/crashes occur.", true);
+ HintTable[1].init("shortDescription", "ClothingActors will cook in a background thread to speed up creation time.", true);
+ ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=4, longName="asyncFetchResults"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4];
+ ParamDef->init("asyncFetchResults", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Note that ApexPostTickTime from the scene stats will not be correct if true. Caution: Do not set this to false when simulate and/or fetchResults is called from a PxTask. fetchResults can block and wait for other tasks in this case, which can cause a deadlock if the dispatcher is using only 1 workerthread.", true);
+ HintTable[1].init("shortDescription", "Let fetch results tasks run longer than the fetchResults call, they will block at the next updateRenderResource call.", true);
+ ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=5, longName="avgSimFrequencyWindow"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5];
+ ParamDef->init("avgSimFrequencyWindow", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Average Simulation Frequency is estimated with the last n frames", true);
+ ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=6, longName="allowApexWorkBetweenSubsteps"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6];
+ ParamDef->init("allowApexWorkBetweenSubsteps", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "The clothing module can interpolate matrices between substeps. However, for this APEX needs to call simulate/fetchResults several times per frame. This causes problems if physX particles are handled by the application in the same scene. The application needs to be able to read particle buffers with deletion IDs after each fetchResults, which is not possible in that case. Use allowApexWorkBetweenSubsteps to enable matrix interpolation between substeps.", true);
+ HintTable[1].init("shortDescription", "Allow APEX SDK to interpolate clothing matrices between the substeps.", true);
+ ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=7, longName="interCollisionDistance"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7];
+ ParamDef->init("interCollisionDistance", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Experimental. Set the radius to 0.0 to disable inter-collision.", true);
+ HintTable[1].init("shortDescription", "Experimental. Radius of the collision between different clothing actors. (3.x solver mode)", true);
+ ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=8, longName="interCollisionStiffness"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8];
+ ParamDef->init("interCollisionStiffness", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Experimental. Stiffness of the collision between different clothing actors. (3.x solver mode)", true);
+ ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=9, longName="interCollisionIterations"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9];
+ ParamDef->init("interCollisionIterations", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Experimental. Number of Iterations for the collision between different clothing actors. (3.x solver mode)", true);
+ ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=10, longName="sparseSelfCollision"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[10];
+ ParamDef->init("sparseSelfCollision", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Experimental. The particle subset is part of the cooked data and depends on the assets selfCollision radius.", true);
+ HintTable[1].init("shortDescription", "Experimental. Only use a subset of particles for self-collision. (3.x solver mode)", true);
+ ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=11, longName="maxTimeRenderProxyInPool"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[11];
+ ParamDef->init("maxTimeRenderProxyInPool", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Maximum number of frames a RenderProxy object can stay the object pool before the memory is released", true);
+ ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // SetChildren for: nodeIndex=0, longName=""
+ {
+ static Definition* Children[11];
+ Children[0] = PDEF_PTR(1);
+ Children[1] = PDEF_PTR(2);
+ Children[2] = PDEF_PTR(3);
+ Children[3] = PDEF_PTR(4);
+ Children[4] = PDEF_PTR(5);
+ Children[5] = PDEF_PTR(6);
+ Children[6] = PDEF_PTR(7);
+ Children[7] = PDEF_PTR(8);
+ Children[8] = PDEF_PTR(9);
+ Children[9] = PDEF_PTR(10);
+ Children[10] = PDEF_PTR(11);
+
+ ParamDefTable[0].setChildren(Children, 11);
+ }
+
+ mBuiltFlag = true;
+
+}
+void ClothingModuleParameters::initStrings(void)
+{
+}
+
+void ClothingModuleParameters::initDynamicArrays(void)
+{
+}
+
+void ClothingModuleParameters::initDefaults(void)
+{
+
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+ maxNumCompartments = uint32_t(4);
+ maxUnusedPhysXResources = uint32_t(5);
+ allowAsyncCooking = bool(true);
+ asyncFetchResults = bool(true);
+ avgSimFrequencyWindow = uint32_t(60);
+ allowApexWorkBetweenSubsteps = bool(false);
+ interCollisionDistance = float(0.0);
+ interCollisionStiffness = float(1.0);
+ interCollisionIterations = uint32_t(1);
+ sparseSelfCollision = bool(false);
+ maxTimeRenderProxyInPool = uint32_t(100);
+
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+}
+
+void ClothingModuleParameters::initReferences(void)
+{
+}
+
+void ClothingModuleParameters::freeDynamicArrays(void)
+{
+}
+
+void ClothingModuleParameters::freeStrings(void)
+{
+}
+
+void ClothingModuleParameters::freeReferences(void)
+{
+}
+
+} // namespace clothing
+} // namespace nvidia
diff --git a/APEX_1.4/module/clothing/src/autogen/ClothingPhysicalMeshParameters.cpp b/APEX_1.4/module/clothing/src/autogen/ClothingPhysicalMeshParameters.cpp
new file mode 100644
index 00000000..de67c1a9
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/autogen/ClothingPhysicalMeshParameters.cpp
@@ -0,0 +1,2418 @@
+// 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-2015 NVIDIA Corporation. All rights reserved.
+
+// This file was generated by NvParameterized/scripts/GenParameterized.pl
+
+
+#include "ClothingPhysicalMeshParameters.h"
+#include <string.h>
+#include <stdlib.h>
+
+using namespace NvParameterized;
+
+namespace nvidia
+{
+namespace clothing
+{
+
+using namespace ClothingPhysicalMeshParametersNS;
+
+const char* const ClothingPhysicalMeshParametersFactory::vptr =
+ NvParameterized::getVptr<ClothingPhysicalMeshParameters, ClothingPhysicalMeshParameters::ClassAlignment>();
+
+const uint32_t NumParamDefs = 74;
+static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs];
+
+
+static const size_t ParamLookupChildrenTable[] =
+{
+ 1, 35, 43, 52, 53, 54, 62, 71, 72, 73, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 19, 21, 23,
+ 25, 26, 27, 29, 30, 31, 32, 33, 34, 9, 11, 13, 15, 16, 17, 18, 20, 22, 24, 28, 36,
+ 37, 38, 39, 40, 41, 42, 44, 45, 46, 47, 48, 49, 50, 51, 55, 56, 57, 58, 59, 60, 61,
+ 63, 64, 65, 66, 67, 68, 69, 70,
+};
+
+#define TENUM(type) nvidia::##type
+#define CHILDREN(index) &ParamLookupChildrenTable[index]
+static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] =
+{
+ { TYPE_STRUCT, false, 0, CHILDREN(0), 10 },
+ { TYPE_STRUCT, false, (size_t)(&((ParametersStruct*)0)->physicalMesh), CHILDREN(10), 22 }, // physicalMesh
+ { TYPE_U32, false, (size_t)(&((PhysicalMesh_Type*)0)->numVertices), NULL, 0 }, // physicalMesh.numVertices
+ { TYPE_U32, false, (size_t)(&((PhysicalMesh_Type*)0)->numSimulatedVertices), NULL, 0 }, // physicalMesh.numSimulatedVertices
+ { TYPE_U32, false, (size_t)(&((PhysicalMesh_Type*)0)->numMaxDistance0Vertices), NULL, 0 }, // physicalMesh.numMaxDistance0Vertices
+ { TYPE_U32, false, (size_t)(&((PhysicalMesh_Type*)0)->numIndices), NULL, 0 }, // physicalMesh.numIndices
+ { TYPE_U32, false, (size_t)(&((PhysicalMesh_Type*)0)->numSimulatedIndices), NULL, 0 }, // physicalMesh.numSimulatedIndices
+ { TYPE_U32, false, (size_t)(&((PhysicalMesh_Type*)0)->numBonesPerVertex), NULL, 0 }, // physicalMesh.numBonesPerVertex
+ { TYPE_ARRAY, true, (size_t)(&((PhysicalMesh_Type*)0)->vertices), CHILDREN(32), 1 }, // physicalMesh.vertices
+ { TYPE_VEC3, false, 1 * sizeof(physx::PxVec3), NULL, 0 }, // physicalMesh.vertices[]
+ { TYPE_ARRAY, true, (size_t)(&((PhysicalMesh_Type*)0)->normals), CHILDREN(33), 1 }, // physicalMesh.normals
+ { TYPE_VEC3, false, 1 * sizeof(physx::PxVec3), NULL, 0 }, // physicalMesh.normals[]
+ { TYPE_ARRAY, true, (size_t)(&((PhysicalMesh_Type*)0)->skinningNormals), CHILDREN(34), 1 }, // physicalMesh.skinningNormals
+ { TYPE_VEC3, false, 1 * sizeof(physx::PxVec3), NULL, 0 }, // physicalMesh.skinningNormals[]
+ { TYPE_ARRAY, true, (size_t)(&((PhysicalMesh_Type*)0)->constrainCoefficients), CHILDREN(35), 1 }, // physicalMesh.constrainCoefficients
+ { TYPE_STRUCT, false, 1 * sizeof(ConstrainCoefficient_Type), CHILDREN(36), 3 }, // physicalMesh.constrainCoefficients[]
+ { TYPE_F32, false, (size_t)(&((ConstrainCoefficient_Type*)0)->maxDistance), NULL, 0 }, // physicalMesh.constrainCoefficients[].maxDistance
+ { TYPE_F32, false, (size_t)(&((ConstrainCoefficient_Type*)0)->collisionSphereRadius), NULL, 0 }, // physicalMesh.constrainCoefficients[].collisionSphereRadius
+ { TYPE_F32, false, (size_t)(&((ConstrainCoefficient_Type*)0)->collisionSphereDistance), NULL, 0 }, // physicalMesh.constrainCoefficients[].collisionSphereDistance
+ { TYPE_ARRAY, true, (size_t)(&((PhysicalMesh_Type*)0)->boneIndices), CHILDREN(39), 1 }, // physicalMesh.boneIndices
+ { TYPE_U16, false, 1 * sizeof(uint16_t), NULL, 0 }, // physicalMesh.boneIndices[]
+ { TYPE_ARRAY, true, (size_t)(&((PhysicalMesh_Type*)0)->boneWeights), CHILDREN(40), 1 }, // physicalMesh.boneWeights
+ { TYPE_F32, false, 1 * sizeof(float), NULL, 0 }, // physicalMesh.boneWeights[]
+ { TYPE_ARRAY, true, (size_t)(&((PhysicalMesh_Type*)0)->optimizationData), CHILDREN(41), 1 }, // physicalMesh.optimizationData
+ { TYPE_U8, false, 1 * sizeof(uint8_t), NULL, 0 }, // physicalMesh.optimizationData[]
+ { TYPE_BOOL, false, (size_t)(&((PhysicalMesh_Type*)0)->hasNegativeBackstop), NULL, 0 }, // physicalMesh.hasNegativeBackstop
+ { TYPE_BOOL, false, (size_t)(&((PhysicalMesh_Type*)0)->isClosed), NULL, 0 }, // physicalMesh.isClosed
+ { TYPE_ARRAY, true, (size_t)(&((PhysicalMesh_Type*)0)->indices), CHILDREN(42), 1 }, // physicalMesh.indices
+ { TYPE_U32, false, 1 * sizeof(uint32_t), NULL, 0 }, // physicalMesh.indices[]
+ { TYPE_F32, false, (size_t)(&((PhysicalMesh_Type*)0)->maximumMaxDistance), NULL, 0 }, // physicalMesh.maximumMaxDistance
+ { TYPE_U32, false, (size_t)(&((PhysicalMesh_Type*)0)->physicalMeshSorting), NULL, 0 }, // physicalMesh.physicalMeshSorting
+ { TYPE_F32, false, (size_t)(&((PhysicalMesh_Type*)0)->shortestEdgeLength), NULL, 0 }, // physicalMesh.shortestEdgeLength
+ { TYPE_F32, false, (size_t)(&((PhysicalMesh_Type*)0)->averageEdgeLength), NULL, 0 }, // physicalMesh.averageEdgeLength
+ { TYPE_BOOL, false, (size_t)(&((PhysicalMesh_Type*)0)->isTetrahedralMesh), NULL, 0 }, // physicalMesh.isTetrahedralMesh
+ { TYPE_BOOL, false, (size_t)(&((PhysicalMesh_Type*)0)->flipNormals), NULL, 0 }, // physicalMesh.flipNormals
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->transitionUpB), CHILDREN(43), 1 }, // transitionUpB
+ { TYPE_STRUCT, false, 1 * sizeof(SkinClothMapB_Type), CHILDREN(44), 6 }, // transitionUpB[]
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapB_Type*)0)->vtxTetraBary), NULL, 0 }, // transitionUpB[].vtxTetraBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapB_Type*)0)->vertexIndexPlusOffset), NULL, 0 }, // transitionUpB[].vertexIndexPlusOffset
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapB_Type*)0)->nrmTetraBary), NULL, 0 }, // transitionUpB[].nrmTetraBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapB_Type*)0)->faceIndex0), NULL, 0 }, // transitionUpB[].faceIndex0
+ { TYPE_U32, false, (size_t)(&((SkinClothMapB_Type*)0)->tetraIndex), NULL, 0 }, // transitionUpB[].tetraIndex
+ { TYPE_U32, false, (size_t)(&((SkinClothMapB_Type*)0)->submeshIndex), NULL, 0 }, // transitionUpB[].submeshIndex
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->transitionUp), CHILDREN(50), 1 }, // transitionUp
+ { TYPE_STRUCT, false, 1 * sizeof(SkinClothMapD_Type), CHILDREN(51), 7 }, // transitionUp[]
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexBary), NULL, 0 }, // transitionUp[].vertexBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexIndex0), NULL, 0 }, // transitionUp[].vertexIndex0
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapD_Type*)0)->normalBary), NULL, 0 }, // transitionUp[].normalBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexIndex1), NULL, 0 }, // transitionUp[].vertexIndex1
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapD_Type*)0)->tangentBary), NULL, 0 }, // transitionUp[].tangentBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexIndex2), NULL, 0 }, // transitionUp[].vertexIndex2
+ { TYPE_U32, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexIndexPlusOffset), NULL, 0 }, // transitionUp[].vertexIndexPlusOffset
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->transitionUpThickness), NULL, 0 }, // transitionUpThickness
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->transitionUpOffset), NULL, 0 }, // transitionUpOffset
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->transitionDownB), CHILDREN(58), 1 }, // transitionDownB
+ { TYPE_STRUCT, false, 1 * sizeof(SkinClothMapB_Type), CHILDREN(59), 6 }, // transitionDownB[]
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapB_Type*)0)->vtxTetraBary), NULL, 0 }, // transitionDownB[].vtxTetraBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapB_Type*)0)->vertexIndexPlusOffset), NULL, 0 }, // transitionDownB[].vertexIndexPlusOffset
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapB_Type*)0)->nrmTetraBary), NULL, 0 }, // transitionDownB[].nrmTetraBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapB_Type*)0)->faceIndex0), NULL, 0 }, // transitionDownB[].faceIndex0
+ { TYPE_U32, false, (size_t)(&((SkinClothMapB_Type*)0)->tetraIndex), NULL, 0 }, // transitionDownB[].tetraIndex
+ { TYPE_U32, false, (size_t)(&((SkinClothMapB_Type*)0)->submeshIndex), NULL, 0 }, // transitionDownB[].submeshIndex
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->transitionDown), CHILDREN(65), 1 }, // transitionDown
+ { TYPE_STRUCT, false, 1 * sizeof(SkinClothMapD_Type), CHILDREN(66), 7 }, // transitionDown[]
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexBary), NULL, 0 }, // transitionDown[].vertexBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexIndex0), NULL, 0 }, // transitionDown[].vertexIndex0
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapD_Type*)0)->normalBary), NULL, 0 }, // transitionDown[].normalBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexIndex1), NULL, 0 }, // transitionDown[].vertexIndex1
+ { TYPE_VEC3, false, (size_t)(&((SkinClothMapD_Type*)0)->tangentBary), NULL, 0 }, // transitionDown[].tangentBary
+ { TYPE_U32, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexIndex2), NULL, 0 }, // transitionDown[].vertexIndex2
+ { TYPE_U32, false, (size_t)(&((SkinClothMapD_Type*)0)->vertexIndexPlusOffset), NULL, 0 }, // transitionDown[].vertexIndexPlusOffset
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->transitionDownThickness), NULL, 0 }, // transitionDownThickness
+ { TYPE_F32, false, (size_t)(&((ParametersStruct*)0)->transitionDownOffset), NULL, 0 }, // transitionDownOffset
+ { TYPE_U32, false, (size_t)(&((ParametersStruct*)0)->referenceCount), NULL, 0 }, // referenceCount
+};
+
+
+bool ClothingPhysicalMeshParameters::mBuiltFlag = false;
+NvParameterized::MutexType ClothingPhysicalMeshParameters::mBuiltFlagMutex;
+
+ClothingPhysicalMeshParameters::ClothingPhysicalMeshParameters(NvParameterized::Traits* traits, void* buf, int32_t* refCount) :
+ NvParameters(traits, buf, refCount)
+{
+ //mParameterizedTraits->registerFactory(className(), &ClothingPhysicalMeshParametersFactoryInst);
+
+ if (!buf) //Do not init data if it is inplace-deserialized
+ {
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+ initDefaults();
+ }
+}
+
+ClothingPhysicalMeshParameters::~ClothingPhysicalMeshParameters()
+{
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+}
+
+void ClothingPhysicalMeshParameters::destroy()
+{
+ // We cache these fields here to avoid overwrite in destructor
+ bool doDeallocateSelf = mDoDeallocateSelf;
+ NvParameterized::Traits* traits = mParameterizedTraits;
+ int32_t* refCount = mRefCount;
+ void* buf = mBuffer;
+
+ this->~ClothingPhysicalMeshParameters();
+
+ NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf);
+}
+
+const NvParameterized::DefinitionImpl* ClothingPhysicalMeshParameters::getParameterDefinitionTree(void)
+{
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+const NvParameterized::DefinitionImpl* ClothingPhysicalMeshParameters::getParameterDefinitionTree(void) const
+{
+ ClothingPhysicalMeshParameters* tmpParam = const_cast<ClothingPhysicalMeshParameters*>(this);
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ tmpParam->buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+NvParameterized::ErrorType ClothingPhysicalMeshParameters::getParameterHandle(const char* long_name, Handle& handle) const
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+NvParameterized::ErrorType ClothingPhysicalMeshParameters::getParameterHandle(const char* long_name, Handle& handle)
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+void ClothingPhysicalMeshParameters::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const
+{
+ ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<ClothingPhysicalMeshParameters::ParametersStruct*>(&parameters()), handle, offset);
+}
+
+
+/* Dynamic Handle Indices */
+
+void ClothingPhysicalMeshParameters::freeParameterDefinitionTable(NvParameterized::Traits* traits)
+{
+ if (!traits)
+ {
+ return;
+ }
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ return;
+ }
+
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+
+ if (!mBuiltFlag)
+ {
+ return;
+ }
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ ParamDefTable[i].~DefinitionImpl();
+ }
+
+ traits->free(ParamDefTable);
+
+ mBuiltFlag = false;
+}
+
+#define PDEF_PTR(index) (&ParamDefTable[index])
+
+void ClothingPhysicalMeshParameters::buildTree(void)
+{
+
+ uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs;
+ ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize));
+ memset(ParamDefTable, 0, allocSize);
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=0, longName=""
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0];
+ ParamDef->init("", TYPE_STRUCT, "STRUCT", true);
+
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=1, longName="physicalMesh"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1];
+ ParamDef->init("physicalMesh", TYPE_STRUCT, "PhysicalMesh", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The physical mesh data.", true);
+ ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=2, longName="physicalMesh.numVertices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2];
+ ParamDef->init("numVertices", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Number of vertices of this mesh", true);
+ ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=3, longName="physicalMesh.numSimulatedVertices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3];
+ ParamDef->init("numSimulatedVertices", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Number of simulated vertices of this mesh", true);
+ ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=4, longName="physicalMesh.numMaxDistance0Vertices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4];
+ ParamDef->init("numMaxDistance0Vertices", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Number of vertices that have max distance set to 0", true);
+ ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=5, longName="physicalMesh.numIndices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5];
+ ParamDef->init("numIndices", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Number of indices of this mesh", true);
+ ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=6, longName="physicalMesh.numSimulatedIndices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6];
+ ParamDef->init("numSimulatedIndices", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Number of simulated indices of this mesh", true);
+ ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=7, longName="physicalMesh.numBonesPerVertex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7];
+ ParamDef->init("numBonesPerVertex", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Number of bone weights/indices per vertex", true);
+ ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=8, longName="physicalMesh.vertices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[8];
+ ParamDef->init("vertices", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Array of vertices", true);
+ ParamDefTable[8].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+ ParamDefTable[8].setAlignment(16);
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=9, longName="physicalMesh.vertices[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[9];
+ ParamDef->init("vertices", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Array of vertices", true);
+ ParamDefTable[9].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=10, longName="physicalMesh.normals"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[10];
+ ParamDef->init("normals", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "These are the normals provided by the user. The mesh-mesh skinning will try to restore them as good\nas possible throughout simulation. Note, they can differ from the skinningNormals quite drastically.\n", true);
+ HintTable[2].init("shortDescription", "Array of normals", true);
+ ParamDefTable[10].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+ ParamDefTable[10].setAlignment(16);
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=11, longName="physicalMesh.normals[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[11];
+ ParamDef->init("normals", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "These are the normals provided by the user. The mesh-mesh skinning will try to restore them as good\nas possible throughout simulation. Note, they can differ from the skinningNormals quite drastically.\n", true);
+ HintTable[2].init("shortDescription", "Array of normals", true);
+ ParamDefTable[11].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=12, longName="physicalMesh.skinningNormals"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[12];
+ ParamDef->init("skinningNormals", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "These are the normals of the original mesh. They reflect what should come out of physics but the output\ncan be distorted because parts of the simulation mesh are turned off, resulting in wrong normal computation.\nThey are needed for the flags.CorrectSimulationNormals actorflag.\n", true);
+ HintTable[2].init("shortDescription", "Array of skinning normals", true);
+ ParamDefTable[12].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+ ParamDefTable[12].setAlignment(16);
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=13, longName="physicalMesh.skinningNormals[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[13];
+ ParamDef->init("skinningNormals", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "These are the normals of the original mesh. They reflect what should come out of physics but the output\ncan be distorted because parts of the simulation mesh are turned off, resulting in wrong normal computation.\nThey are needed for the flags.CorrectSimulationNormals actorflag.\n", true);
+ HintTable[2].init("shortDescription", "Array of skinning normals", true);
+ ParamDefTable[13].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=14, longName="physicalMesh.constrainCoefficients"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[14];
+ ParamDef->init("constrainCoefficients", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[14].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "These are not provided but computed by copying values from the graphical mesh to the physical mesh.\n", true);
+ HintTable[2].init("shortDescription", "The clothing constrain coefficients for this mesh.", true);
+ ParamDefTable[14].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+ ParamDefTable[14].setAlignment(16);
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=15, longName="physicalMesh.constrainCoefficients[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[15];
+ ParamDef->init("constrainCoefficients", TYPE_STRUCT, "ConstrainCoefficient", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[15].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "These are not provided but computed by copying values from the graphical mesh to the physical mesh.\n", true);
+ HintTable[2].init("shortDescription", "The clothing constrain coefficients for this mesh.", true);
+ ParamDefTable[15].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=16, longName="physicalMesh.constrainCoefficients[].maxDistance"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[16];
+ ParamDef->init("maxDistance", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Maximum distance this vertex is allowed to travel from its skinned position.", true);
+ ParamDefTable[16].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=17, longName="physicalMesh.constrainCoefficients[].collisionSphereRadius"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[17];
+ ParamDef->init("collisionSphereRadius", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Size of the Backstop collision sphere.", true);
+ ParamDefTable[17].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=18, longName="physicalMesh.constrainCoefficients[].collisionSphereDistance"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[18];
+ ParamDef->init("collisionSphereDistance", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Distance of the Backstop collision sphere.", true);
+ ParamDefTable[18].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=19, longName="physicalMesh.boneIndices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[19];
+ ParamDef->init("boneIndices", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[19].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "Note: contains numVertices * numBonesPerVertex elements.\n", true);
+ HintTable[2].init("shortDescription", "The bone indices per vertex", true);
+ ParamDefTable[19].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+ ParamDefTable[19].setAlignment(16);
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=20, longName="physicalMesh.boneIndices[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[20];
+ ParamDef->init("boneIndices", TYPE_U16, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[20].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "Note: contains numVertices * numBonesPerVertex elements.\n", true);
+ HintTable[2].init("shortDescription", "The bone indices per vertex", true);
+ ParamDefTable[20].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=21, longName="physicalMesh.boneWeights"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[21];
+ ParamDef->init("boneWeights", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[21].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "Note: contains numVertices * numBonesPerVertex elements.\n", true);
+ HintTable[2].init("shortDescription", "The bone weights per vertex", true);
+ ParamDefTable[21].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+ ParamDefTable[21].setAlignment(16);
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=22, longName="physicalMesh.boneWeights[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[22];
+ ParamDef->init("boneWeights", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[22].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "Note: contains numVertices * numBonesPerVertex elements.\n", true);
+ HintTable[2].init("shortDescription", "The bone weights per vertex", true);
+ ParamDefTable[22].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=23, longName="physicalMesh.optimizationData"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[23];
+ ParamDef->init("optimizationData", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[23].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "Each byte contains info for 2 vertices.\nbits 0-3: number of actual bones for that vertex (with boneWeight > 0)\nbit 4: set if that vertex has a negative backstop\nbits 5-7: same data for next vertex\n", true);
+ HintTable[2].init("shortDescription", "Per Vertex Number of boneweights > 0, bool if it has negative collision distance", true);
+ ParamDefTable[23].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+ ParamDefTable[23].setAlignment(16);
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=24, longName="physicalMesh.optimizationData[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[24];
+ ParamDef->init("optimizationData", TYPE_U8, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[24].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("longDescription", "Each byte contains info for 2 vertices.\nbits 0-3: number of actual bones for that vertex (with boneWeight > 0)\nbit 4: set if that vertex has a negative backstop\nbits 5-7: same data for next vertex\n", true);
+ HintTable[2].init("shortDescription", "Per Vertex Number of boneweights > 0, bool if it has negative collision distance", true);
+ ParamDefTable[24].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=25, longName="physicalMesh.hasNegativeBackstop"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[25];
+ ParamDef->init("hasNegativeBackstop", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "True if at least 1 has negative collision distance", true);
+ ParamDefTable[25].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=26, longName="physicalMesh.isClosed"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[26];
+ ParamDef->init("isClosed", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "True if all edges have two adjacent triangles", true);
+ ParamDefTable[26].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=27, longName="physicalMesh.indices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[27];
+ ParamDef->init("indices", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[27].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "The index buffer", true);
+ ParamDefTable[27].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+ ParamDefTable[27].setAlignment(16);
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=28, longName="physicalMesh.indices[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[28];
+ ParamDef->init("indices", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ ParamDefTable[28].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("NOPVD", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "The index buffer", true);
+ ParamDefTable[28].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=29, longName="physicalMesh.maximumMaxDistance"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[29];
+ ParamDef->init("maximumMaxDistance", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The maximum max-distance value for all the vertices.", true);
+ ParamDefTable[29].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=30, longName="physicalMesh.physicalMeshSorting"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[30];
+ ParamDef->init("physicalMeshSorting", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Physical mesh sorting", true);
+ ParamDefTable[30].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=31, longName="physicalMesh.shortestEdgeLength"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[31];
+ ParamDef->init("shortestEdgeLength", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Mesh statistic, only needed for debug rendering.", true);
+ ParamDefTable[31].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=32, longName="physicalMesh.averageEdgeLength"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[32];
+ ParamDef->init("averageEdgeLength", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Mesh statistic, useful for selecting the thickness of the mesh-mesh skinning.", true);
+ ParamDefTable[32].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=33, longName="physicalMesh.isTetrahedralMesh"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[33];
+ ParamDef->init("isTetrahedralMesh", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Are we storing triangles or tetrahedrons in this mesh.", true);
+ ParamDefTable[33].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=34, longName="physicalMesh.flipNormals"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[34];
+ ParamDef->init("flipNormals", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "True when the model has been transformed to left-handed space.", true);
+ ParamDefTable[34].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=35, longName="transitionUpB"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[35];
+ ParamDef->init("transitionUpB", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Transition between this and the next graphical LoD.", true);
+ ParamDefTable[35].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+ ParamDefTable[35].setAlignment(16);
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=36, longName="transitionUpB[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[36];
+ ParamDef->init("transitionUpB", TYPE_STRUCT, "SkinClothMapB", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Transition between this and the next graphical LoD.", true);
+ ParamDefTable[36].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=37, longName="transitionUpB[].vtxTetraBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[37];
+ ParamDef->init("vtxTetraBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate into the implicit tetrahedron.", true);
+ ParamDefTable[37].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=38, longName="transitionUpB[].vertexIndexPlusOffset"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[38];
+ ParamDef->init("vertexIndexPlusOffset", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The vertex index in the graphical mesh (the target index).", true);
+ ParamDefTable[38].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=39, longName="transitionUpB[].nrmTetraBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[39];
+ ParamDef->init("nrmTetraBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate of (vertex+normal). When vertex is subtracted this will result in the normal again.", true);
+ ParamDefTable[39].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=40, longName="transitionUpB[].faceIndex0"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[40];
+ ParamDef->init("faceIndex0", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "First index of the 3 consecutive indices making the physical triangle.", true);
+ ParamDefTable[40].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=41, longName="transitionUpB[].tetraIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[41];
+ ParamDef->init("tetraIndex", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Selects which of the 6 implicit tetrahedrons is used for the mapping.", true);
+ ParamDefTable[41].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=42, longName="transitionUpB[].submeshIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[42];
+ ParamDef->init("submeshIndex", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ ParamDefTable[42].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ HintTable[1].init("longDescription", "This is only needed during the authoring stage and thus does not need to be serialized.", true);
+ HintTable[2].init("shortDescription", "Index into which Physical Submesh/LoD this element of the mapping belongs to.", true);
+ ParamDefTable[42].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=43, longName="transitionUp"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[43];
+ ParamDef->init("transitionUp", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Transition between this and the next graphical LoD.", true);
+ ParamDefTable[43].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+ ParamDefTable[43].setAlignment(16);
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=44, longName="transitionUp[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[44];
+ ParamDef->init("transitionUp", TYPE_STRUCT, "SkinClothMapD", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Transition between this and the next graphical LoD.", true);
+ ParamDefTable[44].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=45, longName="transitionUp[].vertexBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[45];
+ ParamDef->init("vertexBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate into the triangle.", true);
+ ParamDefTable[45].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=46, longName="transitionUp[].vertexIndex0"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[46];
+ ParamDef->init("vertexIndex0", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Vertex index of the physics triangle.", true);
+ ParamDefTable[46].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=47, longName="transitionUp[].normalBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[47];
+ ParamDef->init("normalBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate of (vertex+normal). When vertex is subtracted this will result in the normal again.", true);
+ ParamDefTable[47].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=48, longName="transitionUp[].vertexIndex1"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[48];
+ ParamDef->init("vertexIndex1", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Vertex index of the physics triangle.", true);
+ ParamDefTable[48].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=49, longName="transitionUp[].tangentBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[49];
+ ParamDef->init("tangentBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate of (position+tangent). When position is subtracted this will result in the tangent again.", true);
+ ParamDefTable[49].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=50, longName="transitionUp[].vertexIndex2"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[50];
+ ParamDef->init("vertexIndex2", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Vertex index of the physics triangle.", true);
+ ParamDefTable[50].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=51, longName="transitionUp[].vertexIndexPlusOffset"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[51];
+ ParamDef->init("vertexIndexPlusOffset", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The vertex index in the graphical mesh (the target index).", true);
+ ParamDefTable[51].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=52, longName="transitionUpThickness"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[52];
+ ParamDef->init("transitionUpThickness", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The thickness of the transition map", true);
+ ParamDefTable[52].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=53, longName="transitionUpOffset"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[53];
+ ParamDef->init("transitionUpOffset", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The normal offset of the transition map", true);
+ ParamDefTable[53].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=54, longName="transitionDownB"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[54];
+ ParamDef->init("transitionDownB", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Transition between this and the previous graphical LoD.", true);
+ ParamDefTable[54].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+ ParamDefTable[54].setAlignment(16);
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=55, longName="transitionDownB[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[55];
+ ParamDef->init("transitionDownB", TYPE_STRUCT, "SkinClothMapB", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Transition between this and the previous graphical LoD.", true);
+ ParamDefTable[55].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=56, longName="transitionDownB[].vtxTetraBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[56];
+ ParamDef->init("vtxTetraBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate into the implicit tetrahedron.", true);
+ ParamDefTable[56].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=57, longName="transitionDownB[].vertexIndexPlusOffset"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[57];
+ ParamDef->init("vertexIndexPlusOffset", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The vertex index in the graphical mesh (the target index).", true);
+ ParamDefTable[57].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=58, longName="transitionDownB[].nrmTetraBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[58];
+ ParamDef->init("nrmTetraBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate of (vertex+normal). When vertex is subtracted this will result in the normal again.", true);
+ ParamDefTable[58].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=59, longName="transitionDownB[].faceIndex0"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[59];
+ ParamDef->init("faceIndex0", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "First index of the 3 consecutive indices making the physical triangle.", true);
+ ParamDefTable[59].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=60, longName="transitionDownB[].tetraIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[60];
+ ParamDef->init("tetraIndex", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Selects which of the 6 implicit tetrahedrons is used for the mapping.", true);
+ ParamDefTable[60].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=61, longName="transitionDownB[].submeshIndex"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[61];
+ ParamDef->init("submeshIndex", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ ParamDefTable[61].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("DONOTSERIALIZE", uint64_t(1), true);
+ HintTable[1].init("longDescription", "This is only needed during the authoring stage and thus does not need to be serialized.", true);
+ HintTable[2].init("shortDescription", "Index into which Physical Submesh/LoD this element of the mapping belongs to.", true);
+ ParamDefTable[61].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=62, longName="transitionDown"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[62];
+ ParamDef->init("transitionDown", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Transition between this and the previous graphical LoD.", true);
+ ParamDefTable[62].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+ ParamDefTable[62].setAlignment(16);
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=63, longName="transitionDown[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[63];
+ ParamDef->init("transitionDown", TYPE_STRUCT, "SkinClothMapD", true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Transition between this and the previous graphical LoD.", true);
+ ParamDefTable[63].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=64, longName="transitionDown[].vertexBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[64];
+ ParamDef->init("vertexBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate into the triangle.", true);
+ ParamDefTable[64].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=65, longName="transitionDown[].vertexIndex0"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[65];
+ ParamDef->init("vertexIndex0", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Vertex index of the physics triangle.", true);
+ ParamDefTable[65].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=66, longName="transitionDown[].normalBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[66];
+ ParamDef->init("normalBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate of (vertex+normal). When vertex is subtracted this will result in the normal again.", true);
+ ParamDefTable[66].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=67, longName="transitionDown[].vertexIndex1"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[67];
+ ParamDef->init("vertexIndex1", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Vertex index of the physics triangle.", true);
+ ParamDefTable[67].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=68, longName="transitionDown[].tangentBary"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[68];
+ ParamDef->init("tangentBary", TYPE_VEC3, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The barycentric coordinate of (position+tangent). When position is subtracted this will result in the tangent again.", true);
+ ParamDefTable[68].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=69, longName="transitionDown[].vertexIndex2"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[69];
+ ParamDef->init("vertexIndex2", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "Vertex index of the physics triangle.", true);
+ ParamDefTable[69].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=70, longName="transitionDown[].vertexIndexPlusOffset"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[70];
+ ParamDef->init("vertexIndexPlusOffset", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The vertex index in the graphical mesh (the target index).", true);
+ ParamDefTable[70].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=71, longName="transitionDownThickness"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[71];
+ ParamDef->init("transitionDownThickness", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The thickness of the transition map", true);
+ ParamDefTable[71].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=72, longName="transitionDownOffset"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[72];
+ ParamDef->init("transitionDownOffset", TYPE_F32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("shortDescription", "The normal offset of the transition map", true);
+ ParamDefTable[72].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=73, longName="referenceCount"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[73];
+ ParamDef->init("referenceCount", TYPE_U32, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("READONLY", uint64_t(1), true);
+ ParamDefTable[73].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("READONLY", uint64_t(1), true);
+ HintTable[1].init("shortDescription", "Only used internally, do not modify", true);
+ ParamDefTable[73].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // SetChildren for: nodeIndex=0, longName=""
+ {
+ static Definition* Children[10];
+ Children[0] = PDEF_PTR(1);
+ Children[1] = PDEF_PTR(35);
+ Children[2] = PDEF_PTR(43);
+ Children[3] = PDEF_PTR(52);
+ Children[4] = PDEF_PTR(53);
+ Children[5] = PDEF_PTR(54);
+ Children[6] = PDEF_PTR(62);
+ Children[7] = PDEF_PTR(71);
+ Children[8] = PDEF_PTR(72);
+ Children[9] = PDEF_PTR(73);
+
+ ParamDefTable[0].setChildren(Children, 10);
+ }
+
+ // SetChildren for: nodeIndex=1, longName="physicalMesh"
+ {
+ static Definition* Children[22];
+ Children[0] = PDEF_PTR(2);
+ Children[1] = PDEF_PTR(3);
+ Children[2] = PDEF_PTR(4);
+ Children[3] = PDEF_PTR(5);
+ Children[4] = PDEF_PTR(6);
+ Children[5] = PDEF_PTR(7);
+ Children[6] = PDEF_PTR(8);
+ Children[7] = PDEF_PTR(10);
+ Children[8] = PDEF_PTR(12);
+ Children[9] = PDEF_PTR(14);
+ Children[10] = PDEF_PTR(19);
+ Children[11] = PDEF_PTR(21);
+ Children[12] = PDEF_PTR(23);
+ Children[13] = PDEF_PTR(25);
+ Children[14] = PDEF_PTR(26);
+ Children[15] = PDEF_PTR(27);
+ Children[16] = PDEF_PTR(29);
+ Children[17] = PDEF_PTR(30);
+ Children[18] = PDEF_PTR(31);
+ Children[19] = PDEF_PTR(32);
+ Children[20] = PDEF_PTR(33);
+ Children[21] = PDEF_PTR(34);
+
+ ParamDefTable[1].setChildren(Children, 22);
+ }
+
+ // SetChildren for: nodeIndex=8, longName="physicalMesh.vertices"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(9);
+
+ ParamDefTable[8].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=10, longName="physicalMesh.normals"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(11);
+
+ ParamDefTable[10].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=12, longName="physicalMesh.skinningNormals"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(13);
+
+ ParamDefTable[12].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=14, longName="physicalMesh.constrainCoefficients"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(15);
+
+ ParamDefTable[14].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=15, longName="physicalMesh.constrainCoefficients[]"
+ {
+ static Definition* Children[3];
+ Children[0] = PDEF_PTR(16);
+ Children[1] = PDEF_PTR(17);
+ Children[2] = PDEF_PTR(18);
+
+ ParamDefTable[15].setChildren(Children, 3);
+ }
+
+ // SetChildren for: nodeIndex=19, longName="physicalMesh.boneIndices"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(20);
+
+ ParamDefTable[19].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=21, longName="physicalMesh.boneWeights"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(22);
+
+ ParamDefTable[21].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=23, longName="physicalMesh.optimizationData"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(24);
+
+ ParamDefTable[23].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=27, longName="physicalMesh.indices"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(28);
+
+ ParamDefTable[27].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=35, longName="transitionUpB"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(36);
+
+ ParamDefTable[35].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=36, longName="transitionUpB[]"
+ {
+ static Definition* Children[6];
+ Children[0] = PDEF_PTR(37);
+ Children[1] = PDEF_PTR(38);
+ Children[2] = PDEF_PTR(39);
+ Children[3] = PDEF_PTR(40);
+ Children[4] = PDEF_PTR(41);
+ Children[5] = PDEF_PTR(42);
+
+ ParamDefTable[36].setChildren(Children, 6);
+ }
+
+ // SetChildren for: nodeIndex=43, longName="transitionUp"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(44);
+
+ ParamDefTable[43].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=44, longName="transitionUp[]"
+ {
+ static Definition* Children[7];
+ Children[0] = PDEF_PTR(45);
+ Children[1] = PDEF_PTR(46);
+ Children[2] = PDEF_PTR(47);
+ Children[3] = PDEF_PTR(48);
+ Children[4] = PDEF_PTR(49);
+ Children[5] = PDEF_PTR(50);
+ Children[6] = PDEF_PTR(51);
+
+ ParamDefTable[44].setChildren(Children, 7);
+ }
+
+ // SetChildren for: nodeIndex=54, longName="transitionDownB"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(55);
+
+ ParamDefTable[54].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=55, longName="transitionDownB[]"
+ {
+ static Definition* Children[6];
+ Children[0] = PDEF_PTR(56);
+ Children[1] = PDEF_PTR(57);
+ Children[2] = PDEF_PTR(58);
+ Children[3] = PDEF_PTR(59);
+ Children[4] = PDEF_PTR(60);
+ Children[5] = PDEF_PTR(61);
+
+ ParamDefTable[55].setChildren(Children, 6);
+ }
+
+ // SetChildren for: nodeIndex=62, longName="transitionDown"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(63);
+
+ ParamDefTable[62].setChildren(Children, 1);
+ }
+
+ // SetChildren for: nodeIndex=63, longName="transitionDown[]"
+ {
+ static Definition* Children[7];
+ Children[0] = PDEF_PTR(64);
+ Children[1] = PDEF_PTR(65);
+ Children[2] = PDEF_PTR(66);
+ Children[3] = PDEF_PTR(67);
+ Children[4] = PDEF_PTR(68);
+ Children[5] = PDEF_PTR(69);
+ Children[6] = PDEF_PTR(70);
+
+ ParamDefTable[63].setChildren(Children, 7);
+ }
+
+ mBuiltFlag = true;
+
+}
+void ClothingPhysicalMeshParameters::initStrings(void)
+{
+}
+
+void ClothingPhysicalMeshParameters::initDynamicArrays(void)
+{
+ physicalMesh.vertices.buf = NULL;
+ physicalMesh.vertices.isAllocated = true;
+ physicalMesh.vertices.elementSize = sizeof(physx::PxVec3);
+ physicalMesh.vertices.arraySizes[0] = 0;
+ physicalMesh.normals.buf = NULL;
+ physicalMesh.normals.isAllocated = true;
+ physicalMesh.normals.elementSize = sizeof(physx::PxVec3);
+ physicalMesh.normals.arraySizes[0] = 0;
+ physicalMesh.skinningNormals.buf = NULL;
+ physicalMesh.skinningNormals.isAllocated = true;
+ physicalMesh.skinningNormals.elementSize = sizeof(physx::PxVec3);
+ physicalMesh.skinningNormals.arraySizes[0] = 0;
+ physicalMesh.constrainCoefficients.buf = NULL;
+ physicalMesh.constrainCoefficients.isAllocated = true;
+ physicalMesh.constrainCoefficients.elementSize = sizeof(ConstrainCoefficient_Type);
+ physicalMesh.constrainCoefficients.arraySizes[0] = 0;
+ physicalMesh.boneIndices.buf = NULL;
+ physicalMesh.boneIndices.isAllocated = true;
+ physicalMesh.boneIndices.elementSize = sizeof(uint16_t);
+ physicalMesh.boneIndices.arraySizes[0] = 0;
+ physicalMesh.boneWeights.buf = NULL;
+ physicalMesh.boneWeights.isAllocated = true;
+ physicalMesh.boneWeights.elementSize = sizeof(float);
+ physicalMesh.boneWeights.arraySizes[0] = 0;
+ physicalMesh.optimizationData.buf = NULL;
+ physicalMesh.optimizationData.isAllocated = true;
+ physicalMesh.optimizationData.elementSize = sizeof(uint8_t);
+ physicalMesh.optimizationData.arraySizes[0] = 0;
+ physicalMesh.indices.buf = NULL;
+ physicalMesh.indices.isAllocated = true;
+ physicalMesh.indices.elementSize = sizeof(uint32_t);
+ physicalMesh.indices.arraySizes[0] = 0;
+ transitionUpB.buf = NULL;
+ transitionUpB.isAllocated = true;
+ transitionUpB.elementSize = sizeof(SkinClothMapB_Type);
+ transitionUpB.arraySizes[0] = 0;
+ transitionUp.buf = NULL;
+ transitionUp.isAllocated = true;
+ transitionUp.elementSize = sizeof(SkinClothMapD_Type);
+ transitionUp.arraySizes[0] = 0;
+ transitionDownB.buf = NULL;
+ transitionDownB.isAllocated = true;
+ transitionDownB.elementSize = sizeof(SkinClothMapB_Type);
+ transitionDownB.arraySizes[0] = 0;
+ transitionDown.buf = NULL;
+ transitionDown.isAllocated = true;
+ transitionDown.elementSize = sizeof(SkinClothMapD_Type);
+ transitionDown.arraySizes[0] = 0;
+}
+
+void ClothingPhysicalMeshParameters::initDefaults(void)
+{
+
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+ physicalMesh.numVertices = uint32_t(0);
+ physicalMesh.numSimulatedVertices = uint32_t(0);
+ physicalMesh.numIndices = uint32_t(0);
+ physicalMesh.numSimulatedIndices = uint32_t(0);
+ physicalMesh.numBonesPerVertex = uint32_t(0);
+ physicalMesh.hasNegativeBackstop = bool(false);
+ physicalMesh.isClosed = bool(false);
+ physicalMesh.maximumMaxDistance = float(0);
+ physicalMesh.physicalMeshSorting = uint32_t(0);
+ physicalMesh.shortestEdgeLength = float(0);
+ physicalMesh.averageEdgeLength = float(0);
+ physicalMesh.isTetrahedralMesh = bool(false);
+ physicalMesh.flipNormals = bool(false);
+ transitionUpThickness = float(0);
+ transitionUpOffset = float(0);
+ transitionDownThickness = float(0);
+ transitionDownOffset = float(0);
+ referenceCount = uint32_t(0);
+
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+}
+
+void ClothingPhysicalMeshParameters::initReferences(void)
+{
+}
+
+void ClothingPhysicalMeshParameters::freeDynamicArrays(void)
+{
+ if (physicalMesh.vertices.isAllocated && physicalMesh.vertices.buf)
+ {
+ mParameterizedTraits->free(physicalMesh.vertices.buf);
+ }
+ if (physicalMesh.normals.isAllocated && physicalMesh.normals.buf)
+ {
+ mParameterizedTraits->free(physicalMesh.normals.buf);
+ }
+ if (physicalMesh.skinningNormals.isAllocated && physicalMesh.skinningNormals.buf)
+ {
+ mParameterizedTraits->free(physicalMesh.skinningNormals.buf);
+ }
+ if (physicalMesh.constrainCoefficients.isAllocated && physicalMesh.constrainCoefficients.buf)
+ {
+ mParameterizedTraits->free(physicalMesh.constrainCoefficients.buf);
+ }
+ if (physicalMesh.boneIndices.isAllocated && physicalMesh.boneIndices.buf)
+ {
+ mParameterizedTraits->free(physicalMesh.boneIndices.buf);
+ }
+ if (physicalMesh.boneWeights.isAllocated && physicalMesh.boneWeights.buf)
+ {
+ mParameterizedTraits->free(physicalMesh.boneWeights.buf);
+ }
+ if (physicalMesh.optimizationData.isAllocated && physicalMesh.optimizationData.buf)
+ {
+ mParameterizedTraits->free(physicalMesh.optimizationData.buf);
+ }
+ if (physicalMesh.indices.isAllocated && physicalMesh.indices.buf)
+ {
+ mParameterizedTraits->free(physicalMesh.indices.buf);
+ }
+ if (transitionUpB.isAllocated && transitionUpB.buf)
+ {
+ mParameterizedTraits->free(transitionUpB.buf);
+ }
+ if (transitionUp.isAllocated && transitionUp.buf)
+ {
+ mParameterizedTraits->free(transitionUp.buf);
+ }
+ if (transitionDownB.isAllocated && transitionDownB.buf)
+ {
+ mParameterizedTraits->free(transitionDownB.buf);
+ }
+ if (transitionDown.isAllocated && transitionDown.buf)
+ {
+ mParameterizedTraits->free(transitionDown.buf);
+ }
+}
+
+void ClothingPhysicalMeshParameters::freeStrings(void)
+{
+}
+
+void ClothingPhysicalMeshParameters::freeReferences(void)
+{
+}
+
+} // namespace clothing
+} // namespace nvidia
diff --git a/APEX_1.4/module/clothing/src/autogen/ClothingPreviewParam.cpp b/APEX_1.4/module/clothing/src/autogen/ClothingPreviewParam.cpp
new file mode 100644
index 00000000..c1996251
--- /dev/null
+++ b/APEX_1.4/module/clothing/src/autogen/ClothingPreviewParam.cpp
@@ -0,0 +1,506 @@
+// 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-2015 NVIDIA Corporation. All rights reserved.
+
+// This file was generated by NvParameterized/scripts/GenParameterized.pl
+
+
+#include "ClothingPreviewParam.h"
+#include <string.h>
+#include <stdlib.h>
+
+using namespace NvParameterized;
+
+namespace nvidia
+{
+namespace clothing
+{
+
+using namespace ClothingPreviewParamNS;
+
+const char* const ClothingPreviewParamFactory::vptr =
+ NvParameterized::getVptr<ClothingPreviewParam, ClothingPreviewParam::ClassAlignment>();
+
+const uint32_t NumParamDefs = 8;
+static NvParameterized::DefinitionImpl* ParamDefTable; // now allocated in buildTree [NumParamDefs];
+
+
+static const size_t ParamLookupChildrenTable[] =
+{
+ 1, 2, 3, 4, 5, 6, 7,
+};
+
+#define TENUM(type) nvidia::##type
+#define CHILDREN(index) &ParamLookupChildrenTable[index]
+static const NvParameterized::ParamLookupNode ParamLookupTable[NumParamDefs] =
+{
+ { TYPE_STRUCT, false, 0, CHILDREN(0), 6 },
+ { TYPE_MAT44, false, (size_t)(&((ParametersStruct*)0)->globalPose), NULL, 0 }, // globalPose
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->fallbackSkinning), NULL, 0 }, // fallbackSkinning
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->useInternalBoneOrder), NULL, 0 }, // useInternalBoneOrder
+ { TYPE_BOOL, false, (size_t)(&((ParametersStruct*)0)->updateStateWithGlobalMatrices), NULL, 0 }, // updateStateWithGlobalMatrices
+ { TYPE_U64, false, (size_t)(&((ParametersStruct*)0)->userData), NULL, 0 }, // userData
+ { TYPE_ARRAY, true, (size_t)(&((ParametersStruct*)0)->boneMatrices), CHILDREN(6), 1 }, // boneMatrices
+ { TYPE_MAT44, false, 1 * sizeof(physx::PxMat44), NULL, 0 }, // boneMatrices[]
+};
+
+
+bool ClothingPreviewParam::mBuiltFlag = false;
+NvParameterized::MutexType ClothingPreviewParam::mBuiltFlagMutex;
+
+ClothingPreviewParam::ClothingPreviewParam(NvParameterized::Traits* traits, void* buf, int32_t* refCount) :
+ NvParameters(traits, buf, refCount)
+{
+ //mParameterizedTraits->registerFactory(className(), &ClothingPreviewParamFactoryInst);
+
+ if (!buf) //Do not init data if it is inplace-deserialized
+ {
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+ initDefaults();
+ }
+}
+
+ClothingPreviewParam::~ClothingPreviewParam()
+{
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+}
+
+void ClothingPreviewParam::destroy()
+{
+ // We cache these fields here to avoid overwrite in destructor
+ bool doDeallocateSelf = mDoDeallocateSelf;
+ NvParameterized::Traits* traits = mParameterizedTraits;
+ int32_t* refCount = mRefCount;
+ void* buf = mBuffer;
+
+ this->~ClothingPreviewParam();
+
+ NvParameters::destroy(this, traits, doDeallocateSelf, refCount, buf);
+}
+
+const NvParameterized::DefinitionImpl* ClothingPreviewParam::getParameterDefinitionTree(void)
+{
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+const NvParameterized::DefinitionImpl* ClothingPreviewParam::getParameterDefinitionTree(void) const
+{
+ ClothingPreviewParam* tmpParam = const_cast<ClothingPreviewParam*>(this);
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+ if (!mBuiltFlag)
+ {
+ tmpParam->buildTree();
+ }
+ }
+
+ return(&ParamDefTable[0]);
+}
+
+NvParameterized::ErrorType ClothingPreviewParam::getParameterHandle(const char* long_name, Handle& handle) const
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+NvParameterized::ErrorType ClothingPreviewParam::getParameterHandle(const char* long_name, Handle& handle)
+{
+ ErrorType Ret = NvParameters::getParameterHandle(long_name, handle);
+ if (Ret != ERROR_NONE)
+ {
+ return(Ret);
+ }
+
+ size_t offset;
+ void* ptr;
+
+ getVarPtr(handle, ptr, offset);
+
+ if (ptr == NULL)
+ {
+ return(ERROR_INDEX_OUT_OF_RANGE);
+ }
+
+ return(ERROR_NONE);
+}
+
+void ClothingPreviewParam::getVarPtr(const Handle& handle, void*& ptr, size_t& offset) const
+{
+ ptr = getVarPtrHelper(&ParamLookupTable[0], const_cast<ClothingPreviewParam::ParametersStruct*>(&parameters()), handle, offset);
+}
+
+
+/* Dynamic Handle Indices */
+
+void ClothingPreviewParam::freeParameterDefinitionTable(NvParameterized::Traits* traits)
+{
+ if (!traits)
+ {
+ return;
+ }
+
+ if (!mBuiltFlag) // Double-checked lock
+ {
+ return;
+ }
+
+ NvParameterized::MutexType::ScopedLock lock(mBuiltFlagMutex);
+
+ if (!mBuiltFlag)
+ {
+ return;
+ }
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ ParamDefTable[i].~DefinitionImpl();
+ }
+
+ traits->free(ParamDefTable);
+
+ mBuiltFlag = false;
+}
+
+#define PDEF_PTR(index) (&ParamDefTable[index])
+
+void ClothingPreviewParam::buildTree(void)
+{
+
+ uint32_t allocSize = sizeof(NvParameterized::DefinitionImpl) * NumParamDefs;
+ ParamDefTable = (NvParameterized::DefinitionImpl*)(mParameterizedTraits->alloc(allocSize));
+ memset(ParamDefTable, 0, allocSize);
+
+ for (uint32_t i = 0; i < NumParamDefs; ++i)
+ {
+ NV_PARAM_PLACEMENT_NEW(ParamDefTable + i, NvParameterized::DefinitionImpl)(*mParameterizedTraits);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=0, longName=""
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[0];
+ ParamDef->init("", TYPE_STRUCT, "STRUCT", true);
+
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=1, longName="globalPose"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[1];
+ ParamDef->init("globalPose", TYPE_MAT44, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("shortDescription", "The pose where the clothing asset will be put into the scene", true);
+ ParamDefTable[1].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=2, longName="fallbackSkinning"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[2];
+ ParamDef->init("fallbackSkinning", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Performs the regular boneweighted skinning on the CPU before giving the\ndata out through the rendering API.\n", true);
+ HintTable[1].init("shortDescription", "Performs skinning in software", true);
+ ParamDefTable[2].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=3, longName="useInternalBoneOrder"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[3];
+ ParamDef->init("useInternalBoneOrder", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("longDescription", "If this is set to true the bone buffers in updateState and the actor\ndescriptor have to be given in the same order as the bones are stored\ninternally in the asset. This can be queried using\nNxClothingAsset::getNumUsedBones and NxClothingAsset::getBoneName or\nNxClothingAsset::getBoneMapping.\n\nIf this is set to false, the bone buffers can be provided in the order as\nthey are stored in the application. This is either the bone order at\nauthoring time, or NxClothingAsset::remapBoneIndex can be called for each\nbone to let APEX know about the current ordering in the game. Note that\nthis is only recommended if the application already uses physx::PxMat44\n(or something binary equivalent) and does not have to convert the matrices.\n", true);
+ HintTable[2].init("shortDescription", "Expect internally ordered bone arrays in updateState call.", true);
+ ParamDefTable[3].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=4, longName="updateStateWithGlobalMatrices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[4];
+ ParamDef->init("updateStateWithGlobalMatrices", TYPE_BOOL, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("longDescription", "Depending on what matrices are present, the state can be updated using\nglobal world or object space bone matrices or composite matrices. The\ncomposite matrix can be generated by multiplying the world or object space\nmatrix by the inverse bone bine pose.\n\nNote: If there are problems which might be caused by bind poses being\ndifferent in the ClothingAsset and in the game's animation system, changing\nthis to true (and thus providing global pose matrices) might fix the problem.\n", true);
+ HintTable[1].init("shortDescription", "Use world space matrices instead of composite (relative to bind pose) in NxClothingActor::updateState().", true);
+ ParamDefTable[4].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=5, longName="userData"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[5];
+ ParamDef->init("userData", TYPE_U64, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[2];
+ static Hint* HintPtrTable[2] = { &HintTable[0], &HintTable[1], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("shortDescription", "Optional user data pointer associated with the clothing actor", true);
+ ParamDefTable[5].setHints((const NvParameterized::Hint**)HintPtrTable, 2);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=6, longName="boneMatrices"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[6];
+ ParamDef->init("boneMatrices", TYPE_ARRAY, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("longDescription", "These matrices are sometimes referred to as composite matrices. They are the\nmultiplication of the current world space bone pose with the inverse bind\npose in world space.\nNote: If \'updateStateWithGlobalMatrices\' is set to true, these must be\nglobal poses instead.\n", true);
+ HintTable[2].init("shortDescription", "An Array of matrices with the full transform for each bone", true);
+ ParamDefTable[6].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+ ParamDef->setArraySize(-1);
+ }
+
+ // Initialize DefinitionImpl node: nodeIndex=7, longName="boneMatrices[]"
+ {
+ NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[7];
+ ParamDef->init("boneMatrices", TYPE_MAT44, NULL, true);
+
+#ifdef NV_PARAMETERIZED_HIDE_DESCRIPTIONS
+
+ static HintImpl HintTable[1];
+ static Hint* HintPtrTable[1] = { &HintTable[0], };
+ HintTable[0].init("editorDisplay", "false", true);
+ ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 1);
+
+#else
+
+ static HintImpl HintTable[3];
+ static Hint* HintPtrTable[3] = { &HintTable[0], &HintTable[1], &HintTable[2], };
+ HintTable[0].init("editorDisplay", "false", true);
+ HintTable[1].init("longDescription", "These matrices are sometimes referred to as composite matrices. They are the\nmultiplication of the current world space bone pose with the inverse bind\npose in world space.\nNote: If \'updateStateWithGlobalMatrices\' is set to true, these must be\nglobal poses instead.\n", true);
+ HintTable[2].init("shortDescription", "An Array of matrices with the full transform for each bone", true);
+ ParamDefTable[7].setHints((const NvParameterized::Hint**)HintPtrTable, 3);
+
+#endif /* NV_PARAMETERIZED_HIDE_DESCRIPTIONS */
+
+
+
+
+
+ }
+
+ // SetChildren for: nodeIndex=0, longName=""
+ {
+ static Definition* Children[6];
+ Children[0] = PDEF_PTR(1);
+ Children[1] = PDEF_PTR(2);
+ Children[2] = PDEF_PTR(3);
+ Children[3] = PDEF_PTR(4);
+ Children[4] = PDEF_PTR(5);
+ Children[5] = PDEF_PTR(6);
+
+ ParamDefTable[0].setChildren(Children, 6);
+ }
+
+ // SetChildren for: nodeIndex=6, longName="boneMatrices"
+ {
+ static Definition* Children[1];
+ Children[0] = PDEF_PTR(7);
+
+ ParamDefTable[6].setChildren(Children, 1);
+ }
+
+ mBuiltFlag = true;
+
+}
+void ClothingPreviewParam::initStrings(void)
+{
+}
+
+void ClothingPreviewParam::initDynamicArrays(void)
+{
+ boneMatrices.buf = NULL;
+ boneMatrices.isAllocated = true;
+ boneMatrices.elementSize = sizeof(physx::PxMat44);
+ boneMatrices.arraySizes[0] = 0;
+}
+
+void ClothingPreviewParam::initDefaults(void)
+{
+
+ freeStrings();
+ freeReferences();
+ freeDynamicArrays();
+ globalPose = physx::PxMat44(physx::PxVec4(1.0f));
+ fallbackSkinning = bool(false);
+ useInternalBoneOrder = bool(false);
+ updateStateWithGlobalMatrices = bool(false);
+ userData = uint64_t(0);
+
+ initDynamicArrays();
+ initStrings();
+ initReferences();
+}
+
+void ClothingPreviewParam::initReferences(void)
+{
+}
+
+void ClothingPreviewParam::freeDynamicArrays(void)
+{
+ if (boneMatrices.isAllocated && boneMatrices.buf)
+ {
+ mParameterizedTraits->free(boneMatrices.buf);
+ }
+}
+
+void ClothingPreviewParam::freeStrings(void)
+{
+}
+
+void ClothingPreviewParam::freeReferences(void)
+{
+}
+
+} // namespace clothing
+} // namespace nvidia