Эх сурвалжийг харах

[cpp] Skeleton.getBounds() optionally applies clipping, see #2515

Mario Zechner 1 жил өмнө
parent
commit
b8f0aaaacc

+ 5 - 1
spine-cpp/spine-cpp/include/spine/Skeleton.h

@@ -58,6 +58,8 @@ namespace spine {
 
 	class Attachment;
 
+    class SkeletonClipping;
+
 	class SP_API Skeleton : public SpineObject {
 		friend class AnimationState;
 
@@ -187,7 +189,9 @@ namespace spine {
 		/// @param outWidth The width of the AABB
 		/// @param outHeight The height of the AABB.
 		/// @param outVertexBuffer Reference to hold a Vector of floats. This method will assign it with new floats as needed.
-		void getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector<float> &outVertexBuffer);
+		// @param clipping Pointer to a SkeletonClipping instance or NULL. If a clipper is given, clipping attachments will be taken into account.
+        void getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector<float> &outVertexBuffer);
+		void getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector<float> &outVertexBuffer, SkeletonClipping *clipper);
 
 		Bone *getRootBone();
 

+ 3 - 0
spine-cpp/spine-cpp/include/spine/SkeletonClipping.h

@@ -48,6 +48,9 @@ namespace spine {
 
 		void clipEnd();
 
+        void
+        clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength);
+
 		void
 		clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength, float *uvs, size_t stride);
 

+ 41 - 13
spine-cpp/spine-cpp/src/spine/Skeleton.cpp

@@ -41,6 +41,7 @@
 
 #include <spine/BoneData.h>
 #include <spine/IkConstraintData.h>
+#include <spine/ClippingAttachment.h>
 #include <spine/MeshAttachment.h>
 #include <spine/PathAttachment.h>
 #include <spine/PathConstraintData.h>
@@ -48,6 +49,7 @@
 #include <spine/RegionAttachment.h>
 #include <spine/SlotData.h>
 #include <spine/TransformConstraintData.h>
+#include <spine/SkeletonClipping.h>
 
 #include <spine/ContainerUtil.h>
 
@@ -456,7 +458,14 @@ Skeleton::findPhysicsConstraint(const String &constraintName) {
 }
 
 void Skeleton::getBounds(float &outX, float &outY, float &outWidth,
-						 float &outHeight, Vector<float> &outVertexBuffer) {
+                         float &outHeight, Vector<float> &outVertexBuffer) {
+    getBounds(outX, outY, outWidth, outHeight, outVertexBuffer, NULL);
+}
+
+static unsigned short quadIndices[] = {0, 1, 2, 2, 3, 0};
+
+void Skeleton::getBounds(float &outX, float &outY, float &outWidth,
+						 float &outHeight, Vector<float> &outVertexBuffer, SkeletonClipping *clipper) {
 	float minX = FLT_MAX;
 	float minY = FLT_MAX;
 	float maxX = -FLT_MAX;
@@ -468,6 +477,8 @@ void Skeleton::getBounds(float &outX, float &outY, float &outWidth,
 			continue;
 		size_t verticesLength = 0;
 		Attachment *attachment = slot->getAttachment();
+        unsigned short *triangles = NULL;
+        size_t trianglesLength = 0;
 
 		if (attachment != NULL &&
 			attachment->getRTTI().instanceOf(RegionAttachment::rtti)) {
@@ -479,6 +490,8 @@ void Skeleton::getBounds(float &outX, float &outY, float &outWidth,
 				outVertexBuffer.setSize(8, 0);
 			}
 			regionAttachment->computeWorldVertices(*slot, outVertexBuffer, 0);
+            triangles = quadIndices;
+            trianglesLength = 6;
 		} else if (attachment != NULL &&
 				   attachment->getRTTI().instanceOf(MeshAttachment::rtti)) {
 			MeshAttachment *mesh = static_cast<MeshAttachment *>(attachment);
@@ -490,18 +503,33 @@ void Skeleton::getBounds(float &outX, float &outY, float &outWidth,
 
 			mesh->computeWorldVertices(*slot, 0, verticesLength,
 									   outVertexBuffer.buffer(), 0);
-		}
-
-		for (size_t ii = 0; ii < verticesLength; ii += 2) {
-			float vx = outVertexBuffer[ii];
-			float vy = outVertexBuffer[ii + 1];
-
-			minX = MathUtil::min(minX, vx);
-			minY = MathUtil::min(minY, vy);
-			maxX = MathUtil::max(maxX, vx);
-			maxY = MathUtil::max(maxY, vy);
-		}
-	}
+            triangles = mesh->getTriangles().buffer();
+            trianglesLength = mesh->getTriangles().size();
+		} else if (attachment != NULL &&
+            attachment->getRTTI().instanceOf(ClippingAttachment::rtti) && clipper != NULL) {
+            clipper->clipStart(*slot, static_cast<ClippingAttachment *>(attachment));
+        }
+
+        if (verticesLength > 0) {
+            float *vertices = outVertexBuffer.buffer();
+            if (clipper != NULL && clipper->isClipping()) {
+                clipper->clipTriangles(outVertexBuffer.buffer(), triangles, trianglesLength);
+                vertices = clipper->getClippedVertices().buffer();
+                verticesLength = clipper->getClippedVertices().size();
+            }
+            for (size_t ii = 0; ii < verticesLength; ii += 2) {
+                float vx = vertices[ii];
+                float vy = vertices[ii + 1];
+
+                minX = MathUtil::min(minX, vx);
+                minY = MathUtil::min(minY, vy);
+                maxX = MathUtil::max(maxX, vx);
+                maxY = MathUtil::max(maxY, vy);
+            }
+        }
+        if (clipper != NULL) clipper->clipEnd(*slot);
+	}
+    if (clipper != NULL) clipper->clipEnd();
 
 	outX = minX;
 	outY = minY;

+ 73 - 0
spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp

@@ -82,6 +82,79 @@ void SkeletonClipping::clipEnd() {
 	_clippingPolygon.clear();
 }
 
+void SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles,
+                                     size_t trianglesLength) {
+    Vector<float> &clipOutput = _clipOutput;
+    Vector<float> &clippedVertices = _clippedVertices;
+    Vector<unsigned short> &clippedTriangles = _clippedTriangles;
+    Vector<Vector<float> *> &polygons = *_clippingPolygons;
+    size_t polygonsCount = (*_clippingPolygons).size();
+
+    size_t index = 0;
+    clippedVertices.clear();
+    _clippedUVs.clear();
+    clippedTriangles.clear();
+
+    int stride = 2;
+    size_t i = 0;
+    continue_outer:
+    for (; i < trianglesLength; i += 3) {
+        int vertexOffset = triangles[i] * stride;
+        float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
+
+        vertexOffset = triangles[i + 1] * stride;
+        float x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
+
+        vertexOffset = triangles[i + 2] * stride;
+        float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
+
+        for (size_t p = 0; p < polygonsCount; p++) {
+            size_t s = clippedVertices.size();
+            if (clip(x1, y1, x2, y2, x3, y3, &(*polygons[p]), &clipOutput)) {
+                size_t clipOutputLength = clipOutput.size();
+                if (clipOutputLength == 0) continue;
+
+                size_t clipOutputCount = clipOutputLength >> 1;
+                clippedVertices.setSize(s + clipOutputCount * 2, 0);
+                for (size_t ii = 0; ii < clipOutputLength; ii += 2) {
+                    float x = clipOutput[ii], y = clipOutput[ii + 1];
+                    clippedVertices[s] = x;
+                    clippedVertices[s + 1] = y;
+                    s += 2;
+                }
+
+                s = clippedTriangles.size();
+                clippedTriangles.setSize(s + 3 * (clipOutputCount - 2), 0);
+                clipOutputCount--;
+                for (size_t ii = 1; ii < clipOutputCount; ii++) {
+                    clippedTriangles[s] = (unsigned short) (index);
+                    clippedTriangles[s + 1] = (unsigned short) (index + ii);
+                    clippedTriangles[s + 2] = (unsigned short) (index + ii + 1);
+                    s += 3;
+                }
+                index += clipOutputCount + 1;
+            } else {
+                clippedVertices.setSize(s + 3 * 2, 0);
+                clippedVertices[s] = x1;
+                clippedVertices[s + 1] = y1;
+                clippedVertices[s + 2] = x2;
+                clippedVertices[s + 3] = y2;
+                clippedVertices[s + 4] = x3;
+                clippedVertices[s + 5] = y3;
+
+                s = clippedTriangles.size();
+                clippedTriangles.setSize(s + 3, 0);
+                clippedTriangles[s] = (unsigned short) index;
+                clippedTriangles[s + 1] = (unsigned short) (index + 1);
+                clippedTriangles[s + 2] = (unsigned short) (index + 2);
+                index += 3;
+                i += 3;
+                goto continue_outer;
+            }
+        }
+    }
+}
+
 void SkeletonClipping::clipTriangles(Vector<float> &vertices, Vector<unsigned short> &triangles, Vector<float> &uvs,
 									 size_t stride) {
 	clipTriangles(vertices.buffer(), triangles.buffer(), triangles.size(), uvs.buffer(), stride);

+ 1 - 1
spine-sdl/example/main.cpp

@@ -58,9 +58,9 @@ int main(int argc, char **argv) {
 	drawable.animationState->getData()->setDefaultMix(0.2f);
 	drawable.skeleton->setPosition(400, 500);
 	drawable.skeleton->setToSetupPose();
-	drawable.update(0, spine::Physics_Update);
 	drawable.animationState->setAnimation(0, "portal", true);
 	drawable.animationState->addAnimation(0, "run", true, 0);
+    drawable.update(0, spine::Physics_Update);
 
 	bool quit = false;
 	uint64_t lastFrameTime = SDL_GetPerformanceCounter();