SetBlendShapeTargetDeltasCommand.cpp dnacalib/commands/SetBlendShapeTargetDeltasCommand.h dnacalib/TypeDefs.h dnacalib/CommandImplBase.h dnacalib/commands/SupportFactories.h dnacalib/dna/DNA.h dnacalib/dna/DNACalibDNAReaderImpl.h dnacalib/types/Aliases.h dnacalib/utils/FormatString.h cstdint numeric dnac::SetBlendShapeTargetDeltasCommand::Impl dnac //CopyrightEpicGames,Inc.AllRightsReserved. #include"dnacalib/commands/SetBlendShapeTargetDeltasCommand.h" #include"dnacalib/TypeDefs.h" #include"dnacalib/CommandImplBase.h" #include"dnacalib/commands/SupportFactories.h" #include"dnacalib/dna/DNA.h" #include"dnacalib/dna/DNACalibDNAReaderImpl.h" #include"dnacalib/types/Aliases.h" #include"dnacalib/utils/FormatString.h" #include<cstdint> #include<numeric> namespacednac{ classSetBlendShapeTargetDeltasCommand::Impl:publicCommandImplBase<Impl>{ private: usingSuper=CommandImplBase<Impl>; public: explicitImpl(MemoryResource*memRes_): Super{memRes_}, deltas{memRes_}, vertexIndices{memRes_}, masks{memRes_}, operation{VectorOperation::Interpolate}, meshIndex{}, blendShapeTargetIndex{}{ } voidsetMeshIndex(std::uint16_tmeshIndex_){ meshIndex=meshIndex_; } voidsetBlendShapeTargetIndex(std::uint16_tblendShapeTargetIndex_){ blendShapeTargetIndex=blendShapeTargetIndex_; } voidsetDeltas(ConstArrayView<Vector3>deltas_){ deltas.assign(deltas_.begin(),deltas_.end()); } voidsetDeltas(ConstArrayView<float>xs,ConstArrayView<float>ys,ConstArrayView<float>zs){ deltas.xs.assign(xs.begin(),xs.end()); deltas.ys.assign(ys.begin(),ys.end()); deltas.zs.assign(zs.begin(),zs.end()); } voidsetVertexIndices(ConstArrayView<std::uint32_t>vertexIndices_){ vertexIndices.assign(vertexIndices_.begin(),vertexIndices_.end()); } voidsetMasks(ConstArrayView<float>masks_){ masks.assign(masks_.begin(),masks_.end()); } voidsetOperation(VectorOperationoperation_){ operation=operation_; } voidrun(DNACalibDNAReaderImpl*output){ status.reset(); autogetWeight=WeightGetterFactory::create(masks); autoop=OperationFactory::create(operation); computeBlendShapeTargetDeltas(op,getWeight,output); } private: staticvoiddensify(RawVector3Vector&bsDeltas,Vector<std::uint32_t>&bsVertexIndices,std::uint32_tvertexCount){ constautodeltaCount=static_cast<std::uint32_t>(bsDeltas.size()); bsDeltas.resize(vertexCount); bsVertexIndices.resize(vertexCount); for(std::uint32_tj=deltaCount;j>0;--j){ constautoi=j-1; constautosrcDelta=Vector3{bsDeltas.xs[i],bsDeltas.ys[i],bsDeltas.zs[i]}; bsDeltas.xs[i]={}; bsDeltas.ys[i]={}; bsDeltas.zs[i]={}; bsDeltas.xs[bsVertexIndices[i]]=srcDelta.x; bsDeltas.ys[bsVertexIndices[i]]=srcDelta.y; bsDeltas.zs[bsVertexIndices[i]]=srcDelta.z; } std::iota(bsVertexIndices.begin(),bsVertexIndices.end(),0u); } staticvoidsparsify(RawVector3Vector&bsDeltas,Vector<std::uint32_t>&bsVertexIndices,floatthreshold){ constfloatthreshold2=threshold*threshold; std::uint32_tdi=0u; for(std::uint32_tsi=0u;si<bsVertexIndices.size();si++){ constautosourceDelta=tdm::fvec3{bsDeltas.xs[si],bsDeltas.ys[si],bsDeltas.zs[si]}; constfloatmagnitude2=tdm::dot(sourceDelta,sourceDelta); if(magnitude2>threshold2){ bsVertexIndices[di]=bsVertexIndices[si]; bsDeltas.xs[di]=sourceDelta[0]; bsDeltas.ys[di]=sourceDelta[1]; bsDeltas.zs[di]=sourceDelta[2]; ++di; } } bsDeltas.resize(di); bsVertexIndices.resize(di); } template<typenameFOperation,typenameFWeightGetter> voidcomputeBlendShapeTargetDeltas(FOperationop,FWeightGettergetWeight,DNACalibDNAReaderImpl*output){ constautoxs=output->getBlendShapeTargetDeltaXs(meshIndex,blendShapeTargetIndex); constautoys=output->getBlendShapeTargetDeltaYs(meshIndex,blendShapeTargetIndex); constautozs=output->getBlendShapeTargetDeltaZs(meshIndex,blendShapeTargetIndex); constautovtxIndices=output->getBlendShapeTargetVertexIndices(meshIndex,blendShapeTargetIndex); assert((xs.size()==ys.size())&&(ys.size()==zs.size())&&(xs.size()==vtxIndices.size())); RawVector3VectorbsDeltas{xs,ys,zs,output->getMemoryResource()}; Vector<std::uint32_t>bsVertexIndices{output->getMemoryResource()}; bsVertexIndices.assign(vtxIndices.begin(),vtxIndices.end()); //Ifnovertexindiceswereset,tryusingexistingones.Theconditionthatmustbemetinthatcaseisthatnumber //ofsetdeltasequalsthenumberofexistingvertexindices. if(vertexIndices.empty()){ if(deltas.size()!=bsVertexIndices.size()){ constautomessage=formatString( output->getMemoryResource(), "Novertexindicesset.CurrentvertexindicesinDNAwillnotbeused,astheirnumber(%hu)differsfromthenumberofsetdeltas(%hu).", bsVertexIndices.size(), deltas.size()); status.set(NoVertexIndicesSetError,message.c_str()); return; } vertexIndices.assign(bsVertexIndices.begin(),bsVertexIndices.end()); } constautovertexCount=output->getVertexPositionCount(meshIndex); for(constautovi:vertexIndices){ if(vi>=vertexCount){ constautomessage=formatString(output->getMemoryResource(), "Vertexindex(%hu)isoutofbounds.Vertexcountis(%hu).", vi, vertexCount); status.set(VertexIndicesOutOfBoundsError,message.c_str()); return; } } //DensifycurrentblendshapesfromDNA densify(bsDeltas,bsVertexIndices,vertexCount); if(deltas.size()!=vertexIndices.size()){ constautomessage=formatString(output->getMemoryResource(), "Numberofsetdeltas(%hu)differsfromnumberofsetvertexindices(%hu).", deltas.size(), vertexIndices.size()); status.set(DeltasVertexIndicesCountMismatch,message.c_str()); return; } if(!masks.empty()&&(deltas.size()!=masks.size())){ constautomessage=formatString(output->getMemoryResource(), "Numberofsetdeltas(%hu)differsfromnumberofsetmasks(%hu).", deltas.size(), masks.size()); status.set(DeltasMasksCountMismatch,message.c_str()); return; } //Computeoperation assert(bsDeltas.size()==vertexCount); for(std::uint32_ti=0u;i<vertexIndices.size();++i){ constautoindex=vertexIndices[i]; constfloatweight=getWeight(masks.data(),i); bsDeltas.xs[index]=op(bsDeltas.xs[index],deltas.xs[i],weight); bsDeltas.ys[index]=op(bsDeltas.ys[index],deltas.ys[i],weight); bsDeltas.zs[index]=op(bsDeltas.zs[index],deltas.zs[i],weight); } //Sparsifyresult sparsify(bsDeltas,bsVertexIndices,0.0f); //SetnewdeltasandvertexindicestooutputDNA output->setBlendShapeTargetDeltas(meshIndex,blendShapeTargetIndex,std::move(bsDeltas)); output->setBlendShapeTargetVertexIndices(meshIndex,blendShapeTargetIndex, ConstArrayView<std::uint32_t>{bsVertexIndices}); } private: staticsc::StatusProviderstatus; RawVector3Vectordeltas; Vector<std::uint32_t>vertexIndices; Vector<float>masks; VectorOperationoperation; std::uint16_tmeshIndex; std::uint16_tblendShapeTargetIndex; }; constsc::StatusCodeSetBlendShapeTargetDeltasCommand::VertexIndicesOutOfBoundsError{3101,"%s"}; constsc::StatusCodeSetBlendShapeTargetDeltasCommand::NoVertexIndicesSetError{3102,"%s"}; constsc::StatusCodeSetBlendShapeTargetDeltasCommand::DeltasVertexIndicesCountMismatch{3103,"%s"}; constsc::StatusCodeSetBlendShapeTargetDeltasCommand::DeltasMasksCountMismatch{3104,"%s"}; #ifdef__clang__ #pragmaclangdiagnosticpush #pragmaclangdiagnosticignored"-Wglobal-constructors" #endif sc::StatusProviderSetBlendShapeTargetDeltasCommand::Impl::status{VertexIndicesOutOfBoundsError,NoVertexIndicesSetError, DeltasVertexIndicesCountMismatch,DeltasMasksCountMismatch}; #ifdef__clang__ #pragmaclangdiagnosticpop #endif SetBlendShapeTargetDeltasCommand::SetBlendShapeTargetDeltasCommand(MemoryResource*memRes):pImpl{makeScoped<Impl>(memRes)}{ } SetBlendShapeTargetDeltasCommand::SetBlendShapeTargetDeltasCommand(std::uint16_tmeshIndex, std::uint16_tblendShapeTargetIndex, ConstArrayView<Vector3>deltas, ConstArrayView<std::uint32_t>vertexIndices, VectorOperationoperation, MemoryResource*memRes): pImpl{makeScoped<Impl>(memRes)}{ pImpl->setMeshIndex(meshIndex); pImpl->setBlendShapeTargetIndex(blendShapeTargetIndex); pImpl->setDeltas(deltas); pImpl->setVertexIndices(vertexIndices); pImpl->setOperation(operation); } SetBlendShapeTargetDeltasCommand::SetBlendShapeTargetDeltasCommand(std::uint16_tmeshIndex, std::uint16_tblendShapeTargetIndex, ConstArrayView<float>xs, ConstArrayView<float>ys, ConstArrayView<float>zs, ConstArrayView<std::uint32_t>vertexIndices, VectorOperationoperation, MemoryResource*memRes): pImpl{makeScoped<Impl>(memRes)}{ pImpl->setMeshIndex(meshIndex); pImpl->setBlendShapeTargetIndex(blendShapeTargetIndex); pImpl->setDeltas(xs,ys,zs); pImpl->setVertexIndices(vertexIndices); pImpl->setOperation(operation); } SetBlendShapeTargetDeltasCommand::SetBlendShapeTargetDeltasCommand(std::uint16_tmeshIndex, std::uint16_tblendShapeTargetIndex, ConstArrayView<Vector3>deltas, ConstArrayView<std::uint32_t>vertexIndices, ConstArrayView<float>masks, VectorOperationoperation, MemoryResource*memRes): pImpl{makeScoped<Impl>(memRes)}{ pImpl->setMeshIndex(meshIndex); pImpl->setBlendShapeTargetIndex(blendShapeTargetIndex); pImpl->setDeltas(deltas); pImpl->setVertexIndices(vertexIndices); pImpl->setMasks(masks); pImpl->setOperation(operation); } SetBlendShapeTargetDeltasCommand::SetBlendShapeTargetDeltasCommand(std::uint16_tmeshIndex, std::uint16_tblendShapeTargetIndex, ConstArrayView<float>xs, ConstArrayView<float>ys, ConstArrayView<float>zs, ConstArrayView<std::uint32_t>vertexIndices, ConstArrayView<float>masks, VectorOperationoperation, MemoryResource*memRes): pImpl{makeScoped<Impl>(memRes)}{ pImpl->setMeshIndex(meshIndex); pImpl->setBlendShapeTargetIndex(blendShapeTargetIndex); pImpl->setDeltas(xs,ys,zs); pImpl->setVertexIndices(vertexIndices); pImpl->setMasks(masks); pImpl->setOperation(operation); } SetBlendShapeTargetDeltasCommand::~SetBlendShapeTargetDeltasCommand()=default; SetBlendShapeTargetDeltasCommand::SetBlendShapeTargetDeltasCommand(SetBlendShapeTargetDeltasCommand&&)=default; SetBlendShapeTargetDeltasCommand&SetBlendShapeTargetDeltasCommand::operator=(SetBlendShapeTargetDeltasCommand&&)=default; voidSetBlendShapeTargetDeltasCommand::setMeshIndex(std::uint16_tmeshIndex){ pImpl->setMeshIndex(meshIndex); } voidSetBlendShapeTargetDeltasCommand::setBlendShapeTargetIndex(std::uint16_tblendShapeTargetIndex){ pImpl->setBlendShapeTargetIndex(blendShapeTargetIndex); } voidSetBlendShapeTargetDeltasCommand::setDeltas(ConstArrayView<Vector3>deltas){ pImpl->setDeltas(deltas); } voidSetBlendShapeTargetDeltasCommand::setDeltas(ConstArrayView<float>xs,ConstArrayView<float>ys,ConstArrayView<float>zs){ pImpl->setDeltas(xs,ys,zs); } voidSetBlendShapeTargetDeltasCommand::setVertexIndices(ConstArrayView<std::uint32_t>vertexIndices){ pImpl->setVertexIndices(vertexIndices); } voidSetBlendShapeTargetDeltasCommand::setMasks(ConstArrayView<float>masks){ pImpl->setMasks(masks); } voidSetBlendShapeTargetDeltasCommand::setOperation(VectorOperationoperation){ pImpl->setOperation(operation); } voidSetBlendShapeTargetDeltasCommand::run(DNACalibDNAReader*output){ pImpl->run(static_cast<DNACalibDNAReaderImpl*>(output)); } }//namespacednac