int spSkeletonClipping_clipStart(spSkeletonClipping* self, spSlot* slot, spClippingAttachment* clip) { int i, n; float* vertices; if (self->clipAttachment) return 0; self->clipAttachment = clip; n = clip->super.worldVerticesLength; vertices = spFloatArray_setSize(self->clippingPolygon, n)->items; spVertexAttachment_computeWorldVertices(SUPER(clip), slot, 0, n, vertices, 0, 2); _makeClockwise(self->clippingPolygon); self->clippingPolygons = spTriangulator_decompose(self->triangulator, self->clippingPolygon, spTriangulator_triangulate(self->triangulator, self->clippingPolygon)); for (i = 0, n = self->clippingPolygons->size; i < n; i++) { spFloatArray* polygon = self->clippingPolygons->items[i]; _makeClockwise(polygon); spFloatArray_add(polygon, polygon->items[0]); spFloatArray_add(polygon, polygon->items[1]); } return self->clippingPolygons->size; }
void SpineDrawable::updateBoundingBox() { boundingBox.reset(); for (int i = 0; i < skeleton->slotsCount; ++i) { spSlot* slot = skeleton->drawOrder[i]; spAttachment* attachment = slot->attachment; if (attachment) { if (attachment->type == SP_ATTACHMENT_REGION) { spRegionAttachment* regionAttachment = reinterpret_cast<spRegionAttachment*>(attachment); spRegionAttachment_computeWorldVertices(regionAttachment, slot->bone, worldVertices, 0, 2); boundingBox.insertPoint(ouzel::Vector3(worldVertices[0], worldVertices[1], 0.0F)); boundingBox.insertPoint(ouzel::Vector3(worldVertices[2], worldVertices[3], 0.0F)); boundingBox.insertPoint(ouzel::Vector3(worldVertices[4], worldVertices[5], 0.0F)); boundingBox.insertPoint(ouzel::Vector3(worldVertices[6], worldVertices[7], 0.0F)); } else if (attachment->type == SP_ATTACHMENT_MESH) { spMeshAttachment* meshAttachment = reinterpret_cast<spMeshAttachment*>(attachment); if (meshAttachment->trianglesCount * 3 > SPINE_MESH_VERTEX_COUNT_MAX) continue; spVertexAttachment_computeWorldVertices(SUPER(meshAttachment), slot, 0, meshAttachment->super.worldVerticesLength, worldVertices, 0, 2); for (int t = 0; t < meshAttachment->trianglesCount; ++t) { int index = meshAttachment->triangles[t] << 1; boundingBox.insertPoint(ouzel::Vector3(worldVertices[index], worldVertices[index + 1], 0.0F)); } } } } }
void SpineDrawable::draw(const ouzel::Matrix4& transformMatrix, float opacity, const ouzel::Matrix4& renderViewProjection, bool wireframe) { Component::draw(transformMatrix, opacity, renderViewProjection, wireframe); spAnimationState_apply(animationState, skeleton); spSkeleton_updateWorldTransform(skeleton); std::vector<std::vector<float>> vertexShaderConstants(1); ouzel::Matrix4 modelViewProj = renderViewProjection * transformMatrix; vertexShaderConstants[0] = {std::begin(modelViewProj.m), std::end(modelViewProj.m)}; ouzel::graphics::Vertex vertex; uint16_t currentVertexIndex = 0; indices.clear(); vertices.clear(); uint32_t offset = 0; boundingBox.reset(); struct DrawCommand { std::shared_ptr<ouzel::graphics::Material> material; uint32_t indexCount; uint32_t offset; std::vector<std::vector<float>> pixelShaderConstants = std::vector<std::vector<float>>(1); }; std::vector<DrawCommand> drawCommands; for (int i = 0; i < skeleton->slotsCount; ++i) { spSlot* slot = skeleton->drawOrder[i]; spAttachment* attachment = slot->attachment; if (!attachment) continue; DrawCommand drawCommand; drawCommand.material = materials[static_cast<size_t>(i)]; float colorVector[] = {slot->color.r * drawCommand.material->diffuseColor.normR(), slot->color.g * drawCommand.material->diffuseColor.normG(), slot->color.b * drawCommand.material->diffuseColor.normB(), slot->color.a * drawCommand.material->diffuseColor.normA() * opacity}; drawCommand.pixelShaderConstants[0] = {std::begin(colorVector), std::end(colorVector)}; if (attachment->type == SP_ATTACHMENT_REGION) { spRegionAttachment* regionAttachment = reinterpret_cast<spRegionAttachment*>(attachment); spRegionAttachment_computeWorldVertices(regionAttachment, slot->bone, worldVertices, 0, 2); uint8_t r = static_cast<uint8_t>(skeleton->color.r * 255.0f); uint8_t g = static_cast<uint8_t>(skeleton->color.g * 255.0f); uint8_t b = static_cast<uint8_t>(skeleton->color.b * 255.0f); uint8_t a = static_cast<uint8_t>(skeleton->color.a * 255.0f); vertex.color.r = r; vertex.color.g = g; vertex.color.b = b; vertex.color.a = a; vertex.position.x = worldVertices[0]; vertex.position.y = worldVertices[1]; vertex.texCoords[0].x = regionAttachment->uvs[0]; vertex.texCoords[0].y = regionAttachment->uvs[1]; vertex.normal = ouzel::Vector3(0.0f, 0.0f, -1.0f); vertices.push_back(vertex); vertex.color.r = r; vertex.color.g = g; vertex.color.b = b; vertex.color.a = a; vertex.position.x = worldVertices[2]; vertex.position.y = worldVertices[3]; vertex.texCoords[0].x = regionAttachment->uvs[2]; vertex.texCoords[0].y = regionAttachment->uvs[3]; vertex.normal = ouzel::Vector3(0.0f, 0.0f, -1.0f); vertices.push_back(vertex); vertex.color.r = r; vertex.color.g = g; vertex.color.b = b; vertex.color.a = a; vertex.position.x = worldVertices[4]; vertex.position.y = worldVertices[5]; vertex.texCoords[0].x = regionAttachment->uvs[4]; vertex.texCoords[0].y = regionAttachment->uvs[5]; vertex.normal = ouzel::Vector3(0.0f, 0.0f, -1.0f); vertices.push_back(vertex); vertex.color.r = r; vertex.color.g = g; vertex.color.b = b; vertex.color.a = a; vertex.position.x = worldVertices[6]; vertex.position.y = worldVertices[7]; vertex.texCoords[0].x = regionAttachment->uvs[6]; vertex.texCoords[0].y = regionAttachment->uvs[7]; vertex.normal = ouzel::Vector3(0.0f, 0.0f, -1.0f); vertices.push_back(vertex); indices.push_back(currentVertexIndex + 0); indices.push_back(currentVertexIndex + 1); indices.push_back(currentVertexIndex + 2); indices.push_back(currentVertexIndex + 0); indices.push_back(currentVertexIndex + 2); indices.push_back(currentVertexIndex + 3); currentVertexIndex += 4; boundingBox.insertPoint(ouzel::Vector3(worldVertices[0], worldVertices[1], 0.0F)); boundingBox.insertPoint(ouzel::Vector3(worldVertices[2], worldVertices[3], 0.0F)); boundingBox.insertPoint(ouzel::Vector3(worldVertices[4], worldVertices[5], 0.0F)); boundingBox.insertPoint(ouzel::Vector3(worldVertices[6], worldVertices[7], 0.0F)); if (!materials[static_cast<size_t>(i)]->textures[0]) { SpineTexture* texture = static_cast<SpineTexture*>((static_cast<spAtlasRegion*>(regionAttachment->rendererObject))->page->rendererObject); if (texture) materials[static_cast<size_t>(i)]->textures[0] = texture->texture; } } else if (attachment->type == SP_ATTACHMENT_MESH) { spMeshAttachment* meshAttachment = reinterpret_cast<spMeshAttachment*>(attachment); if (meshAttachment->trianglesCount * 3 > SPINE_MESH_VERTEX_COUNT_MAX) continue; spVertexAttachment_computeWorldVertices(SUPER(meshAttachment), slot, 0, meshAttachment->super.worldVerticesLength, worldVertices, 0, 2); vertex.color.r = static_cast<uint8_t>(skeleton->color.r * 255.0f); vertex.color.g = static_cast<uint8_t>(skeleton->color.g * 255.0f); vertex.color.b = static_cast<uint8_t>(skeleton->color.b * 255.0f); vertex.color.a = static_cast<uint8_t>(skeleton->color.a * 255.0f); for (int t = 0; t < meshAttachment->trianglesCount; ++t) { int index = meshAttachment->triangles[t] << 1; vertex.position.x = worldVertices[index]; vertex.position.y = worldVertices[index + 1]; vertex.texCoords[0].x = meshAttachment->uvs[index]; vertex.texCoords[0].y = meshAttachment->uvs[index + 1]; indices.push_back(currentVertexIndex); currentVertexIndex++; vertices.push_back(vertex); boundingBox.insertPoint(ouzel::Vector3(worldVertices[index], worldVertices[index + 1], 0.0F)); } if (!materials[static_cast<size_t>(i)]->textures[0]) { SpineTexture* texture = static_cast<SpineTexture*>((static_cast<spAtlasRegion*>(meshAttachment->rendererObject))->page->rendererObject); if (texture) materials[static_cast<size_t>(i)]->textures[0] = texture->texture; } } else { continue; } if (indices.size() - offset > 0) { drawCommand.indexCount = static_cast<uint32_t>(indices.size()) - offset; drawCommand.offset = offset; drawCommands.push_back(drawCommand); } offset = static_cast<uint32_t>(indices.size()); } indexBuffer->setData(indices.data(), static_cast<uint32_t>(ouzel::getVectorSize(indices))); vertexBuffer->setData(vertices.data(), static_cast<uint32_t>(ouzel::getVectorSize(vertices))); for (const DrawCommand& drawCommand : drawCommands) { std::vector<uintptr_t> textures; if (wireframe) textures.push_back(whitePixelTexture->getResource()); else for (const auto& texture : drawCommand.material->textures) textures.push_back(texture ? texture->getResource() : 0); ouzel::engine->getRenderer()->setCullMode(drawCommand.material->cullMode); ouzel::engine->getRenderer()->setPipelineState(drawCommand.material->blendState->getResource(), drawCommand.material->shader->getResource()); ouzel::engine->getRenderer()->setShaderConstants(drawCommand.pixelShaderConstants, vertexShaderConstants); ouzel::engine->getRenderer()->setTextures(textures); ouzel::engine->getRenderer()->draw(indexBuffer->getResource(), drawCommand.indexCount, sizeof(uint16_t), vertexBuffer->getResource(), ouzel::graphics::DrawMode::TRIANGLE_LIST, drawCommand.offset); } }
void spMeshAttachment_computeWorldVertices (spMeshAttachment* self, spSlot* slot, float* worldVertices) { spVertexAttachment_computeWorldVertices(SUPER(self), slot, worldVertices); }