Reduce vram usage by removing bones data in static spm
This commit is contained in:
parent
d37a3b8c7e
commit
6d74e84609
@ -29,12 +29,15 @@ private:
|
|||||||
size_t m_vbo_offset;
|
size_t m_vbo_offset;
|
||||||
|
|
||||||
size_t m_ibo_offset;
|
size_t m_ibo_offset;
|
||||||
|
|
||||||
|
bool m_has_skinning;
|
||||||
public:
|
public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
GESPMBuffer()
|
GESPMBuffer()
|
||||||
{
|
{
|
||||||
m_vbo_offset = 0;
|
m_vbo_offset = 0;
|
||||||
m_ibo_offset = 0;
|
m_ibo_offset = 0;
|
||||||
|
m_has_skinning = false;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual const irr::video::SMaterial& getMaterial() const
|
virtual const irr::video::SMaterial& getMaterial() const
|
||||||
@ -160,6 +163,8 @@ public:
|
|||||||
void setIBOOffset(size_t offset) { m_ibo_offset = offset; }
|
void setIBOOffset(size_t offset) { m_ibo_offset = offset; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
size_t getIBOOffset() const { return m_ibo_offset; }
|
size_t getIBOOffset() const { return m_ibo_offset; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
bool hasSkinning() const { return m_has_skinning; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace irr
|
} // end namespace irr
|
||||||
|
@ -155,16 +155,13 @@ void GEVulkanDrawCall::generate()
|
|||||||
unsigned visible_count = p.second.size();
|
unsigned visible_count = p.second.size();
|
||||||
if (visible_count != 0)
|
if (visible_count != 0)
|
||||||
{
|
{
|
||||||
bool skinning = false;
|
bool skinning = p.first->hasSkinning();
|
||||||
for (auto* node : p.second)
|
for (auto* node : p.second)
|
||||||
{
|
{
|
||||||
int skinning_offset = -1000;
|
int skinning_offset = -1000;
|
||||||
auto it = skinning_offets.find(node);
|
auto it = skinning_offets.find(node);
|
||||||
if (it != skinning_offets.end())
|
if (it != skinning_offets.end())
|
||||||
{
|
|
||||||
skinning = true;
|
|
||||||
skinning_offset = it->second;
|
skinning_offset = it->second;
|
||||||
}
|
|
||||||
m_visible_objects.emplace_back(node, material_id,
|
m_visible_objects.emplace_back(node, material_id,
|
||||||
skinning_offset);
|
skinning_offset);
|
||||||
}
|
}
|
||||||
@ -213,23 +210,27 @@ void GEVulkanDrawCall::createAllPipelines(GEVulkanDriver* vk)
|
|||||||
{
|
{
|
||||||
PipelineSettings settings;
|
PipelineSettings settings;
|
||||||
settings.m_vertex_shader = "spm.vert";
|
settings.m_vertex_shader = "spm.vert";
|
||||||
|
settings.m_skinning_vertex_shader = "spm_skinning.vert";
|
||||||
settings.m_fragment_shader = "solid.frag";
|
settings.m_fragment_shader = "solid.frag";
|
||||||
settings.m_shader_name = "solid";
|
settings.m_shader_name = "solid";
|
||||||
createPipeline(vk, settings);
|
createPipeline(vk, settings);
|
||||||
|
|
||||||
settings.m_vertex_shader = "spm_skinning.vert";
|
|
||||||
settings.m_shader_name = "solid_skinning";
|
|
||||||
createPipeline(vk, settings);
|
|
||||||
} // createAllPipelines
|
} // createAllPipelines
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void GEVulkanDrawCall::createPipeline(GEVulkanDriver* vk,
|
void GEVulkanDrawCall::createPipeline(GEVulkanDriver* vk,
|
||||||
const PipelineSettings& settings)
|
const PipelineSettings& settings)
|
||||||
{
|
{
|
||||||
|
bool creating_animated_pipeline_for_skinning = false;
|
||||||
|
std::string shader_name = settings.m_shader_name;
|
||||||
|
|
||||||
|
start:
|
||||||
VkPipelineShaderStageCreateInfo vert_shader_stage_info = {};
|
VkPipelineShaderStageCreateInfo vert_shader_stage_info = {};
|
||||||
vert_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
vert_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
vert_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
vert_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
vert_shader_stage_info.module = GEVulkanShaderManager::getShader(settings.m_vertex_shader);
|
vert_shader_stage_info.module = GEVulkanShaderManager::getShader(
|
||||||
|
creating_animated_pipeline_for_skinning ?
|
||||||
|
settings.m_skinning_vertex_shader : settings.m_vertex_shader);
|
||||||
vert_shader_stage_info.pName = "main";
|
vert_shader_stage_info.pName = "main";
|
||||||
|
|
||||||
VkPipelineShaderStageCreateInfo frag_shader_stage_info = {};
|
VkPipelineShaderStageCreateInfo frag_shader_stage_info = {};
|
||||||
@ -244,10 +245,15 @@ void GEVulkanDrawCall::createPipeline(GEVulkanDriver* vk,
|
|||||||
frag_shader_stage_info
|
frag_shader_stage_info
|
||||||
}};
|
}};
|
||||||
|
|
||||||
VkVertexInputBindingDescription binding_description = {};
|
size_t bone_pitch = sizeof(int16_t) * 8;
|
||||||
binding_description.binding = 0;
|
size_t static_pitch = sizeof(irr::video::S3DVertexSkinnedMesh) - bone_pitch;
|
||||||
binding_description.stride = sizeof(irr::video::S3DVertexSkinnedMesh);
|
std::array<VkVertexInputBindingDescription, 2> binding_descriptions;
|
||||||
binding_description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
binding_descriptions[0].binding = 0;
|
||||||
|
binding_descriptions[0].stride = static_pitch;
|
||||||
|
binding_descriptions[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
|
binding_descriptions[1].binding = 1;
|
||||||
|
binding_descriptions[1].stride = bone_pitch;
|
||||||
|
binding_descriptions[1].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
|
|
||||||
std::array<VkVertexInputAttributeDescription, 8> attribute_descriptions = {};
|
std::array<VkVertexInputAttributeDescription, 8> attribute_descriptions = {};
|
||||||
attribute_descriptions[0].binding = 0;
|
attribute_descriptions[0].binding = 0;
|
||||||
@ -274,21 +280,21 @@ void GEVulkanDrawCall::createPipeline(GEVulkanDriver* vk,
|
|||||||
attribute_descriptions[5].location = 5;
|
attribute_descriptions[5].location = 5;
|
||||||
attribute_descriptions[5].format = VK_FORMAT_A2B10G10R10_SNORM_PACK32;
|
attribute_descriptions[5].format = VK_FORMAT_A2B10G10R10_SNORM_PACK32;
|
||||||
attribute_descriptions[5].offset = offsetof(irr::video::S3DVertexSkinnedMesh, m_tangent);
|
attribute_descriptions[5].offset = offsetof(irr::video::S3DVertexSkinnedMesh, m_tangent);
|
||||||
attribute_descriptions[6].binding = 0;
|
attribute_descriptions[6].binding = 1;
|
||||||
attribute_descriptions[6].location = 6;
|
attribute_descriptions[6].location = 6;
|
||||||
attribute_descriptions[6].format = VK_FORMAT_R16G16B16A16_SINT;
|
attribute_descriptions[6].format = VK_FORMAT_R16G16B16A16_SINT;
|
||||||
attribute_descriptions[6].offset = offsetof(irr::video::S3DVertexSkinnedMesh, m_joint_idx);
|
attribute_descriptions[6].offset = 0;
|
||||||
attribute_descriptions[7].binding = 0;
|
attribute_descriptions[7].binding = 1;
|
||||||
attribute_descriptions[7].location = 7;
|
attribute_descriptions[7].location = 7;
|
||||||
attribute_descriptions[7].format = VK_FORMAT_R16G16B16A16_SFLOAT;
|
attribute_descriptions[7].format = VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||||
attribute_descriptions[7].offset = offsetof(irr::video::S3DVertexSkinnedMesh, m_weight);
|
attribute_descriptions[7].offset = sizeof(int16_t) * 4;
|
||||||
|
|
||||||
VkPipelineVertexInputStateCreateInfo vertex_input_info = {};
|
VkPipelineVertexInputStateCreateInfo vertex_input_info = {};
|
||||||
vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
vertex_input_info.vertexBindingDescriptionCount = 1;
|
vertex_input_info.vertexBindingDescriptionCount = 2;
|
||||||
vertex_input_info.vertexAttributeDescriptionCount = attribute_descriptions.size();
|
vertex_input_info.vertexAttributeDescriptionCount = 8;
|
||||||
vertex_input_info.pVertexBindingDescriptions = &binding_description;
|
vertex_input_info.pVertexBindingDescriptions = binding_descriptions.data();
|
||||||
vertex_input_info.pVertexAttributeDescriptions = &attribute_descriptions[0];
|
vertex_input_info.pVertexAttributeDescriptions = attribute_descriptions.data();
|
||||||
|
|
||||||
VkPipelineInputAssemblyStateCreateInfo input_assembly = {};
|
VkPipelineInputAssemblyStateCreateInfo input_assembly = {};
|
||||||
input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
@ -390,10 +396,19 @@ void GEVulkanDrawCall::createPipeline(GEVulkanDriver* vk,
|
|||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("vkCreateGraphicsPipelines failed for " +
|
throw std::runtime_error("vkCreateGraphicsPipelines failed for " +
|
||||||
settings.m_shader_name);
|
shader_name);
|
||||||
}
|
}
|
||||||
m_graphics_pipelines[settings.m_shader_name] = std::make_pair(
|
m_graphics_pipelines[shader_name] = std::make_pair(
|
||||||
graphics_pipeline, settings);
|
graphics_pipeline, settings);
|
||||||
|
|
||||||
|
if (settings.m_skinning_vertex_shader.empty())
|
||||||
|
return;
|
||||||
|
else if (creating_animated_pipeline_for_skinning)
|
||||||
|
return;
|
||||||
|
|
||||||
|
creating_animated_pipeline_for_skinning = true;
|
||||||
|
shader_name = settings.m_shader_name + "_skinning";
|
||||||
|
goto start;
|
||||||
} // createPipeline
|
} // createPipeline
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -648,10 +663,19 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
|
|||||||
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
m_pipeline_layout, 1, 1, &m_data_descriptor_sets[cur_frame], 0, NULL);
|
m_pipeline_layout, 1, 1, &m_data_descriptor_sets[cur_frame], 0, NULL);
|
||||||
|
|
||||||
VkDeviceSize offsets[] = {0};
|
|
||||||
GEVulkanMeshCache* mc = vk->getVulkanMeshCache();
|
GEVulkanMeshCache* mc = vk->getVulkanMeshCache();
|
||||||
VkBuffer vertex_buffer = mc->getBuffer();
|
std::array<VkBuffer, 2> vertex_buffer =
|
||||||
vkCmdBindVertexBuffers(cmd, 0, 1, &vertex_buffer, offsets);
|
{{
|
||||||
|
mc->getBuffer(),
|
||||||
|
mc->getBuffer()
|
||||||
|
}};
|
||||||
|
std::array<VkDeviceSize, 2> offsets =
|
||||||
|
{{
|
||||||
|
0,
|
||||||
|
mc->getSkinningVBOOffset()
|
||||||
|
}};
|
||||||
|
vkCmdBindVertexBuffers(cmd, 0, vertex_buffer.size(), vertex_buffer.data(),
|
||||||
|
offsets.data());
|
||||||
|
|
||||||
vkCmdBindIndexBuffer(cmd, mc->getBuffer(), mc->getIBOOffset(),
|
vkCmdBindIndexBuffer(cmd, mc->getBuffer(), mc->getIBOOffset(),
|
||||||
VK_INDEX_TYPE_UINT16);
|
VK_INDEX_TYPE_UINT16);
|
||||||
|
@ -42,6 +42,7 @@ struct ObjectData
|
|||||||
struct PipelineSettings
|
struct PipelineSettings
|
||||||
{
|
{
|
||||||
std::string m_vertex_shader;
|
std::string m_vertex_shader;
|
||||||
|
std::string m_skinning_vertex_shader;
|
||||||
std::string m_fragment_shader;
|
std::string m_fragment_shader;
|
||||||
std::string m_shader_name;
|
std::string m_shader_name;
|
||||||
};
|
};
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "IAnimatedMesh.h"
|
#include "IAnimatedMesh.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace GE
|
namespace GE
|
||||||
@ -19,7 +21,7 @@ GEVulkanMeshCache::GEVulkanMeshCache()
|
|||||||
m_ge_cache_time = 0;
|
m_ge_cache_time = 0;
|
||||||
m_buffer = VK_NULL_HANDLE;
|
m_buffer = VK_NULL_HANDLE;
|
||||||
m_memory = VK_NULL_HANDLE;
|
m_memory = VK_NULL_HANDLE;
|
||||||
m_ibo_offset = 0;
|
m_ibo_offset = m_skinning_vbo_offset = 0;
|
||||||
} // init
|
} // init
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -36,6 +38,10 @@ void GEVulkanMeshCache::updateCache()
|
|||||||
m_ge_cache_time = m_irrlicht_cache_time;
|
m_ge_cache_time = m_irrlicht_cache_time;
|
||||||
|
|
||||||
destroy();
|
destroy();
|
||||||
|
size_t total_pitch = getVertexPitchFromType(video::EVT_SKINNED_MESH);
|
||||||
|
size_t bone_pitch = sizeof(int16_t) * 8;
|
||||||
|
size_t static_pitch = total_pitch - bone_pitch;
|
||||||
|
|
||||||
size_t vbo_size, ibo_size;
|
size_t vbo_size, ibo_size;
|
||||||
vbo_size = 0;
|
vbo_size = 0;
|
||||||
ibo_size = 0;
|
ibo_size = 0;
|
||||||
@ -47,14 +53,21 @@ void GEVulkanMeshCache::updateCache()
|
|||||||
continue;
|
continue;
|
||||||
for (unsigned j = 0; j < mesh->getMeshBufferCount(); j++)
|
for (unsigned j = 0; j < mesh->getMeshBufferCount(); j++)
|
||||||
{
|
{
|
||||||
scene::IMeshBuffer* mb = mesh->getMeshBuffer(j);
|
GESPMBuffer* mb = static_cast<GESPMBuffer*>(mesh->getMeshBuffer(j));
|
||||||
vbo_size += mesh->getMeshBuffer(j)->getVertexCount();
|
size_t pitch = mb->hasSkinning() ? total_pitch : static_pitch;
|
||||||
ibo_size += mesh->getMeshBuffer(j)->getIndexCount();
|
vbo_size += mb->getVertexCount() * pitch;
|
||||||
buffers.push_back(static_cast<GESPMBuffer*>(mb));
|
ibo_size += mb->getIndexCount();
|
||||||
|
buffers.push_back(mb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vbo_size *= getVertexPitchFromType(video::EVT_SKINNED_MESH);
|
|
||||||
ibo_size *= sizeof(uint16_t);
|
ibo_size *= sizeof(uint16_t);
|
||||||
|
// Some devices (Apple for now) require vertex offset of alignment 4 bytes
|
||||||
|
ibo_size += getPadding(ibo_size, 4);
|
||||||
|
std::stable_partition(buffers.begin(), buffers.end(),
|
||||||
|
[](const GESPMBuffer* mb)
|
||||||
|
{
|
||||||
|
return !mb->hasSkinning();
|
||||||
|
});
|
||||||
|
|
||||||
VkBuffer staging_buffer = VK_NULL_HANDLE;
|
VkBuffer staging_buffer = VK_NULL_HANDLE;
|
||||||
VmaAllocation staging_memory = VK_NULL_HANDLE;
|
VmaAllocation staging_memory = VK_NULL_HANDLE;
|
||||||
@ -78,12 +91,16 @@ void GEVulkanMeshCache::updateCache()
|
|||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
for (GESPMBuffer* spm_buffer : buffers)
|
for (GESPMBuffer* spm_buffer : buffers)
|
||||||
{
|
{
|
||||||
size_t copy_size = spm_buffer->getVertexCount() *
|
size_t real_size = spm_buffer->getVertexCount() * total_pitch;
|
||||||
getVertexPitchFromType(video::EVT_SKINNED_MESH);
|
size_t copy_size = spm_buffer->getVertexCount() * static_pitch;
|
||||||
uint8_t* loc = mapped + offset;
|
uint8_t* loc = mapped + offset;
|
||||||
memcpy(loc, spm_buffer->getVertices(), copy_size);
|
for (unsigned i = 0; i < real_size; i += total_pitch)
|
||||||
spm_buffer->setVBOOffset(
|
{
|
||||||
offset / getVertexPitchFromType(video::EVT_SKINNED_MESH));
|
uint8_t* vertices = ((uint8_t*)spm_buffer->getVertices()) + i;
|
||||||
|
memcpy(loc, vertices, static_pitch);
|
||||||
|
loc += static_pitch;
|
||||||
|
}
|
||||||
|
spm_buffer->setVBOOffset(offset / static_pitch);
|
||||||
offset += copy_size;
|
offset += copy_size;
|
||||||
}
|
}
|
||||||
m_ibo_offset = offset;
|
m_ibo_offset = offset;
|
||||||
@ -97,6 +114,33 @@ void GEVulkanMeshCache::updateCache()
|
|||||||
spm_buffer->setIBOOffset(offset / sizeof(uint16_t));
|
spm_buffer->setIBOOffset(offset / sizeof(uint16_t));
|
||||||
offset += copy_size;
|
offset += copy_size;
|
||||||
}
|
}
|
||||||
|
m_skinning_vbo_offset = m_ibo_offset + offset;
|
||||||
|
m_skinning_vbo_offset += getPadding(m_skinning_vbo_offset, 4);
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
size_t static_vertex_offset = 0;
|
||||||
|
for (GESPMBuffer* spm_buffer : buffers)
|
||||||
|
{
|
||||||
|
if (!spm_buffer->hasSkinning())
|
||||||
|
{
|
||||||
|
static_vertex_offset += spm_buffer->getVertexCount() * bone_pitch;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
uint8_t* loc = mapped + offset + m_skinning_vbo_offset;
|
||||||
|
size_t real_size = spm_buffer->getVertexCount() * total_pitch;
|
||||||
|
for (unsigned i = 0; i < real_size; i += total_pitch)
|
||||||
|
{
|
||||||
|
uint8_t* vertices = ((uint8_t*)spm_buffer->getVertices()) + i +
|
||||||
|
static_pitch;
|
||||||
|
memcpy(loc, vertices, bone_pitch);
|
||||||
|
loc += bone_pitch;
|
||||||
|
}
|
||||||
|
offset += spm_buffer->getVertexCount() * bone_pitch;
|
||||||
|
}
|
||||||
|
assert(m_skinning_vbo_offset + offset == vbo_size + ibo_size);
|
||||||
|
assert(static_vertex_offset < m_skinning_vbo_offset);
|
||||||
|
m_skinning_vbo_offset -= static_vertex_offset;
|
||||||
|
|
||||||
vmaUnmapMemory(m_vk->getVmaAllocator(), staging_memory);
|
vmaUnmapMemory(m_vk->getVmaAllocator(), staging_memory);
|
||||||
vmaFlushAllocation(m_vk->getVmaAllocator(), staging_memory, 0, offset);
|
vmaFlushAllocation(m_vk->getVmaAllocator(), staging_memory, 0, offset);
|
||||||
|
|
||||||
@ -121,7 +165,7 @@ void GEVulkanMeshCache::destroy()
|
|||||||
vmaDestroyBuffer(m_vk->getVmaAllocator(), m_buffer, m_memory);
|
vmaDestroyBuffer(m_vk->getVmaAllocator(), m_buffer, m_memory);
|
||||||
m_buffer = VK_NULL_HANDLE;
|
m_buffer = VK_NULL_HANDLE;
|
||||||
m_memory = VK_NULL_HANDLE;
|
m_memory = VK_NULL_HANDLE;
|
||||||
m_ibo_offset = 0;
|
m_ibo_offset = m_skinning_vbo_offset = 0;
|
||||||
} // destroy
|
} // destroy
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ private:
|
|||||||
|
|
||||||
VmaAllocation m_memory;
|
VmaAllocation m_memory;
|
||||||
|
|
||||||
size_t m_ibo_offset;
|
size_t m_ibo_offset, m_skinning_vbo_offset;
|
||||||
public:
|
public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
GEVulkanMeshCache();
|
GEVulkanMeshCache();
|
||||||
@ -35,6 +35,8 @@ public:
|
|||||||
VkBuffer getBuffer() const { return m_buffer; }
|
VkBuffer getBuffer() const { return m_buffer; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
size_t getIBOOffset() const { return m_ibo_offset; }
|
size_t getIBOOffset() const { return m_ibo_offset; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
size_t getSkinningVBOOffset() const { return m_skinning_vbo_offset; }
|
||||||
}; // GEVulkanMeshCache
|
}; // GEVulkanMeshCache
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -105,6 +105,7 @@ scene::IAnimatedMesh* B3DMeshLoader::createMesh(io::IReadFile* f)
|
|||||||
{
|
{
|
||||||
SP::SPMeshBuffer* spbuf = spm->getSPMeshBuffer(i);
|
SP::SPMeshBuffer* spbuf = spm->getSPMeshBuffer(i);
|
||||||
GE::GESPMBuffer* gebuf = new GE::GESPMBuffer();
|
GE::GESPMBuffer* gebuf = new GE::GESPMBuffer();
|
||||||
|
gebuf->m_has_skinning = !spm->isStatic();
|
||||||
ge_spm->m_buffer.push_back(gebuf);
|
ge_spm->m_buffer.push_back(gebuf);
|
||||||
std::swap(gebuf->m_vertices, spbuf->getVerticesRef());
|
std::swap(gebuf->m_vertices, spbuf->getVerticesRef());
|
||||||
std::swap(gebuf->m_indices, spbuf->getIndicesRef());
|
std::swap(gebuf->m_indices, spbuf->getIndicesRef());
|
||||||
|
@ -556,6 +556,7 @@ void SPMeshLoader::decompressGESPM(irr::io::IReadFile* spm,
|
|||||||
// 1.0 in half float (16bit)
|
// 1.0 in half float (16bit)
|
||||||
vertex.m_weight[0] = 15360;
|
vertex.m_weight[0] = 15360;
|
||||||
}
|
}
|
||||||
|
mb->m_has_skinning = true;
|
||||||
}
|
}
|
||||||
vertices.push_back(vertex);
|
vertices.push_back(vertex);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user