diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/framework/src/ApexRenderMeshAssetAuthoring.cpp | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'APEX_1.4/framework/src/ApexRenderMeshAssetAuthoring.cpp')
| -rw-r--r-- | APEX_1.4/framework/src/ApexRenderMeshAssetAuthoring.cpp | 650 |
1 files changed, 650 insertions, 0 deletions
diff --git a/APEX_1.4/framework/src/ApexRenderMeshAssetAuthoring.cpp b/APEX_1.4/framework/src/ApexRenderMeshAssetAuthoring.cpp new file mode 100644 index 00000000..1ccc32f0 --- /dev/null +++ b/APEX_1.4/framework/src/ApexRenderMeshAssetAuthoring.cpp @@ -0,0 +1,650 @@ +/* + * 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 "PsArray.h" +#include "ApexRenderMeshAssetAuthoring.h" +#include "ApexRenderMeshActor.h" +#include "ApexSharedUtils.h" +#include "ApexCustomBufferIterator.h" +#include "ApexUsingNamespace.h" +#include "ApexSDKIntl.h" +#include "ResourceProviderIntl.h" + +#include "PsSort.h" + +#ifndef WITHOUT_APEX_AUTHORING + +namespace nvidia +{ +namespace apex +{ + + +PX_INLINE bool PxVec3equals(const PxVec3& a, const PxVec3& v, float epsilon) +{ + return + PxEquals(a.x, v.x, epsilon) && + PxEquals(a.y, v.y, epsilon) && + PxEquals(a.z, v.z, epsilon); +} + +ApexRenderMeshAssetAuthoring::ApexRenderMeshAssetAuthoring(ResourceList& list, RenderMeshAssetParameters* params, const char* name) +{ + list.add(*this); + + createFromParameters(params); + + mName = name; +} + +ApexRenderMeshAssetAuthoring::ApexRenderMeshAssetAuthoring(ResourceList& list) +{ + list.add(*this); +} + +ApexRenderMeshAssetAuthoring::~ApexRenderMeshAssetAuthoring() +{ +} + +// We will create our vertex map here. Remapping will be from sorting by part index + + +void ApexRenderMeshAssetAuthoring::createRenderMesh(const MeshDesc& meshDesc, bool createMappingInformation) +{ + if (!meshDesc.isValid()) + { + APEX_INVALID_OPERATION("MeshDesc is not valid!"); + return; + } + + if (mParams != NULL) + { + mParams->destroy(); + } + + NvParameterized::Traits* traits = GetInternalApexSDK()->getParameterizedTraits(); + mParams = (RenderMeshAssetParameters*)traits->createNvParameterized(RenderMeshAssetParameters::staticClassName()); + NvParameterized::Handle rootHandle(*mParams); + + // Submeshes + mParams->getParameterHandle("materialNames", rootHandle); + rootHandle.resizeArray((int32_t)meshDesc.m_numSubmeshes); + mParams->getParameterHandle("submeshes", rootHandle); + rootHandle.resizeArray((int32_t)meshDesc.m_numSubmeshes); + setSubmeshCount(0); + setSubmeshCount(meshDesc.m_numSubmeshes); + for (uint32_t submeshNum = 0; submeshNum < meshDesc.m_numSubmeshes; ++submeshNum) + { + ApexRenderSubmesh& submesh = *mSubmeshes[submeshNum]; + SubmeshParameters* submeshParams = (SubmeshParameters*)traits->createNvParameterized(SubmeshParameters::staticClassName()); + submesh.createFromParameters(submeshParams); + mParams->submeshes.buf[submeshNum] = submeshParams; + //NvParameterized::Handle submeshHandle( submeshParams ); + const SubmeshDesc& submeshDesc = meshDesc.m_submeshes[submeshNum]; + + // Material name + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("materialNames", handle); + NvParameterized::Handle elementHandle(*mParams); + handle.getChildHandle((int32_t)submeshNum, elementHandle); + mParams->setParamString(elementHandle, submeshDesc.m_materialName); + + // Index buffer + + physx::Array<VertexPart> submeshMap; + submeshMap.resize(submeshDesc.m_numVertices); + const uint32_t invalidPart = PxMax(1u, submeshDesc.m_numParts); + for (uint32_t i = 0; i < submeshDesc.m_numVertices; ++i) + { + submeshMap[i].part = invalidPart; + submeshMap[i].vertexIndex = i; + } + bool success = false; + switch (submeshDesc.m_indexType) + { + case IndexType::UINT: + success = fillSubmeshMap<uint32_t>(submeshMap, submeshDesc.m_partIndices, submeshDesc.m_numParts, submeshDesc.m_vertexIndices, submeshDesc.m_numIndices, submeshDesc.m_numVertices); + break; + case IndexType::USHORT: + success = fillSubmeshMap<uint16_t>(submeshMap, submeshDesc.m_partIndices, submeshDesc.m_numParts, submeshDesc.m_vertexIndices, submeshDesc.m_numIndices, submeshDesc.m_numVertices); + break; + default: + PX_ALWAYS_ASSERT(); + } + + // error message? + if (!success) + { + return; + } + + if (submeshMap.size() > 1) + { + shdfnd::sort(submeshMap.begin(), submeshMap.size(), VertexPart()); + } + + uint32_t vertexCount = 0; + for (; vertexCount < submeshDesc.m_numVertices; ++vertexCount) + { + if (submeshMap[vertexCount].part == invalidPart) + { + break; + } + } + + // Create inverse map for our internal remapping + Array<int32_t> invMap; // maps old indices to new indices + invMap.resize(submeshDesc.m_numVertices); + for (uint32_t i = 0; i < submeshDesc.m_numVertices; ++i) + { + const uint32_t vIndex = submeshMap[i].vertexIndex; + if (i >= vertexCount) + { + invMap[vIndex] = -1; + } + else + { + invMap[vIndex] = (int32_t)i; + } + } + + // Copy index buffer (remapping) + NvParameterized::Handle ibHandle(submeshParams); + submeshParams->getParameterHandle("indexBuffer", ibHandle); + ibHandle.resizeArray((int32_t)submeshDesc.m_numIndices); + switch (submeshDesc.m_indexType) + { + case IndexType::UINT: + for (uint32_t i = 0; i < submeshDesc.m_numIndices; ++i) + { + const uint32_t index = submeshDesc.m_vertexIndices != NULL ? ((uint32_t*)submeshDesc.m_vertexIndices)[i] : i; + submeshParams->indexBuffer.buf[i] = (uint32_t)invMap[index]; + PX_ASSERT(submeshParams->indexBuffer.buf[i] != (uint32_t)-1); + } + break; + case IndexType::USHORT: + for (uint32_t i = 0; i < submeshDesc.m_numIndices; ++i) + { + const uint16_t index = submeshDesc.m_vertexIndices != NULL ? ((uint16_t*)submeshDesc.m_vertexIndices)[i] : (uint16_t)i; + submeshParams->indexBuffer.buf[i] = (uint32_t)invMap[index]; + PX_ASSERT(submeshParams->indexBuffer.buf[i] != (uint32_t)-1); + } + break; + default: + PX_ALWAYS_ASSERT(); + } + + // Smoothing groups + int32_t smoothingGroupArraySize = 0; + if (submeshDesc.m_smoothingGroups != NULL) + { + switch (submeshDesc.m_primitive) + { + case Primitive::TRIANGLE_LIST: + smoothingGroupArraySize = (int32_t)submeshDesc.m_numIndices/3; + break; + default: + PX_ALWAYS_ASSERT(); // We only have one kind of primitive + } + } + if (smoothingGroupArraySize != 0) + { + NvParameterized::Handle sgHandle(submeshParams); + submeshParams->getParameterHandle("smoothingGroups", sgHandle); + sgHandle.resizeArray(smoothingGroupArraySize); + sgHandle.setParamU32Array(submeshDesc.m_smoothingGroups, smoothingGroupArraySize, 0); + } + + // Index partition + NvParameterized::Handle ipHandle(submeshParams); + submeshParams->getParameterHandle("indexPartition", ipHandle); + ipHandle.resizeArray(PxMax((int32_t)submeshDesc.m_numParts + 1, 2)); + + if (submeshDesc.m_numParts == 0) + { + submeshParams->indexPartition.buf[0] = 0; + submeshParams->indexPartition.buf[1] = submeshDesc.m_numIndices; + } + else + { + switch (submeshDesc.m_indexType) + { + case IndexType::UINT: + for (uint32_t i = 0; i < submeshDesc.m_numParts; ++i) + { + submeshParams->indexPartition.buf[i] = ((uint32_t*)submeshDesc.m_partIndices)[i]; + } + submeshParams->indexPartition.buf[submeshDesc.m_numParts] = submeshDesc.m_numIndices; + break; + case IndexType::USHORT: + for (uint32_t i = 0; i < submeshDesc.m_numParts; ++i) + { + submeshParams->indexPartition.buf[i] = (uint32_t)((uint16_t*)submeshDesc.m_partIndices)[i]; + } + submeshParams->indexPartition.buf[submeshDesc.m_numParts] = submeshDesc.m_numIndices; + break; + default: + PX_ALWAYS_ASSERT(); + } + } + + // Vertex partition + Array<uint32_t> lookup; + createIndexStartLookup(lookup, 0, submeshDesc.m_numParts, (int32_t*)submeshMap.begin(), vertexCount, sizeof(VertexPart)); + NvParameterized::Handle vpHandle(submeshParams); + submeshParams->getParameterHandle("vertexPartition", vpHandle); + vpHandle.resizeArray((int32_t)lookup.size()); + vpHandle.setParamU32Array(lookup.begin(), (int32_t)lookup.size()); + + // Vertex buffer + + // Create format description + ApexVertexFormat format; + + for (uint32_t i = 0; i < submeshDesc.m_numVertexBuffers; ++i) + { + const VertexBuffer& vb = submeshDesc.m_vertexBuffers[i]; + for (uint32_t semantic = 0; semantic < RenderVertexSemantic::NUM_SEMANTICS; ++semantic) + { + RenderVertexSemantic::Enum vertexSemantic = (RenderVertexSemantic::Enum)semantic; + RenderDataFormat::Enum vertexFormat = vb.getSemanticData(vertexSemantic).format; + + if (vertexSemanticFormatValid(vertexSemantic, vertexFormat)) + { + int32_t bufferIndex = format.addBuffer(format.getSemanticName(vertexSemantic)); + format.setBufferFormat((uint32_t)bufferIndex, vb.getSemanticData(vertexSemantic).format); + } + else if (vertexFormat != RenderDataFormat::UNSPECIFIED) + { + APEX_INVALID_PARAMETER("Format (%d) is not valid for Semantic (%s)", vertexFormat, format.getSemanticName(vertexSemantic)); + } + } + } + + format.setWinding(submeshDesc.m_cullMode); + + // Include custom buffers + for (uint32_t i = 0; i < submeshDesc.m_numVertexBuffers; ++i) + { + const VertexBuffer& vb = submeshDesc.m_vertexBuffers[i]; + for (uint32_t index = 0; index < vb.getNumCustomSemantics(); ++index) + { + const RenderSemanticData& data = vb.getCustomSemanticData(index); + // BRG - reusing data.ident as the custom channel name. What to do with the serialize parameter? + int32_t bufferIndex = format.addBuffer((char*)data.ident); + format.setBufferFormat((uint32_t)bufferIndex, data.format); + + // PH: custom buffers are never serialized this way, we might need to change this! + format.setBufferSerialize((uint32_t)bufferIndex, data.serialize); + } + } + + if (createMappingInformation) + { + int32_t bufferIndex = format.addBuffer("VERTEX_ORIGINAL_INDEX"); + format.setBufferFormat((uint32_t)bufferIndex, RenderDataFormat::UINT1); + } + + // Create apex vertex buffer + submesh.buildVertexBuffer(format, vertexCount); + + // Now fill in... + for (uint32_t i = 0; i < submeshDesc.m_numVertexBuffers; ++i) + { + const VertexBuffer& vb = submeshDesc.m_vertexBuffers[i]; + const VertexFormat& vf = submesh.getVertexBuffer().getFormat(); + + RenderSemanticData boneWeightData; + RenderSemanticData boneIndexData; + RenderDataFormat::Enum checkFormatBoneWeight = RenderDataFormat::UNSPECIFIED; + RenderDataFormat::Enum checkFormatBoneIndex = RenderDataFormat::UNSPECIFIED; + RenderDataFormat::Enum dstFormatBoneWeight = RenderDataFormat::UNSPECIFIED; + RenderDataFormat::Enum dstFormatBoneIndex = RenderDataFormat::UNSPECIFIED; + void* dstDataWeight = NULL; + void* dstDataIndex = NULL; + uint32_t numBoneWeights = 0; + uint32_t numBoneIndices = 0; + + for (uint32_t semantic = 0; semantic < RenderVertexSemantic::NUM_SEMANTICS; ++semantic) + { + if (vertexSemanticFormatValid((RenderVertexSemantic::Enum)semantic, vb.getSemanticData((RenderVertexSemantic::Enum)semantic).format)) + { + RenderDataFormat::Enum dstFormat; + void* dst = submesh.getVertexBufferWritable().getBufferAndFormatWritable(dstFormat, (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID((RenderVertexSemantic::Enum)semantic))); + const RenderSemanticData& data = vb.getSemanticData((RenderVertexSemantic::Enum)semantic); + + copyRenderVertexBuffer(dst, dstFormat, 0, 0, data.data, data.srcFormat, data.stride, 0, submeshDesc.m_numVertices, invMap.begin()); + + if (semantic == RenderVertexSemantic::BONE_WEIGHT) + { + boneWeightData = data; + // Verification code for bone weights. + switch (data.srcFormat) + { + case RenderDataFormat::FLOAT1: + checkFormatBoneWeight = RenderDataFormat::FLOAT1; + numBoneWeights = 1; + break; + case RenderDataFormat::FLOAT2: + checkFormatBoneWeight = RenderDataFormat::FLOAT2; + numBoneWeights = 2; + break; + case RenderDataFormat::FLOAT3: + checkFormatBoneWeight = RenderDataFormat::FLOAT3; + numBoneWeights = 3; + break; + case RenderDataFormat::FLOAT4: + checkFormatBoneWeight = RenderDataFormat::FLOAT4; + numBoneWeights = 4; + break; + default: + break; + } + + dstDataWeight = dst; + dstFormatBoneWeight = dstFormat; + } + else if (semantic == RenderVertexSemantic::BONE_INDEX) + { + boneIndexData = data; + switch (data.srcFormat) + { + case RenderDataFormat::USHORT1: + checkFormatBoneIndex = RenderDataFormat::USHORT1; + numBoneIndices = 1; + break; + case RenderDataFormat::USHORT2: + checkFormatBoneIndex = RenderDataFormat::USHORT2; + numBoneIndices = 2; + break; + case RenderDataFormat::USHORT3: + checkFormatBoneIndex = RenderDataFormat::USHORT3; + numBoneIndices = 3; + break; + case RenderDataFormat::USHORT4: + checkFormatBoneIndex = RenderDataFormat::USHORT4; + numBoneIndices = 4; + break; + default: + break; + } + dstDataIndex = dst; + dstFormatBoneIndex = dstFormat; + } + } + } + + // some verification code + if (numBoneIndices > 1 && numBoneWeights == numBoneIndices) + { + float verifyWeights[4] = { 0.0f }; + uint16_t verifyIndices[4] = { 0 }; + for (uint32_t vi = 0; vi < submeshDesc.m_numVertices; vi++) + { + const int32_t dest = invMap[vi]; + if (dest >= 0) + { + + copyRenderVertexBuffer(verifyWeights, checkFormatBoneWeight, 0, 0, boneWeightData.data, boneWeightData.srcFormat, boneWeightData.stride, vi, 1); + copyRenderVertexBuffer(verifyIndices, checkFormatBoneIndex, 0, 0, boneIndexData.data, boneIndexData.srcFormat, boneIndexData.stride, vi, 1); + + float sum = 0.0f; + for (uint32_t j = 0; j < numBoneWeights; j++) + { + sum += verifyWeights[j]; + } + + if (PxAbs(1 - sum) > 0.001) + { + if (sum > 0.0f) + { + for (uint32_t j = 0; j < numBoneWeights; j++) + { + verifyWeights[j] /= sum; + } + } + + APEX_INVALID_PARAMETER("Submesh %d Vertex %d has been normalized, bone weight was (%f)", i, vi, sum); + } + // PH: bubble sort, don't kill me for this + for (uint32_t j = 1; j < numBoneWeights; j++) + { + for (uint32_t k = 1; k < numBoneWeights; k++) + { + if (verifyWeights[k - 1] < verifyWeights[k]) + { + nvidia::swap(verifyWeights[k - 1], verifyWeights[k]); + nvidia::swap(verifyIndices[k - 1], verifyIndices[k]); + } + } + } + + for (uint32_t j = 0; j < numBoneWeights; j++) + { + if (verifyWeights[j] == 0.0f) + { + verifyIndices[j] = 0; + } + } + + copyRenderVertexBuffer(dstDataWeight, dstFormatBoneWeight, 0, (uint32_t)dest, verifyWeights, checkFormatBoneWeight, 0, 0, 1); + copyRenderVertexBuffer(dstDataIndex, dstFormatBoneIndex, 0, (uint32_t)dest, verifyIndices, checkFormatBoneIndex, 0, 0, 1); + } + } + } + + // Custom buffers + for (uint32_t index = 0; index < vb.getNumCustomSemantics(); ++index) + { + const RenderSemanticData& data = vb.getCustomSemanticData(index); + const int32_t bufferIndex = format.getBufferIndexFromID(format.getID((char*)data.ident)); + PX_ASSERT(bufferIndex >= 0); + void* dst = const_cast<void*>(submesh.getVertexBuffer().getBuffer((uint32_t)bufferIndex)); + RenderDataFormat::Enum srcFormat = data.srcFormat != RenderDataFormat::UNSPECIFIED ? data.srcFormat : data.format; + copyRenderVertexBuffer(dst, data.format, 0, 0, data.data, srcFormat, data.stride, 0, submeshDesc.m_numVertices, invMap.begin()); + } + } + + if (createMappingInformation) + { + const VertexFormat::BufferID bufferID = format.getID("VERTEX_ORIGINAL_INDEX"); + const int32_t bufferIndex = format.getBufferIndexFromID(bufferID); + RenderDataFormat::Enum bufferFormat = format.getBufferFormat((uint32_t)bufferIndex); + PX_ASSERT(bufferIndex >= 0); + const void* dst = submesh.getVertexBuffer().getBuffer((uint32_t)bufferIndex); + copyRenderVertexBuffer(const_cast<void*>(dst), bufferFormat, 0, 0, &submeshMap[0].vertexIndex , RenderDataFormat::UINT1 , sizeof(VertexPart), 0, vertexCount, NULL); + } + } + + // Part bounds + uint32_t partCount = 1; + for (uint32_t submeshNum = 0; submeshNum < meshDesc.m_numSubmeshes; ++submeshNum) + { + partCount = PxMax(partCount, meshDesc.m_submeshes[submeshNum].m_numParts); + } + mParams->getParameterHandle("partBounds", rootHandle); + mParams->resizeArray(rootHandle, (int32_t)partCount); + for (uint32_t partNum = 0; partNum < partCount; ++partNum) + { + mParams->partBounds.buf[partNum].setEmpty(); + // Add part vertices + for (uint32_t submeshNum = 0; submeshNum < meshDesc.m_numSubmeshes; ++submeshNum) + { + SubmeshParameters* submeshParams = DYNAMIC_CAST(SubmeshParameters*)(mParams->submeshes.buf[submeshNum]); + ApexRenderSubmesh& submesh = *mSubmeshes[submeshNum]; + RenderDataFormat::Enum positionFormat; + const VertexFormat& vf = submesh.getVertexBuffer().getFormat(); + const PxVec3* positions = (const PxVec3*)submesh.getVertexBuffer().getBufferAndFormat(positionFormat, + (uint32_t)vf.getBufferIndexFromID(vf.getSemanticID(RenderVertexSemantic::POSITION))); + if (positions && positionFormat == RenderDataFormat::FLOAT3) + { + for (uint32_t vertexIndex = submeshParams->vertexPartition.buf[partNum]; vertexIndex < submeshParams->vertexPartition.buf[partNum + 1]; ++vertexIndex) + { + mParams->partBounds.buf[partNum].include(positions[vertexIndex]); + } + } + } + } + + mParams->textureUVOrigin = meshDesc.m_uvOrigin; + + createLocalData(); +} + +uint32_t ApexRenderMeshAssetAuthoring::createReductionMap(uint32_t* map, const Vertex* vertices, const uint32_t* smoothingGroups, uint32_t vertexCount, + const PxVec3& positionTolerance, float normalTolerance, float UVTolerance) +{ + physx::Array<BoundsRep> vertexNeighborhoods; + vertexNeighborhoods.resize(vertexCount); + const PxVec3 neighborhoodExtent = 0.5f * positionTolerance; + for (uint32_t vertexNum = 0; vertexNum < vertexCount; ++vertexNum) + { + vertexNeighborhoods[vertexNum].aabb = PxBounds3(vertices[vertexNum].position - neighborhoodExtent, vertices[vertexNum].position + neighborhoodExtent); + } + + physx::Array<IntPair> vertexNeighbors; + if (vertexNeighborhoods.size() > 0) + { + boundsCalculateOverlaps(vertexNeighbors, Bounds3XYZ, &vertexNeighborhoods[0], vertexNeighborhoods.size(), sizeof(vertexNeighborhoods[0])); + } + + for (uint32_t i = 0; i < vertexCount; ++i) + { + map[i] = i; + } + + for (uint32_t pairNum = 0; pairNum < vertexNeighbors.size(); ++pairNum) + { + const IntPair& pair = vertexNeighbors[pairNum]; + const uint32_t map0 = map[pair.i0]; + const uint32_t map1 = map[pair.i1]; + if (smoothingGroups != NULL && smoothingGroups[map0] != smoothingGroups[map1]) + { + continue; + } + const Vertex& vertex0 = vertices[map0]; + const Vertex& vertex1 = vertices[map1]; + if (PxAbs(vertex0.position.x - vertex1.position.x) > positionTolerance.x || + PxAbs(vertex0.position.y - vertex1.position.y) > positionTolerance.y || + PxAbs(vertex0.position.z - vertex1.position.z) > positionTolerance.z) + { + continue; + } + if (!PxVec3equals(vertex0.normal, vertex1.normal, normalTolerance) || + !PxVec3equals(vertex0.tangent, vertex1.tangent, normalTolerance) || + !PxVec3equals(vertex0.binormal, vertex1.binormal, normalTolerance)) + { + continue; + } + uint32_t uvNum = 0; + for (; uvNum < VertexFormat::MAX_UV_COUNT; ++uvNum) + { + const VertexUV& uv0 = vertex0.uv[uvNum]; + const VertexUV& uv1 = vertex1.uv[uvNum]; + if (PxAbs(uv0[0] - uv1[0]) > UVTolerance || PxAbs(uv0[1] - uv1[1]) > UVTolerance) + { + break; + } + } + if (uvNum < VertexFormat::MAX_UV_COUNT) + { + continue; + } + map[pair.i1] = map0; + } + + physx::Array<int32_t> offsets(vertexCount, -1); + for (uint32_t i = 0; i < vertexCount; ++i) + { + offsets[map[i]] = 0; + } + int32_t delta = 0; + for (uint32_t i = 0; i < vertexCount; ++i) + { + delta += offsets[i]; + offsets[i] = delta; + } + for (uint32_t i = 0; i < vertexCount; ++i) + { + map[i] += offsets[map[i]]; + } + return vertexCount + delta; +} + + + +void ApexRenderMeshAssetAuthoring::setMaterialName(uint32_t submeshIndex, const char* name) +{ + size_t maxMaterials = (uint32_t)mParams->materialNames.arraySizes[0]; + PX_ASSERT(submeshIndex < maxMaterials); + if (submeshIndex < maxMaterials) + { + NvParameterized::Handle handle(*mParams); + mParams->getParameterHandle("materialNames", handle); + NvParameterized::Handle elementHandle(*mParams); + handle.getChildHandle((int32_t)submeshIndex, elementHandle); + mParams->setParamString(elementHandle, name ? name : ""); + } +} + +void ApexRenderMeshAssetAuthoring::setWindingOrder(uint32_t submeshIndex, RenderCullMode::Enum winding) +{ + ApexRenderSubmesh& subMesh = *ApexRenderMeshAsset::mSubmeshes[submeshIndex]; + VertexBufferIntl& vb = subMesh.getVertexBufferWritable(); + vb.getFormatWritable().setWinding(winding); +} + +RenderCullMode::Enum ApexRenderMeshAssetAuthoring::getWindingOrder(uint32_t submeshIndex) const +{ + const RenderSubmesh& subMesh = getSubmesh(submeshIndex); + const nvidia::apex::VertexBuffer& vb = subMesh.getVertexBuffer(); + const VertexFormat& format = vb.getFormat(); + return format.getWinding(); +} + + + +template <typename PxU> +bool ApexRenderMeshAssetAuthoring::fillSubmeshMap(physx::Array<VertexPart>& submeshMap, const void* const partIndicesVoid, + uint32_t numParts, const void* const vertexIndicesVoid, + uint32_t numSubmeshIndices, uint32_t numSubmeshVertices) +{ + PxU partIndexStart = 0; + if (numParts == 0) + { + numParts = 1; + } + + const PxU* const partIndices = partIndicesVoid != NULL ? reinterpret_cast<const PxU * const>(partIndicesVoid) : &partIndexStart; + const PxU* const vertexIndices = reinterpret_cast<const PxU * const>(vertexIndicesVoid); + + for (uint32_t i = 0; i < numParts; ++i) + { + const uint32_t stop = i + 1 < numParts ? partIndices[i + 1] : numSubmeshIndices; + for (uint32_t j = partIndices[i]; j < stop; ++j) + { + const uint32_t vertexIndex = vertexIndices != NULL ? vertexIndices[j] : j; + if (vertexIndex >= numSubmeshVertices) + { + return false; // to do: issue error - index out of range + } + if (submeshMap[vertexIndex].part != numParts && submeshMap[vertexIndex].part != i) + { + return false; // to do: issue error - vertex in more than one part + } + submeshMap[vertexIndex].part = i; + } + } + return true; +} + +} +} // end namespace nvidia::apex +#endif |