Hi all,
I'm not sure if it's a bug in my code or a bug in the spine-c runtime, but it seems the further away from (0, 0) a mesh gets, the more distorted it gets.
For example, check out the knees on the characters here. The one on the left is relatively straight (as intended) but the one on the right is dangerously spikey.
Loading Image
I wasn't sure if this was specific to the characters idle/run animations or how the legs were put together in Spine, so I tried a bigger animation.
Close to (0, 0):
Loading Image
Far from (0, 0):
Loading Image
As you can see, bits of the mesh (chin, horn, beardybits) gets extruded (or possibly rounded) towards (0, 0).
Here are the exported atlas/json/png files:
http://forceofhab.it/files/temp/chudAvatar.atlas
http://forceofhab.it/files/temp/chudAvatar.json
http://forceofhab.it/_files/temp/chudAvatar.png
I tried to test these files with spine-js (easiest one to test for me besides spine-c) but that doesn't have the new meshes/ffd stuff so alas no succcess.
Here is the render code for the Skeletons. It's pretty much the spine-sfml rendering code:
void Skeleton::render() {
unsigned int BLEND_ADDITIVE = Renderer::BLEND_ADDITIVE;
unsigned int BLEND_SPINE = Renderer::BLEND_NORMAL;
Renderer* r = ARK2D::getRenderer();
r->setDrawColor(Color::white);
float worldVertices[SPINE_MESH_VERTEX_COUNT_MAX];
for (int i = 0; i < m_skeleton->slotCount; ++i)
{
spSlot* slot = m_skeleton->drawOrder[i];
spSlotData* slotdata = slot->data;
spAttachment* attachment = slot->attachment;
if (!attachment) { continue; }
unsigned int blend = slot->data->additiveBlending ? BLEND_ADDITIVE : BLEND_SPINE;
r->setBlendMode(blend);
if (attachment->type == SP_ATTACHMENT_REGION) {
spRegionAttachment* regionAttachment = (spRegionAttachment*)attachment;
spRegionAttachment_computeWorldVertices(regionAttachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
spAtlasRegion* spatreg = (spAtlasRegion*)regionAttachment->rendererObject;
Image* img = (Image*) spatreg->page->rendererObject;
unsigned int texId = img->getTexture()->getId();
float sx = img->getTextureW();
float sy = img->getTextureH();
float rawVertices[] = {
worldVertices[SP_VERTEX_X1], worldVertices[SP_VERTEX_Y1],
worldVertices[SP_VERTEX_X2], worldVertices[SP_VERTEX_Y2],
worldVertices[SP_VERTEX_X4], worldVertices[SP_VERTEX_Y4],
worldVertices[SP_VERTEX_X4], worldVertices[SP_VERTEX_Y4],
worldVertices[SP_VERTEX_X2], worldVertices[SP_VERTEX_Y2],
worldVertices[SP_VERTEX_X3], worldVertices[SP_VERTEX_Y3]
};
float rawTexCoords[] = {
regionAttachment->uvs[SP_VERTEX_X1] * sx, regionAttachment->uvs[SP_VERTEX_Y1] * sy,
regionAttachment->uvs[SP_VERTEX_X2] * sx, regionAttachment->uvs[SP_VERTEX_Y2] * sy,
regionAttachment->uvs[SP_VERTEX_X4] * sx, regionAttachment->uvs[SP_VERTEX_Y4] * sy,
regionAttachment->uvs[SP_VERTEX_X4] * sx, regionAttachment->uvs[SP_VERTEX_Y4] * sy,
regionAttachment->uvs[SP_VERTEX_X2] * sx, regionAttachment->uvs[SP_VERTEX_Y2] * sy,
regionAttachment->uvs[SP_VERTEX_X3] * sx, regionAttachment->uvs[SP_VERTEX_Y3] * sy
};
unsigned char re = (m_skeleton->r * slot->r * regionAttachment->r) * 255;
unsigned char g = (m_skeleton->g * slot->g * regionAttachment->g) * 255;
unsigned char b = (m_skeleton->b * slot->b * regionAttachment->b) * 255;
unsigned char a = (m_skeleton->a * slot->a * regionAttachment->a) * 255;
unsigned char rawColors[] = {
re, g, b, a,
re, g, b, a,
re, g, b, a,
re, g, b, a,
re, g, b, a,
re, g, b, a
};
r->texturedQuads(texId, &rawVertices[0], &rawTexCoords[0], &rawColors[0], 1);
} else if (attachment->type == SP_ATTACHMENT_MESH) {
//spRegionAttachment* regionAttachment = (spRegionAttachment*)attachment;
spMeshAttachment* mesh = (spMeshAttachment*) attachment;
if (mesh->uvsCount > SPINE_MESH_VERTEX_COUNT_MAX) { continue; }
spAtlasRegion* spatreg = (spAtlasRegion*) mesh->rendererObject;
Image* img = (Image*) spatreg->page->rendererObject;
unsigned int texId = img->getTexture()->getId();
float sx = img->getTextureW();
float sy = img->getTextureH();
spMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
float re_f = m_skeleton->r * slot->r * mesh->r;
float g_f = m_skeleton->g * slot->g * mesh->g;
float b_f = m_skeleton->b * slot->b * mesh->b;
float a_f = m_skeleton->a * slot->a * mesh->a;
unsigned char re = (unsigned char) (re_f * 255.0f);
unsigned char g = (unsigned char) (g_f * 255.0f);
unsigned char b = (unsigned char) (b_f * 255.0f);
unsigned char a = (unsigned char) (a_f * 255.0f);
#ifdef ARK2D_WINDOWS_VS
float* rawVertices = (float*)alloca((mesh->trianglesCount * 2) * sizeof(float));
float* rawTexCoords = (float*)alloca((mesh->trianglesCount * 2) * sizeof(float));
unsigned char* rawColors = (unsigned char*)alloca((mesh->trianglesCount * 4) * sizeof(unsigned char));
#else
float rawVertices[mesh->trianglesCount*2];
float rawTexCoords[mesh->trianglesCount*2];
unsigned char rawColors[mesh->trianglesCount*4];
#endif
/*string thisc = string("r: ");
thisc += Cast::toString<float>(re_f);
thisc += string(", g: ");
thisc += Cast::toString<float>(g_f);
thisc += string(", b: ");
thisc += Cast::toString<float>(b_f);
thisc += string(", a: ");
thisc += Cast::toString<float>(a_f);
ARK2D::getLog()->w(thisc); */
int k = 0;
int l = 0;
for (int j = 0; j < mesh->trianglesCount; ++j) {
int index = mesh->triangles[j] << 1;
rawVertices[k] = worldVertices[index];
rawVertices[k+1] = worldVertices[index+1];
rawTexCoords[k] = mesh->uvs[index] * sx;
rawTexCoords[k+1] = mesh->uvs[index + 1] * sy;
rawColors[l] = re;
rawColors[l+1] = g;
rawColors[l+2] = b;
rawColors[l+3] = a;
k += 2;
l += 4;
}
r->texturedTriangles(texId, &rawVertices[0], &rawTexCoords[0], &rawColors[0], mesh->trianglesCount/3);
} else if (attachment->type == SP_ATTACHMENT_SKINNED_MESH) {
spSkinnedMeshAttachment* mesh = (spSkinnedMeshAttachment*) attachment;
if (mesh->uvsCount > SPINE_MESH_VERTEX_COUNT_MAX) { continue; }
spAtlasRegion* spatreg = (spAtlasRegion*)mesh->rendererObject;
Image* img = (Image*) spatreg->page->rendererObject;
unsigned int texId = img->getTexture()->getId();
float sx = img->getTextureW();
float sy = img->getTextureH();
spSkinnedMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
float re_f = m_skeleton->r * slot->r * mesh->r;
float g_f = m_skeleton->g * slot->g * mesh->g;
float b_f = m_skeleton->b * slot->b * mesh->b;
float a_f = m_skeleton->a * slot->a * mesh->a;
unsigned char re = (unsigned char) (re_f * 255.0f);
unsigned char g = (unsigned char) (g_f * 255.0f);
unsigned char b = (unsigned char) (b_f * 255.0f);
unsigned char a = (unsigned char) (a_f * 255.0f);
#ifdef ARK2D_WINDOWS_VS
float* rawVertices = (float*)alloca((mesh->trianglesCount * 6) * sizeof(float));
float* rawTexCoords = (float*)alloca((mesh->trianglesCount * 6) * sizeof(float));
unsigned char* rawColors = (unsigned char*)alloca((mesh->trianglesCount * 12) * sizeof(unsigned char));
#else
float rawVertices[mesh->trianglesCount * 2];
float rawTexCoords[mesh->trianglesCount * 2];
unsigned char rawColors[mesh->trianglesCount * 4];
#endif
int k = 0;
int l = 0;
for (int j = 0; j < mesh->trianglesCount; ++j) {
int index = mesh->triangles[j] << 1;
rawVertices[k] = worldVertices[index];
rawVertices[k+1] = worldVertices[index+1];
rawTexCoords[k] = mesh->uvs[index] * sx;
rawTexCoords[k+1] = mesh->uvs[index + 1] * sy;
rawColors[l] = re;
rawColors[l+1] = g;
rawColors[l+2] = b;
rawColors[l+3] = a;
k += 2;
l += 4;
}
r->texturedTriangles(texId, &rawVertices[0], &rawTexCoords[0], &rawColors[0], mesh->trianglesCount/3);
} /*else if (attachment->type == SP_ATTACHMENT_BOUNDING_BOX) {
spBoundingBoxAttachment* boxAttachment = (spBoundingBoxAttachment*) attachment;
spBoundingBoxAttachment_computeWorldVertices (boxAttachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
r->setDrawColor(Color::white);
r->drawLine(worldVertices[SP_VERTEX_X1], worldVertices[SP_VERTEX_Y1], worldVertices[SP_VERTEX_X2], worldVertices[SP_VERTEX_Y2]);
r->drawLine(worldVertices[SP_VERTEX_X2], worldVertices[SP_VERTEX_Y2], worldVertices[SP_VERTEX_X3], worldVertices[SP_VERTEX_Y3]);
r->drawLine(worldVertices[SP_VERTEX_X3], worldVertices[SP_VERTEX_Y3], worldVertices[SP_VERTEX_X4], worldVertices[SP_VERTEX_Y4]);
r->drawLine(worldVertices[SP_VERTEX_X4], worldVertices[SP_VERTEX_Y4], worldVertices[SP_VERTEX_X1], worldVertices[SP_VERTEX_Y1]);
continue;
}*/
}
r->setBlendMode(Renderer::BLEND_NORMAL);
}
I've also called spBone_setYDown(1) because my setup has a top-left coordinate space.
Let me know if you need anything else to help solve the problem. 🙂
Many thanks,
Ashley
EDIT:
Quick and dirty mesh outline drawing (glPolygonMode). You an still sort of see it on that lip at the front of the face.
Loading Image
Loading Image