diff --git a/defold-spine/commonsrc/vertices.cpp b/defold-spine/commonsrc/vertices.cpp index 945d822..8e18f31 100644 --- a/defold-spine/commonsrc/vertices.cpp +++ b/defold-spine/commonsrc/vertices.cpp @@ -113,14 +113,48 @@ void GetSkeletonBounds(const spSkeleton* skeleton, SpineModelBounds& bounds) } +uint32_t CalcVertexBufferSize(const spSkeleton* skeleton, uint32_t* out_max_triangle_count) +{ + uint32_t count = 0; + uint32_t max_triangle_count = 8; + for (int s = 0; s < skeleton->slotsCount; ++s) + { + spSlot* slot = skeleton->drawOrder[s]; + + spAttachment* attachment = slot->attachment; + if (!attachment)continue; + if (attachment->type == SP_ATTACHMENT_REGION) + { + count += 6; + } + else if (attachment->type == SP_ATTACHMENT_MESH) + { + spMeshAttachment* mesh = (spMeshAttachment*)attachment; + uint32_t num_tri_vertices = SUPER(mesh)->worldVerticesLength; + + count += (uint32_t)mesh->trianglesCount; // It's a list of indices, where each 3-tuple define a triangle + if (num_tri_vertices > max_triangle_count) + max_triangle_count = num_tri_vertices; + } + } + if (out_max_triangle_count) + *out_max_triangle_count = max_triangle_count; + return count; +} + uint32_t GenerateVertexData(dmArray& vertex_buffer, const spSkeleton* skeleton, const dmVMath::Matrix4& world) { - dmArray scratch; // scratch buffer + static dmArray scratch; // scratch buffer int vindex = vertex_buffer.Size(); int vindex_start = vindex; + uint32_t max_triangle_count = 0; + uint32_t estimated_vcount = CalcVertexBufferSize(skeleton, &max_triangle_count); + EnsureArrayFitsNumber(scratch, max_triangle_count); + EnsureArrayFitsNumber(vertex_buffer, estimated_vcount); + // For each slot in the draw order array of the skeleton for (int s = 0; s < skeleton->slotsCount; ++s) { @@ -176,9 +210,6 @@ uint32_t GenerateVertexData(dmArray& vertex_buffer, const spSkeleto spRegionAttachment* regionAttachment = (spRegionAttachment*)attachment; const float* uvs = regionAttachment->uvs; - EnsureArrayFitsNumber(scratch, 4*2); - EnsureArrayFitsNumber(vertex_buffer, 6); - float colorR = tintR * regionAttachment->color.r; float colorG = tintG * regionAttachment->color.g; float colorB = tintB * regionAttachment->color.b; @@ -199,8 +230,6 @@ uint32_t GenerateVertexData(dmArray& vertex_buffer, const spSkeleto addVertex(&vertex_buffer[vindex++], scratch[4], scratch[5], uvs[4], uvs[5], colorR, colorG, colorB, colorA); addVertex(&vertex_buffer[vindex++], scratch[6], scratch[7], uvs[6], uvs[7], colorR, colorG, colorB, colorA); addVertex(&vertex_buffer[vindex++], scratch[0], scratch[1], uvs[0], uvs[1], colorR, colorG, colorB, colorA); - - scratch.SetSize(0); } else if (attachment->type == SP_ATTACHMENT_MESH) { @@ -208,12 +237,7 @@ uint32_t GenerateVertexData(dmArray& vertex_buffer, const spSkeleto // and compute the world vertices spMeshAttachment* mesh = (spMeshAttachment*)attachment; - int num_world_vertices = mesh->super.worldVerticesLength / 2; - - EnsureArrayFitsNumber(scratch, num_world_vertices*2); - - int num_tri_vertices = mesh->trianglesCount; // It's a list of indices, where each 3-tuple define a triangle - EnsureArrayFitsNumber(vertex_buffer, num_tri_vertices); + int num_world_vertices = SUPER(mesh)->worldVerticesLength / 2; // Computed the world vertices positions for the vertices that make up // the mesh attachment. This assumes the world transform of the @@ -241,10 +265,9 @@ uint32_t GenerateVertexData(dmArray& vertex_buffer, const spSkeleto addVertex(&vertex_buffer[vindex++], scratch[index], scratch[index + 1], uvs[index], uvs[index + 1], colorR, colorG, colorB, colorA); } - - scratch.SetSize(0); } } + scratch.SetSize(0); const dmVMath::Matrix4& w = world; @@ -260,6 +283,8 @@ uint32_t GenerateVertexData(dmArray& vertex_buffer, const spSkeleto vertex->y = p.getY(); vertex->z = p.getZ(); } + + assert(vcount == estimated_vcount); } return vcount; diff --git a/defold-spine/include/common/vertices.h b/defold-spine/include/common/vertices.h index eccef56..d9b24a7 100644 --- a/defold-spine/include/common/vertices.h +++ b/defold-spine/include/common/vertices.h @@ -26,6 +26,7 @@ struct SpineModelBounds float maxY; }; +uint32_t CalcVertexBufferSize(const spSkeleton* skeleton, uint32_t* out_max_triangle_count); uint32_t GenerateVertexData(dmArray& vertex_buffer, const spSkeleton* skeleton, const dmVMath::Matrix4& world); void GetSkeletonBounds(const spSkeleton* skeleton, SpineModelBounds& bounds); diff --git a/defold-spine/src/comp_spine_model.cpp b/defold-spine/src/comp_spine_model.cpp index 70249d7..9801bb5 100644 --- a/defold-spine/src/comp_spine_model.cpp +++ b/defold-spine/src/comp_spine_model.cpp @@ -758,6 +758,18 @@ namespace dmSpine uint32_t vertex_start = world->m_VertexBufferData.Size(); uint32_t vertex_count = 0; + + for (uint32_t *i = begin; i != end; ++i) + { + component_index = (uint32_t)buf[*i].m_UserData; + const SpineModelComponent* component = (const SpineModelComponent*) components[component_index]; + vertex_count += dmSpine::CalcVertexBufferSize(component->m_SkeletonInstance, 0); + } + + if (vertex_count > world->m_VertexBufferData.Capacity()) + world->m_VertexBufferData.SetCapacity(vertex_count); + + vertex_count = 0; for (uint32_t *i = begin; i != end; ++i) { component_index = (uint32_t)buf[*i].m_UserData; @@ -860,7 +872,7 @@ namespace dmSpine { case dmRender::RENDER_LIST_OPERATION_BEGIN: { - dmGraphics::SetVertexBufferData(world->m_VertexBuffer, 0, 0, dmGraphics::BUFFER_USAGE_STATIC_DRAW); + dmGraphics::SetVertexBufferData(world->m_VertexBuffer, 0, 0, dmGraphics::BUFFER_USAGE_DYNAMIC_DRAW); world->m_RenderObjects.SetSize(0); world->m_VertexBufferData.SetSize(0); break; @@ -873,7 +885,7 @@ namespace dmSpine case dmRender::RENDER_LIST_OPERATION_END: { dmGraphics::SetVertexBufferData(world->m_VertexBuffer, sizeof(dmSpine::SpineVertex) * world->m_VertexBufferData.Size(), - world->m_VertexBufferData.Begin(), dmGraphics::BUFFER_USAGE_STATIC_DRAW); + world->m_VertexBufferData.Begin(), dmGraphics::BUFFER_USAGE_DYNAMIC_DRAW); //DM_COUNTER("SpineVertexBuffer", world->m_VertexBufferData.Size() * sizeof(dmSpine::SpineVertex)); break; }