CalculateMeshLowerLODsCommand.cpp dnacalib/commands/CalculateMeshLowerLODsCommand.h dnacalib/CommandImplBase.h dnacalib/dna/DNA.h dnacalib/dna/DNACalibDNAReaderImpl.h dnacalib/types/Aliases.h dnacalib/types/UVBarycentricMapping.h dnac::CalculateMeshLowerLODsCommand::Impl dnac //CopyrightEpicGames,Inc.AllRightsReserved. #include"dnacalib/commands/CalculateMeshLowerLODsCommand.h" #include"dnacalib/CommandImplBase.h" #include"dnacalib/dna/DNA.h" #include"dnacalib/dna/DNACalibDNAReaderImpl.h" #include"dnacalib/types/Aliases.h" #include"dnacalib/types/UVBarycentricMapping.h" namespacednac{ classCalculateMeshLowerLODsCommand::Impl:publicCommandImplBase<Impl>{ private: usingSuper=CommandImplBase<Impl>; public: explicitImpl(MemoryResource*memRes_): Super{memRes_}, meshIndex{}{ } voidsetMeshIndex(std::uint16_tmeshIndex_){ meshIndex=meshIndex_; } voidrun(DNACalibDNAReaderImpl*output){ UVBarycentricMappingmapping{output,meshIndex,getMemoryResource()}; autosrcMeshXs=output->getVertexPositionXs(meshIndex); autosrcMeshYs=output->getVertexPositionYs(meshIndex); autosrcMeshZs=output->getVertexPositionZs(meshIndex); constautogetSrcVertex=[srcMeshXs,srcMeshYs,srcMeshZs](std::uint32_tpositionIndex){ returnfvec3{srcMeshXs[positionIndex],srcMeshYs[positionIndex],srcMeshZs[positionIndex]}; }; for(std::uint16_tmi:findIndicesOfMeshLowerLODs(output)){ autovertexLayoutPositionIndices=output->getVertexLayoutPositionIndices(mi); autovertexLayoutTextureCoordinateIndices=output->getVertexLayoutTextureCoordinateIndices(mi); autous=output->getVertexTextureCoordinateUs(mi); autovs=output->getVertexTextureCoordinateVs(mi); conststd::uint32_tpositionCount=output->getVertexPositionCount(mi); RawVector3VectordestVertexPositions{positionCount,{},getMemoryResource()}; //AstherecanbemultipleVertexLayoutpereachVertexPositionwewillusearithmeticmeanvalue. Vector<uint8_t>vertexLayoutsPerPosition{positionCount,{},getMemoryResource()}; for(std::size_ti=0u;i<vertexLayoutPositionIndices.size();++i){ conststd::uint32_tuvIndex=vertexLayoutTextureCoordinateIndices[i]; constfvec2uvs={us[uvIndex],vs[uvIndex]}; constautoweightsIndicesPair=mapping.getBarycentric(uvs); constfvec3&barycentric=weightsIndicesPair.first; autosrcVtxIndices=weightsIndicesPair.second; if(srcVtxIndices.size()==0){ //We'llneedtohandlethiscaseinthefuture? assert(false&&"Couldnotmapavertex,didnothitanytriangle'sboundingbox."); continue; } constfvec3src= getSrcVertex(srcVtxIndices[0])*barycentric[0]+ getSrcVertex(srcVtxIndices[1])*barycentric[1]+ getSrcVertex(srcVtxIndices[2])*barycentric[2]; constuint32_tpositionIndex=vertexLayoutPositionIndices[i]; float&destX=destVertexPositions.xs[positionIndex]; float&destY=destVertexPositions.ys[positionIndex]; float&destZ=destVertexPositions.zs[positionIndex]; constautovtxLayoutCount=++vertexLayoutsPerPosition[positionIndex]; if(vtxLayoutCount==1){ destX=src[0]; destY=src[1]; destZ=src[2]; }else{ //Werequiremeanaverage,morethanonevertexLayoutforthisvertexposition constautolastDenominator=static_cast<float>(vtxLayoutCount-1u); constautonewDenominator=static_cast<float>(vtxLayoutCount); destX=(destX*lastDenominator+src[0])/newDenominator; destY=(destY*lastDenominator+src[1])/newDenominator; destZ=(destZ*lastDenominator+src[2])/newDenominator; } } output->setVertexPositions(mi,std::move(destVertexPositions)); } } private: staticStringViewgetMeshName(DNACalibDNAReaderImpl*output,std::uint16_tmi){ constautomeshName=output->getMeshName(mi); constautounderscoreIter=std::find(meshName.begin(),meshName.end(),'_'); assert(underscoreIter!=meshName.end()&&"Meshnamingdoesnotfollowconvention."); autolength=static_cast<size_t>(std::distance(meshName.begin(),underscoreIter)); return{meshName.data(),length}; } Vector<std::uint16_t>findIndicesOfMeshLowerLODs(DNACalibDNAReaderImpl*output){ Vector<std::uint16_t>lowerLODIndices{getMemoryResource()}; boolisLowerLOD=false; automeshName=getMeshName(output,meshIndex); for(std::uint16_tlodIndex=0u;lodIndex<output->getLODCount();++lodIndex){ autolodMeshIndices=output->getMeshIndicesForLOD(lodIndex); if(isLowerLOD){ for(std::uint16_tmi:lodMeshIndices){ if(meshName==getMeshName(output,mi)){ lowerLODIndices.push_back(mi); break; } } }else{ isLowerLOD=std::find(lodMeshIndices.begin(),lodMeshIndices.end(),meshIndex)!=lodMeshIndices.end(); } } returnlowerLODIndices; } private: std::uint16_tmeshIndex; }; CalculateMeshLowerLODsCommand::CalculateMeshLowerLODsCommand(MemoryResource*memRes):pImpl{makeScoped<Impl>(memRes)}{ } CalculateMeshLowerLODsCommand::CalculateMeshLowerLODsCommand(std::uint16_tmeshIndex,MemoryResource*memRes): pImpl{makeScoped<Impl>(memRes)}{ pImpl->setMeshIndex(meshIndex); } CalculateMeshLowerLODsCommand::~CalculateMeshLowerLODsCommand()=default; CalculateMeshLowerLODsCommand::CalculateMeshLowerLODsCommand(CalculateMeshLowerLODsCommand&&)=default; CalculateMeshLowerLODsCommand&CalculateMeshLowerLODsCommand::operator=(CalculateMeshLowerLODsCommand&&)=default; voidCalculateMeshLowerLODsCommand::setMeshIndex(std::uint16_tmeshIndex){ pImpl->setMeshIndex(meshIndex); } voidCalculateMeshLowerLODsCommand::run(DNACalibDNAReader*output){ pImpl->run(static_cast<DNACalibDNAReaderImpl*>(output)); } }//namespacednac