Fixed missing moves in SHBatch move constructor and assignment as well as added isAnimated check with base 0-index identity matrix for bones
This commit is contained in:
parent
af3e4a3cfd
commit
62e0e5e1ad
|
@ -37,40 +37,50 @@ namespace SHADE
|
||||||
/* SHBatch - Constructors/Destructors */
|
/* SHBatch - Constructors/Destructors */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
|
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
|
||||||
: pipeline{ pipeline }
|
: pipeline{ pipeline }
|
||||||
{
|
{
|
||||||
if (!pipeline)
|
if (!pipeline)
|
||||||
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
|
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
|
||||||
|
|
||||||
|
// Check the pipeline and flag it depending on whether or not it is animated
|
||||||
|
isAnimated = checkIfIsAnimatedPipeline(pipeline);
|
||||||
|
|
||||||
// Mark all as dirty
|
// Mark all as dirty
|
||||||
setAllDirtyFlags();
|
setAllDirtyFlags();
|
||||||
}
|
}
|
||||||
|
|
||||||
SHBatch::SHBatch(SHBatch&& rhs)
|
SHBatch::SHBatch(SHBatch&& rhs)
|
||||||
: device { rhs.device }
|
: device { rhs.device }
|
||||||
, pipeline { rhs.pipeline }
|
, isAnimated { rhs.isAnimated }
|
||||||
, referencedMatInstances { std::move(rhs.referencedMatInstances) }
|
, pipeline { rhs.pipeline }
|
||||||
, matBufferDirty { std::move(rhs.matBufferDirty) }
|
, referencedMatInstances { std::move(rhs.referencedMatInstances) }
|
||||||
, subBatches { std::move(rhs.subBatches) }
|
, matBufferDirty { std::move(rhs.matBufferDirty) }
|
||||||
, isDirty { std::move(rhs.isDirty) }
|
, subBatches { std::move(rhs.subBatches) }
|
||||||
, drawData { std::move(rhs.drawData) }
|
, isDirty { std::move(rhs.isDirty) }
|
||||||
, transformData { std::move(rhs.transformData) }
|
, drawData { std::move(rhs.drawData) }
|
||||||
, instancedIntegerData { std::move(rhs.instancedIntegerData) }
|
, transformData { std::move(rhs.transformData) }
|
||||||
, matPropsData { std::move(rhs.matPropsData) }
|
, instancedIntegerData { std::move(rhs.instancedIntegerData) }
|
||||||
, matPropsDataSize { rhs.matPropsDataSize }
|
, matPropsData { std::move(rhs.matPropsData) }
|
||||||
, singleMatPropAlignedSize { rhs.singleMatPropAlignedSize }
|
, matPropsDataSize { rhs.matPropsDataSize }
|
||||||
, singleMatPropSize { rhs.singleMatPropSize }
|
, singleMatPropAlignedSize { rhs.singleMatPropAlignedSize }
|
||||||
, isCPUBuffersDirty { rhs.isCPUBuffersDirty }
|
, singleMatPropSize { rhs.singleMatPropSize }
|
||||||
, drawDataBuffer { rhs.drawDataBuffer }
|
, boneMatrixData { std::move(rhs.boneMatrixData) }
|
||||||
, transformDataBuffer { rhs.transformDataBuffer }
|
, boneMatrixIndices { std::move(rhs.boneMatrixIndices) }
|
||||||
, instancedIntegerBuffer { rhs.instancedIntegerBuffer }
|
, isCPUBuffersDirty { rhs.isCPUBuffersDirty }
|
||||||
, matPropsBuffer { rhs.matPropsBuffer }
|
, drawDataBuffer { rhs.drawDataBuffer }
|
||||||
, instanceDataDescSet { rhs.instanceDataDescSet }
|
, transformDataBuffer { rhs.transformDataBuffer }
|
||||||
|
, instancedIntegerBuffer { rhs.instancedIntegerBuffer }
|
||||||
|
, matPropsBuffer { rhs.matPropsBuffer }
|
||||||
|
, boneMatrixBuffer { rhs.boneMatrixBuffer }
|
||||||
|
, boneMatrixFirstIndexBuffer { rhs.boneMatrixFirstIndexBuffer }
|
||||||
|
, instanceDataDescSet { rhs.instanceDataDescSet }
|
||||||
{
|
{
|
||||||
rhs.drawDataBuffer = {};
|
rhs.drawDataBuffer = {};
|
||||||
rhs.transformDataBuffer = {};
|
rhs.transformDataBuffer = {};
|
||||||
rhs.instancedIntegerBuffer = {};
|
rhs.instancedIntegerBuffer = {};
|
||||||
rhs.matPropsBuffer = {};
|
rhs.matPropsBuffer = {};
|
||||||
|
rhs.boneMatrixBuffer = {};
|
||||||
|
rhs.boneMatrixFirstIndexBuffer = {};
|
||||||
rhs.instanceDataDescSet = {};
|
rhs.instanceDataDescSet = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,31 +89,38 @@ namespace SHADE
|
||||||
if (this == &rhs)
|
if (this == &rhs)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
device = rhs.device ;
|
device = rhs.device ;
|
||||||
pipeline = rhs.pipeline ;
|
isAnimated = rhs.isAnimated ;
|
||||||
referencedMatInstances = std::move(rhs.referencedMatInstances);
|
pipeline = rhs.pipeline ;
|
||||||
matBufferDirty = std::move(rhs.matBufferDirty) ;
|
referencedMatInstances = std::move(rhs.referencedMatInstances);
|
||||||
subBatches = std::move(rhs.subBatches) ;
|
matBufferDirty = std::move(rhs.matBufferDirty) ;
|
||||||
isDirty = std::move(rhs.isDirty) ;
|
subBatches = std::move(rhs.subBatches) ;
|
||||||
drawData = std::move(rhs.drawData) ;
|
isDirty = std::move(rhs.isDirty) ;
|
||||||
transformData = std::move(rhs.transformData) ;
|
drawData = std::move(rhs.drawData) ;
|
||||||
instancedIntegerData = std::move(rhs.instancedIntegerData) ;
|
transformData = std::move(rhs.transformData) ;
|
||||||
matPropsData = std::move(rhs.matPropsData) ;
|
instancedIntegerData = std::move(rhs.instancedIntegerData) ;
|
||||||
matPropsDataSize = rhs.matPropsDataSize ;
|
matPropsData = std::move(rhs.matPropsData) ;
|
||||||
singleMatPropAlignedSize = rhs.singleMatPropAlignedSize ;
|
matPropsDataSize = rhs.matPropsDataSize ;
|
||||||
singleMatPropSize = rhs.singleMatPropSize ;
|
singleMatPropAlignedSize = rhs.singleMatPropAlignedSize ;
|
||||||
isCPUBuffersDirty = rhs.isCPUBuffersDirty ;
|
singleMatPropSize = rhs.singleMatPropSize ;
|
||||||
drawDataBuffer = rhs.drawDataBuffer ;
|
boneMatrixData = std::move(rhs.boneMatrixData) ;
|
||||||
transformDataBuffer = rhs.transformDataBuffer ;
|
boneMatrixIndices = std::move(rhs.boneMatrixIndices) ;
|
||||||
instancedIntegerBuffer = rhs.instancedIntegerBuffer ;
|
isCPUBuffersDirty = rhs.isCPUBuffersDirty ;
|
||||||
matPropsBuffer = rhs.matPropsBuffer ;
|
drawDataBuffer = rhs.drawDataBuffer ;
|
||||||
instanceDataDescSet = rhs.instanceDataDescSet ;
|
transformDataBuffer = rhs.transformDataBuffer ;
|
||||||
|
instancedIntegerBuffer = rhs.instancedIntegerBuffer ;
|
||||||
|
matPropsBuffer = rhs.matPropsBuffer ;
|
||||||
|
boneMatrixBuffer = rhs.boneMatrixBuffer ;
|
||||||
|
boneMatrixFirstIndexBuffer = rhs.boneMatrixFirstIndexBuffer ;
|
||||||
|
instanceDataDescSet = rhs.instanceDataDescSet ;
|
||||||
|
|
||||||
// Unset values
|
// Unset values
|
||||||
rhs.drawDataBuffer = {};
|
rhs.drawDataBuffer = {};
|
||||||
rhs.transformDataBuffer = {};
|
rhs.transformDataBuffer = {};
|
||||||
rhs.instancedIntegerBuffer = {};
|
rhs.instancedIntegerBuffer = {};
|
||||||
rhs.matPropsBuffer = {};
|
rhs.matPropsBuffer = {};
|
||||||
|
rhs.boneMatrixBuffer = {};
|
||||||
|
rhs.boneMatrixFirstIndexBuffer = {};
|
||||||
rhs.instanceDataDescSet = {};
|
rhs.instanceDataDescSet = {};
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -382,6 +399,10 @@ namespace SHADE
|
||||||
|
|
||||||
void SHBatch::UpdateAnimationBuffer(uint32_t frameIndex)
|
void SHBatch::UpdateAnimationBuffer(uint32_t frameIndex)
|
||||||
{
|
{
|
||||||
|
// Not animated pipeline, we skip
|
||||||
|
if (!isAnimated)
|
||||||
|
return;
|
||||||
|
|
||||||
// Frame Index check
|
// Frame Index check
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
{
|
{
|
||||||
|
@ -392,6 +413,9 @@ namespace SHADE
|
||||||
// Reset Animation Matrix Data
|
// Reset Animation Matrix Data
|
||||||
boneMatrixData.clear();
|
boneMatrixData.clear();
|
||||||
|
|
||||||
|
// Add the first identity matrix into the bone matrix data
|
||||||
|
boneMatrixData.emplace_back(SHMatrix::Identity);
|
||||||
|
|
||||||
// Populate on the CPU
|
// Populate on the CPU
|
||||||
for (auto& subBatch : subBatches)
|
for (auto& subBatch : subBatches)
|
||||||
for (auto rendId : subBatch.Renderables)
|
for (auto rendId : subBatch.Renderables)
|
||||||
|
@ -402,6 +426,7 @@ namespace SHADE
|
||||||
const auto& MATRICES = animator->GetBoneMatrices();
|
const auto& MATRICES = animator->GetBoneMatrices();
|
||||||
boneMatrixData.insert(boneMatrixData.end(), MATRICES.cbegin(), MATRICES.cend());
|
boneMatrixData.insert(boneMatrixData.end(), MATRICES.cbegin(), MATRICES.cend());
|
||||||
}
|
}
|
||||||
|
// We don't have to account for missing animators or reset indices as the renderable list are not updated at this point
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update GPU Buffers
|
// Update GPU Buffers
|
||||||
|
@ -446,13 +471,21 @@ namespace SHADE
|
||||||
// - EID data
|
// - EID data
|
||||||
instancedIntegerData.reserve(numTotalElements);
|
instancedIntegerData.reserve(numTotalElements);
|
||||||
instancedIntegerData.clear();
|
instancedIntegerData.clear();
|
||||||
|
if (isAnimated)
|
||||||
|
{
|
||||||
|
// - Bone Data
|
||||||
|
boneMatrixData.clear();
|
||||||
|
boneMatrixIndices.clear();
|
||||||
|
|
||||||
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
// Add the first identity matrix into the bone matrix data
|
||||||
|
boneMatrixData.emplace_back(SHMatrix::Identity);
|
||||||
|
}
|
||||||
|
|
||||||
// - Material Properties Data
|
// - Material Properties Data
|
||||||
|
auto const& DESC_MAPPINGS = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
||||||
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
||||||
(
|
(
|
||||||
descMappings.at(SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH),
|
DESC_MAPPINGS.at(SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH),
|
||||||
SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA,
|
SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA,
|
||||||
vk::ShaderStageFlagBits::eFragment
|
vk::ShaderStageFlagBits::eFragment
|
||||||
);
|
);
|
||||||
|
@ -470,9 +503,12 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// - Bone Data
|
// - Bone Data
|
||||||
boneMatrixData.clear();
|
if (isAnimated)
|
||||||
boneMatrixIndices.clear();
|
{
|
||||||
boneMatrixIndices.reserve(numTotalElements);
|
boneMatrixData.clear();
|
||||||
|
boneMatrixIndices.clear();
|
||||||
|
boneMatrixIndices.reserve(numTotalElements);
|
||||||
|
}
|
||||||
|
|
||||||
// Build Sub Batches
|
// Build Sub Batches
|
||||||
uint32_t nextInstanceIndex = 0;
|
uint32_t nextInstanceIndex = 0;
|
||||||
|
@ -548,12 +584,20 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bone Data
|
// Bone Data
|
||||||
auto animator = SHComponentManager::GetComponent_s<SHAnimatorComponent>(rendId);
|
if (isAnimated)
|
||||||
if (animator)
|
|
||||||
{
|
{
|
||||||
boneMatrixIndices.emplace_back(static_cast<uint32_t>(boneMatrixData.size()));
|
auto animator = SHComponentManager::GetComponent_s<SHAnimatorComponent>(rendId);
|
||||||
const auto& BONE_MATRICES = animator->GetBoneMatrices();
|
if (animator)
|
||||||
boneMatrixData.insert(boneMatrixData.end(), BONE_MATRICES.cbegin(), BONE_MATRICES.cend());
|
{
|
||||||
|
boneMatrixIndices.emplace_back(static_cast<uint32_t>(boneMatrixData.size()));
|
||||||
|
const auto& BONE_MATRICES = animator->GetBoneMatrices();
|
||||||
|
boneMatrixData.insert(boneMatrixData.end(), BONE_MATRICES.cbegin(), BONE_MATRICES.cend());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Take the first matrix which is always identity
|
||||||
|
boneMatrixIndices.emplace_back(static_cast<uint32_t>(0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -590,7 +634,7 @@ namespace SHADE
|
||||||
"Batch Instance Data Buffer"
|
"Batch Instance Data Buffer"
|
||||||
);
|
);
|
||||||
// - Bone Matrix Indices
|
// - Bone Matrix Indices
|
||||||
if (!boneMatrixIndices.empty())
|
if (isAnimated)
|
||||||
{
|
{
|
||||||
const uint32_t BMI_DATA_BYTES = static_cast<uint32_t>(boneMatrixIndices.size() * sizeof(uint32_t));
|
const uint32_t BMI_DATA_BYTES = static_cast<uint32_t>(boneMatrixIndices.size() * sizeof(uint32_t));
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
@ -625,7 +669,7 @@ namespace SHADE
|
||||||
|
|
||||||
// Bind all required objects before drawing
|
// Bind all required objects before drawing
|
||||||
std::vector<uint32_t> dynamicOffset{ 0 };
|
std::vector<uint32_t> dynamicOffset{ 0 };
|
||||||
if (!boneMatrixData.empty())
|
if (isAnimated)
|
||||||
{
|
{
|
||||||
dynamicOffset.emplace_back(0);
|
dynamicOffset.emplace_back(0);
|
||||||
}
|
}
|
||||||
|
@ -633,7 +677,7 @@ namespace SHADE
|
||||||
cmdBuffer->BindPipeline(pipeline);
|
cmdBuffer->BindPipeline(pipeline);
|
||||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
||||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);
|
||||||
if (boneMatrixFirstIndexBuffer[frameIndex])
|
if (isAnimated && boneMatrixFirstIndexBuffer[frameIndex])
|
||||||
{
|
{
|
||||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::BONE_MATRIX_FIRST_INDEX, boneMatrixFirstIndexBuffer[frameIndex], 0);
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::BONE_MATRIX_FIRST_INDEX, boneMatrixFirstIndexBuffer[frameIndex], 0);
|
||||||
}
|
}
|
||||||
|
@ -701,12 +745,14 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
layoutTypes = PreDefDescLayoutType::MATERIALS;
|
layoutTypes = PreDefDescLayoutType::MATERIALS;
|
||||||
}
|
}
|
||||||
if (!boneMatrixData.empty())
|
if (isAnimated)
|
||||||
{
|
{
|
||||||
layoutTypes = PreDefDescLayoutType::MATERIAL_AND_BONES;
|
layoutTypes = PreDefDescLayoutType::MATERIAL_AND_BONES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matPropsData || !boneMatrixData.empty())
|
const bool MUST_BUILD_ANIM_BUFFER = isAnimated && !boneMatrixData.empty();
|
||||||
|
|
||||||
|
if (matPropsData || MUST_BUILD_ANIM_BUFFER)
|
||||||
{
|
{
|
||||||
// Make sure that we have a descriptor set if we don't already have one
|
// Make sure that we have a descriptor set if we don't already have one
|
||||||
if (!instanceDataDescSet[frameIndex])
|
if (!instanceDataDescSet[frameIndex])
|
||||||
|
@ -756,7 +802,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Animation Bone Data */
|
/* Animation Bone Data */
|
||||||
if (!boneMatrixData.empty())
|
if (MUST_BUILD_ANIM_BUFFER)
|
||||||
{
|
{
|
||||||
// Update GPU Buffers
|
// Update GPU Buffers
|
||||||
const uint32_t BONE_MTX_DATA_BYTES = static_cast<uint32_t>(boneMatrixData.size() * sizeof(SHMatrix));
|
const uint32_t BONE_MTX_DATA_BYTES = static_cast<uint32_t>(boneMatrixData.size() * sizeof(SHMatrix));
|
||||||
|
@ -786,4 +832,21 @@ namespace SHADE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SHBatch::checkIfIsAnimatedPipeline(Handle<SHVkPipeline> pipeline)
|
||||||
|
{
|
||||||
|
if (!pipeline || !pipeline->GetPipelineLayout())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Grab the pipeline descriptor set layouts
|
||||||
|
auto pipelineDescLayouts = pipeline->GetPipelineLayout()->GetDescriptorSetLayoutsPipeline();
|
||||||
|
|
||||||
|
// Check if they contain the material and bones layout, that indicates it is
|
||||||
|
using GfxPreDefType = SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes;
|
||||||
|
const Handle<SHVkDescriptorSetLayout> BONE_DESC_SET_LAYOUT = SHGraphicsPredefinedData::GetPredefinedDescSetLayouts(GfxPreDefType::MATERIAL_AND_BONES)[0];
|
||||||
|
return std::find_if(pipelineDescLayouts.begin(), pipelineDescLayouts.end(), [BONE_DESC_SET_LAYOUT](Handle<SHVkDescriptorSetLayout> layout)
|
||||||
|
{
|
||||||
|
return BONE_DESC_SET_LAYOUT == layout;
|
||||||
|
}) != pipelineDescLayouts.end();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,8 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
// Resources
|
// Resources
|
||||||
Handle<SHVkLogicalDevice> device;
|
Handle<SHVkLogicalDevice> device;
|
||||||
|
// Config
|
||||||
|
bool isAnimated; // Whether the material supports animation
|
||||||
// Batch Properties
|
// Batch Properties
|
||||||
Handle<SHVkPipeline> pipeline;
|
Handle<SHVkPipeline> pipeline;
|
||||||
std::unordered_set<Handle<SHMaterialInstance>> referencedMatInstances;
|
std::unordered_set<Handle<SHMaterialInstance>> referencedMatInstances;
|
||||||
|
@ -126,7 +128,7 @@ namespace SHADE
|
||||||
Byte matPropsDataSize = 0;
|
Byte matPropsDataSize = 0;
|
||||||
Byte singleMatPropAlignedSize = 0;
|
Byte singleMatPropAlignedSize = 0;
|
||||||
Byte singleMatPropSize = 0;
|
Byte singleMatPropSize = 0;
|
||||||
std::vector<SHMatrix> boneMatrixData;
|
std::vector<SHMatrix> boneMatrixData; // 0th element is always an identity matrix
|
||||||
std::vector<uint32_t> boneMatrixIndices;
|
std::vector<uint32_t> boneMatrixIndices;
|
||||||
bool isCPUBuffersDirty = true;
|
bool isCPUBuffersDirty = true;
|
||||||
// GPU Buffers
|
// GPU Buffers
|
||||||
|
@ -143,5 +145,6 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
void setAllDirtyFlags();
|
void setAllDirtyFlags();
|
||||||
void rebuildDescriptorSetBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
void rebuildDescriptorSetBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||||
|
static bool checkIfIsAnimatedPipeline(Handle<SHVkPipeline> pipeline);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,6 +173,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Automatically set to index 0, which will be an identity matrix
|
||||||
vertBoneIdxStorage.resize(vertBoneIdxStorage.size() + addJob.VertexCount);
|
vertBoneIdxStorage.resize(vertBoneIdxStorage.size() + addJob.VertexCount);
|
||||||
}
|
}
|
||||||
if (addJob.VertexBoneWeights)
|
if (addJob.VertexBoneWeights)
|
||||||
|
|
Loading…
Reference in New Issue