소스 검색

[lua] Fixed SkeletonClipping. [corona] Refactored rendering, should be a bit faster as it avoids a bunch of copies. Fixed RegionAttachment to be in alignement with reference implementation

badlogic 8 년 전
부모
커밋
8123422f33

+ 10 - 4
spine-corona/main.lua

@@ -77,12 +77,12 @@ end
 
 
 -- table.insert(skeletons, loadSkeleton("test.atlas", "test.json", 240, 300, 0.4, "animation"))
 -- table.insert(skeletons, loadSkeleton("test.atlas", "test.json", 240, 300, 0.4, "animation"))
 table.insert(skeletons, loadSkeleton("coin.atlas", "coin.json", 240, 300, 0.4, "rotate"))
 table.insert(skeletons, loadSkeleton("coin.atlas", "coin.json", 240, 300, 0.4, "rotate"))
---[[table.insert(skeletons, loadSkeleton("spineboy.atlas", "spineboy.json", 240, 300, 0.4, "walk"))
+table.insert(skeletons, loadSkeleton("spineboy.atlas", "spineboy.json", 240, 300, 0.4, "walk"))
 table.insert(skeletons, loadSkeleton("raptor.atlas", "raptor.json", 200, 300, 0.25, "walk"))
 table.insert(skeletons, loadSkeleton("raptor.atlas", "raptor.json", 200, 300, 0.25, "walk"))
 table.insert(skeletons, loadSkeleton("goblins.atlas", "goblins-mesh.json", 240, 300, 0.8, "walk", "goblin"))
 table.insert(skeletons, loadSkeleton("goblins.atlas", "goblins-mesh.json", 240, 300, 0.8, "walk", "goblin"))
 table.insert(skeletons, loadSkeleton("stretchyman.atlas", "stretchyman.json", 40, 300, 0.5, "sneak"))
 table.insert(skeletons, loadSkeleton("stretchyman.atlas", "stretchyman.json", 40, 300, 0.5, "sneak"))
 table.insert(skeletons, loadSkeleton("tank.atlas", "tank.json", 400, 300, 0.2, "drive"))
 table.insert(skeletons, loadSkeleton("tank.atlas", "tank.json", 400, 300, 0.2, "drive"))
-table.insert(skeletons, loadSkeleton("vine.atlas", "vine.json", 240, 300, 0.3, "animation"))]]--
+table.insert(skeletons, loadSkeleton("vine.atlas", "vine.json", 240, 300, 0.3, "animation"))
 
 
 local triangulator = spine.Triangulator.new()
 local triangulator = spine.Triangulator.new()
 local polygon = { 411, 219, 199, 230, 161, 362, 534, 407, 346, 305, 596, 265 }
 local polygon = { 411, 219, 199, 230, 161, 362, 534, 407, 346, 305, 596, 265 }
@@ -90,6 +90,12 @@ local indices = triangulator:triangulate(polygon)
 print(indices)
 print(indices)
 print(triangulator:decompose(polygon, indices))
 print(triangulator:decompose(polygon, indices))
 
 
+local skeletonClipping = spine.SkeletonClipping.new()
+local polygon2 = {0, 0, 100, 0, 100, 100, 0, 100 }
+skeletonClipping:makeClockwise(polygon2)
+print(polygon2)
+
+
 local bounds = spine.SkeletonBounds.new()
 local bounds = spine.SkeletonBounds.new()
 skeletons[1].skeleton:updateWorldTransform()
 skeletons[1].skeleton:updateWorldTransform()
 bounds:update(skeletons[1].skeleton, true)
 bounds:update(skeletons[1].skeleton, true)
@@ -110,7 +116,7 @@ Runtime:addEventListener("enterFrame", function (event)
 	state = skeletons[activeSkeleton].state
 	state = skeletons[activeSkeleton].state
 
 
 	state:update(delta)
 	state:update(delta)
-	-- state:apply(skeleton)
+	state:apply(skeleton)
 	skeleton:updateWorldTransform()
 	skeleton:updateWorldTransform()
 
 
 	-- uncomment if you want to know how many batches a skeleton renders to
 	-- uncomment if you want to know how many batches a skeleton renders to
@@ -120,7 +126,7 @@ end)
 Runtime:addEventListener("key", function(event)
 Runtime:addEventListener("key", function(event)
 	if activeSkeleton == 2 and event.phase == "down" then
 	if activeSkeleton == 2 and event.phase == "down" then
 		state = skeletons[activeSkeleton].state
 		state = skeletons[activeSkeleton].state
-		state:setAnimationByName(0, "Jump", false)
+		state:setAnimationByName(0, "jump", false)
 		state:addAnimationByName(0, "walk", true, 0)
 		state:addAnimationByName(0, "walk", true, 0)
 	end
 	end
 	return false
 	return false

+ 43 - 71
spine-corona/spine-corona/spine.lua

@@ -92,6 +92,7 @@ spine.Skeleton.new = function(skeletonData, group)
 	self.batches = 0
 	self.batches = 0
 	self.tempColor = spine.Color.newWith(1, 1, 1, 1)
 	self.tempColor = spine.Color.newWith(1, 1, 1, 1)
 	self.tempColor2 = spine.Color.newWith(-1, 1, 1, 1)
 	self.tempColor2 = spine.Color.newWith(-1, 1, 1, 1)
+	self.clipper = spine.SkeletonClipping.new()
 	return self
 	return self
 end
 end
 
 
@@ -140,25 +141,49 @@ function spine.Skeleton:updateWorldTransform()
 	local lastTexture = nil
 	local lastTexture = nil
 	local blendMode = nil
 	local blendMode = nil
 	local lastBlendMode = nil
 	local lastBlendMode = nil
+	local renderable = {
+		vertices = nil,
+		uvs = nil
+	}
+	
 	for i,slot in ipairs(drawOrder) do
 	for i,slot in ipairs(drawOrder) do
 		local attachment = slot.attachment
 		local attachment = slot.attachment
 		local vertices = nil
 		local vertices = nil
+		local uvs = nil
 		local numVertices = 0
 		local numVertices = 0
 		local indices = nil
 		local indices = nil
 		if attachment then
 		if attachment then
 			if attachment.type == spine.AttachmentType.region then
 			if attachment.type == spine.AttachmentType.region then
 				numVertices = 4
 				numVertices = 4
-				vertices = self:computeRegionVertices(slot, attachment, premultipliedAlpha, color)
+				vertices = worldVertices
+				attachment:computeWorldVertices(slot.bone, vertices, 0, 2)
+				uvs = attachment.uvs
 				indices = QUAD_TRIANGLES
 				indices = QUAD_TRIANGLES
 				texture = attachment.region.renderObject.texture				
 				texture = attachment.region.renderObject.texture				
 				blendMode = toCoronaBlendMode(slot.data.blendMode)
 				blendMode = toCoronaBlendMode(slot.data.blendMode)
 			elseif attachment.type == spine.AttachmentType.mesh then
 			elseif attachment.type == spine.AttachmentType.mesh then
 				numVertices = attachment.worldVerticesLength / 2
 				numVertices = attachment.worldVerticesLength / 2
-				vertices = self:computeMeshVertices(slot, attachment, premultipliedAlpha, color)
+				vertices = worldVertices
+				attachment:computeWorldVertices(slot, 0, attachment.worldVerticesLength, vertices, 0, 2)
+				uvs = attachment.uvs
 				indices = attachment.triangles
 				indices = attachment.triangles
 				texture = attachment.region.renderObject.texture
 				texture = attachment.region.renderObject.texture
 				blendMode = toCoronaBlendMode(slot.data.blendMode)
 				blendMode = toCoronaBlendMode(slot.data.blendMode)
+			elseif attachment.type == spine.AttachmentType.clipping then
+				self.clipper:clipStart(slot, attachment)
 			end
 			end
+			
+			local skeleton = slot.bone.skeleton
+			local skeletonColor = skeleton.color
+			local slotColor = slot.color
+			local attachmentColor = attachment.color
+			local alpha = skeletonColor.a * slotColor.a * attachmentColor.a
+			local multiplier = alpha
+			if premultipliedAlpha then multiplier = 1 end
+			color:set(skeletonColor.r * slotColor.r * attachmentColor.r * multiplier,
+								skeletonColor.g * slotColor.g * attachmentColor.g * multiplier,
+								skeletonColor.b * slotColor.b * attachmentColor.b * multiplier,
+								alpha)
 
 
 			if texture and vertices and indices then
 			if texture and vertices and indices then
 				if not lastTexture then lastTexture = texture end
 				if not lastTexture then lastTexture = texture end
@@ -174,80 +199,27 @@ function spine.Skeleton:updateWorldTransform()
 					groupUvs = {}
 					groupUvs = {}
 					groupIndices = {}
 					groupIndices = {}
 				end
 				end
+				
+				if self.clipper:isClipping() then
+					self.clipper:clipTriangles(vertices, uvs, indices, #indices)
+					vertices = self.clipper.clippedVertices
+					numVertices = #vertices / 2
+					uvs = self.clipper.clippedUVs
+					indices = self.clipper.clippedTriangles
+				end
 
 
-				self:batch(vertices, numVertices, indices, groupVertices, groupUvs, groupIndices)
+				self:batch(vertices, uvs, numVertices, indices, groupVertices, groupUvs, groupIndices)
 			end
 			end
+			
+			self.clipper:clipEnd(slot)
 		end
 		end
 	end
 	end
 
 
 	if #groupVertices > 0 then
 	if #groupVertices > 0 then
 		self:flush(groupVertices, groupUvs, groupIndices, texture, color, blendMode, drawingGroup)
 		self:flush(groupVertices, groupUvs, groupIndices, texture, color, blendMode, drawingGroup)
 	end
 	end
-end
-
-function spine.Skeleton:computeRegionVertices(slot, region, pma, color)
-	local skeleton = slot.bone.skeleton
-	local skeletonColor = skeleton.color
-	local slotColor = slot.color
-	local regionColor = region.color
-	local alpha = skeletonColor.a * slotColor.a * regionColor.a
-	local multiplier = alpha
-	if pma then multiplier = 1 end
-	color:set(skeletonColor.r * slotColor.r * regionColor.r * multiplier,
-				skeletonColor.g * slotColor.g * regionColor.g * multiplier,
-				skeletonColor.b * slotColor.b * regionColor.b * multiplier,
-				alpha)
-
-	local vertices = worldVertices
-	region:computeWorldVertices(slot.bone, vertices, 0, 4)
-
-	local uvs = region.uvs
-
-	vertices[3] = uvs[1]
-	vertices[4] = uvs[2]
-
-	vertices[7] = uvs[3]
-	vertices[8] = uvs[4]
-
-	vertices[11] = uvs[5]
-	vertices[12] = uvs[6]
-
-	vertices[15] = uvs[7]
-	vertices[16] = uvs[8]
-
-	return vertices
-end
-
-function spine.Skeleton:computeMeshVertices(slot, mesh, pma, color)
-	local skeleton = slot.bone.skeleton
-	local skeletonColor = skeleton.color
-	local slotColor = slot.color
-	local meshColor = mesh.color
-	local alpha = skeletonColor.a * slotColor.a * meshColor.a
-	local multiplier = alpha
-	if pma then multiplier = 1 end
-	color:set(skeletonColor.r * slotColor.r * meshColor.r * multiplier,
-				skeletonColor.g * slotColor.g * meshColor.g * multiplier,
-				skeletonColor.b * slotColor.b * meshColor.b * multiplier,
-				alpha)
-			
-	local numVertices = mesh.worldVerticesLength / 2
-	local vertices = worldVertices
-	mesh:computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, 4)
 	
 	
-	local uvs = mesh.uvs
-	local i = 1
-	local n = numVertices + 1
-	local u = 1
-	local v = 3
-	while i < n do
-		vertices[v] = uvs[u]
-		vertices[v + 1] = uvs[u + 1]
-		i = i + 1
-		u = u + 2
-		v = v + 4
-	end
-	return vertices
+	self.clipper:clipEnd2()
 end
 end
 
 
 function spine.Skeleton:flush(groupVertices, groupUvs, groupIndices, texture, color, blendMode, drawingGroup)
 function spine.Skeleton:flush(groupVertices, groupUvs, groupIndices, texture, color, blendMode, drawingGroup)
@@ -265,7 +237,7 @@ function spine.Skeleton:flush(groupVertices, groupUvs, groupIndices, texture, co
 	self.batches = self.batches + 1
 	self.batches = self.batches + 1
 end
 end
 
 
-function spine.Skeleton:batch(vertices, numVertices, indices, groupVertices, groupUvs, groupIndices)
+function spine.Skeleton:batch(vertices, uvs, numVertices, indices, groupVertices, groupUvs, groupIndices)
 	local numIndices = #indices
 	local numIndices = #indices
 	local i = 1
 	local i = 1
 	local indexStart = #groupIndices + 1
 	local indexStart = #groupIndices + 1
@@ -284,10 +256,10 @@ function spine.Skeleton:batch(vertices, numVertices, indices, groupVertices, gro
 	while vertexStart < vertexEnd do
 	while vertexStart < vertexEnd do
 		groupVertices[vertexStart] = vertices[i]
 		groupVertices[vertexStart] = vertices[i]
 		groupVertices[vertexStart+1] = vertices[i+1]
 		groupVertices[vertexStart+1] = vertices[i+1]
-		groupUvs[vertexStart] = vertices[i+2]
-		groupUvs[vertexStart+1] = vertices[i+3]
+		groupUvs[vertexStart] = uvs[i]
+		groupUvs[vertexStart+1] = uvs[i+1]
 		vertexStart = vertexStart + 2
 		vertexStart = vertexStart + 2
-		i = i + 4
+		i = i + 2
 	end
 	end
 end
 end
 
 

+ 4 - 0
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/Triangulator.java

@@ -289,5 +289,9 @@ class Triangulator {
 		
 		
 		Array<FloatArray> polys = triangulator.decompose(polygon,  triangles);
 		Array<FloatArray> polys = triangulator.decompose(polygon,  triangles);
 		System.out.println(polys);
 		System.out.println(polys);
+		
+		FloatArray poly2 = new FloatArray(new float[] {0, 0, 100, 0, 100, 100, 0, 100 });
+		SkeletonClipping.makeClockwise(poly2);
+		System.out.println(poly2);
 	}
 	}
 }
 }

+ 298 - 6
spine-lua/SkeletonClipping.lua

@@ -29,6 +29,7 @@
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 
 
 local utils = require "spine-lua.utils"
 local utils = require "spine-lua.utils"
+local Triangulator = require "spine-lua.Triangulator"
 
 
 local setmetatable = setmetatable
 local setmetatable = setmetatable
 local math_min = math.min
 local math_min = math.min
@@ -42,15 +43,306 @@ SkeletonClipping.__index = SkeletonClipping
 
 
 function SkeletonClipping.new ()
 function SkeletonClipping.new ()
 	local self = {
 	local self = {
-		convexPolygons = {},
-		convexPolygonsIndices = {},
-		indicesArray = {},
-		isConcaveArray = {},
-		triangles = {}
+		triangulator = Triangulator.new(),
+		clippingPolygon = {},
+		clipOutput = {},
+		clippedVertices = {},
+		clippedUVs = {},
+		clippedTriangles = {},		
+		clipAttachment = nil
 	}
 	}
 	setmetatable(self, SkeletonClipping)
 	setmetatable(self, SkeletonClipping)
 
 
 	return self
 	return self
 end
 end
 
 
-return Triangulator
+function SkeletonClipping:clipStart(slot, clip)
+	if self.clipAttachment then return 0 end
+	self.clipAttachment = clip
+	
+	local n = clip.worldVerticesLength
+	self.clippingPolygon = {}
+	local vertices = self.clippingPolygon
+	clip:computeWorldVertices(slot, 0, n, vertices, 0, 2)
+	self:makeClockwise(self.clippingPolygon)
+	self.clippingPolygons = self.triangulator:decompose(self.clippingPolygon, self.triangulator:triangulate(self.clippingPolygon))
+	for i,polygon in ipairs(self.clippingPolygons) do
+		self:makeClockwise(polygon)
+		table_insert(polygon, polygon[1])
+		table_insert(polygon, polygon[2])		
+	end
+	return #self.clippingPolygons
+end
+
+function SkeletonClipping:clipEnd(slot)
+	if self.clipAttachment and self.clipAttachment.endSlot == slot then self:clipEnd2() end
+end
+
+function SkeletonClipping:clipEnd2()
+	if self.clipAttachment == nil then return end
+	self.clipAttachment = nil
+	self.clippingPolygons = nil
+	self.clippedVertices = {}
+	self.clippedUVs = {}
+	self.clippedTriangles = {}
+	self.clippingPolygon = {}
+end
+
+function SkeletonClipping:isClipping()
+	return self.clipAttachment ~= nil
+end
+
+function SkeletonClipping:clipTriangles(vertices, uvs, triangles, trianglesLength)
+	self.clippedVertices = {}
+	self.clippedUVs = {}
+	self.clippedTriangles = {}
+	local clippedVertices = self.clippedVertices
+	local clippedUVs = self.clippedUVs
+	local clippedTriangles = self.clippedTriangles
+	local polygons = self.clippingPolygons
+	local polygonsCount = #self.clippingPolygons
+
+	local index = 1
+	
+	local i = 1
+	while i <= trianglesLength do
+		local vertexOffset = (triangles[i] - 1) * 2 + 1
+		local x1 = vertices[vertexOffset]
+		local y1 = vertices[vertexOffset + 1]
+		local u1 = uvs[vertexOffset]
+		local v1 = uvs[vertexOffset + 1]
+
+		vertexOffset = (triangles[i + 1] - 1) * 2 + 1
+		local x2 = vertices[vertexOffset]
+		local y2 = vertices[vertexOffset + 1]
+		local u2 = uvs[vertexOffset]
+		local v2 = uvs[vertexOffset + 1]
+
+		vertexOffset = (triangles[i + 2] - 1) * 2 + 1;
+		local x3 = vertices[vertexOffset]
+		local y3 = vertices[vertexOffset + 1]
+		local u3 = uvs[vertexOffset]
+		local v3 = uvs[vertexOffset + 1]
+
+		local p = 1
+		while p <= polygonsCount do
+			local s = #clippedVertices + 1
+			local clipOutput = {}
+			if (self:clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) then
+				local clipOutputLength = #clipOutput
+				if (clipOutputLength > 0) then
+					local d0 = y2 - y3
+					local d1 = x3 - x2
+					local d2 = x1 - x3
+					local d4 = y3 - y1
+					local d = 1 / (d0 * d2 + d1 * (y1 - y3));
+
+					local clipOutputCount = clipOutputLength / 2
+					local clipOutputItems = clipOutput
+					local clippedVerticesItems = clippedVertices
+					local clippedUVsItems = clippedUVs
+					local ii = 1
+					while ii <= clipOutputLength do
+						local x = clipOutputItems[ii]
+						local y = clipOutputItems[ii + 1]
+						clippedVerticesItems[s] = x
+						clippedVerticesItems[s + 1] = y						
+						local c0 = x - x3
+						local c1 = y - y3
+						local a = (d0 * c0 + d1 * c1) * d
+						local b = (d4 * c0 + d2 * c1) * d
+						local c = 1 - a - b
+						clippedUVsItems[s] = u1 * a + u2 * b + u3 * c
+						clippedUVsItems[s + 1] = v1 * a + v2 * b + v3 * c
+						s = s + 2
+						ii = ii + 2
+					end
+
+					s = #clippedTriangles + 1
+					local clippedTrianglesItems = clippedTriangles
+					clipOutputCount = clipOutputCount - 1
+					ii = 1
+					while ii < clipOutputCount do
+						clippedTrianglesItems[s] = index
+						clippedTrianglesItems[s + 1] = index + ii
+						clippedTrianglesItems[s + 2] = index + ii + 1
+						s = s + 3
+						ii = ii + 1
+					end
+					index = index + clipOutputCount + 1
+				end
+			else
+				local clippedVerticesItems = clippedVertices
+				local clippedUVsItems = clippedUVs
+				clippedVerticesItems[s] = x1
+				clippedVerticesItems[s + 1] = y1
+				clippedVerticesItems[s + 2] = x2
+				clippedVerticesItems[s + 3] = y2
+				clippedVerticesItems[s + 4] = x3
+				clippedVerticesItems[s + 5] = y3
+
+				clippedUVsItems[s] = u1
+				clippedUVsItems[s + 1] = v1
+				clippedUVsItems[s + 2] = u2
+				clippedUVsItems[s + 3] = v2
+				clippedUVsItems[s + 4] = u3
+				clippedUVsItems[s + 5] = v3					
+
+				s = #clippedTriangles + 1
+				local clippedTrianglesItems = clippedTriangles
+				clippedTrianglesItems[s] = index
+				clippedTrianglesItems[s + 1] = index + 1
+				clippedTrianglesItems[s + 2] = index + 2
+				index = index + 3;
+				break
+			end
+			p = p + 1
+		end
+		i = i + 3
+	end
+end
+
+function SkeletonClipping:clip(x1, y1, x2, y2, x3, y3, clippingArea, output)
+	local originalOutput = output
+	local clipped = false
+	local scratch = {}
+
+	-- Avoid copy at the end.
+	local input = nil
+	if #clippingArea % 4 >= 2 then
+		input = output
+		output = scratch
+	else
+		input = scratch
+	end
+
+	table_insert(input, x1)
+	table_insert(input, y1)
+	table_insert(input, x2)
+	table_insert(input, y2)
+	table_insert(input, x3)
+	table_insert(input, y3)
+	table_insert(input, x1)
+	table_insert(input, y1)
+
+	local clippingVertices = clippingArea
+	local clippingVerticesLast = #clippingArea - 4 + 1
+	local i = 1
+	while true do
+		local edgeX = clippingVertices[i]
+		local edgeY = clippingVertices[i + 1]
+		local edgeX2 = clippingVertices[i + 2]
+		local edgeY2 = clippingVertices[i + 3]
+		local deltaX = edgeX - edgeX2
+		local deltaY = edgeY - edgeY2
+
+		local inputVertices = input
+		local inputVerticesLength = #input - 2
+		local outputStart = #output
+		local ii = 1
+		while ii <= inputVerticesLength do
+			local inputX = inputVertices[ii]
+			local inputY = inputVertices[ii + 1]
+			local inputX2 = inputVertices[ii + 2]
+			local inputY2 = inputVertices[ii + 3]
+			local side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0
+			local continue = false;
+			if deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0 then
+				if side2 then -- v1 inside, v2 inside
+					table_insert(output, inputX2)
+					table_insert(output, inputY2)
+					continue = true
+				else
+					-- v1 inside, v2 outside
+					local c0 = inputY2 - inputY
+					local c2 = inputX2 - inputX
+					local ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY))
+					table_insert(output, edgeX + (edgeX2 - edgeX) * ua)
+					table_insert(output, edgeY + (edgeY2 - edgeY) * ua)
+				end
+			elseif side2 then -- v1 outside, v2 inside
+				local c0 = inputY2 - inputY
+				local c2 = inputX2 - inputX
+				local ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY))
+				table_insert(output, edgeX + (edgeX2 - edgeX) * ua)
+				table_insert(output, edgeY + (edgeY2 - edgeY) * ua)
+				table_insert(output, inputX2)
+				table_insert(output, inputY2)
+			end			
+			if not continue then clipped = true end
+			ii = ii + 2
+		end
+
+		if outputStart == #output then -- All edges outside.
+			for i, v in ipairs(originalOutput) do
+				originalOutput[i] = nil
+			end
+			return true
+		end
+
+		table_insert(output, output[1])
+		table_insert(output, output[2])
+
+		if (i == clippingVerticesLast) then break end
+		local temp = output
+		output = input
+		for i, v in ipairs(output) do
+			output[i] = nil
+		end
+		input = temp
+		i = i + 2
+	end
+
+	if originalOutput ~= output then
+		for i, v in ipairs(originalOutput) do
+			originalOutput[i] = nil
+		end
+		i = 1
+		local n = #output - 2
+		while i <= n do
+			originalOutput[i] = output[i]
+			i = i + 1
+		end
+	else
+		utils.setArraySize(originalOutput, #originalOutput - 2)
+	end
+
+	return clipped
+end
+
+function SkeletonClipping:makeClockwise(polygon)
+	local vertices = polygon
+	local verticesLength = #polygon
+	local area = vertices[verticesLength - 2 + 1] * vertices[1 + 1] - vertices[0 + 1] * vertices[verticesLength - 1 + 1]
+	local p1x
+	local p1y
+	local p2x
+	local p2y
+	local i = 1
+	local n = verticesLength - 3 + 1
+	while i <= n do
+		p1x = vertices[i]
+		p1y = vertices[i + 1]
+		p2x = vertices[i + 2]
+		p2y = vertices[i + 3]
+		area = area + p1x * p2y - p2x * p1y
+		i = i + 2
+	end
+	if (area < 0) then return end
+
+	i = 1
+	local lastX = verticesLength - 2 + 1
+	n = verticesLength / 2
+	while i <= n do
+		local x = vertices[i]
+		local y = vertices[i + 1]
+		local other = lastX - i + 1
+		vertices[i] = vertices[other]
+		vertices[i + 1] = vertices[other + 1]
+		vertices[other] = x
+		vertices[other + 1] = y
+		i = i + 2
+	end
+end
+
+return SkeletonClipping

+ 17 - 17
spine-lua/attachments/RegionAttachment.lua

@@ -187,6 +187,15 @@ end
 function RegionAttachment:setRegion (region)
 function RegionAttachment:setRegion (region)
 	local uvs = self.uvs
 	local uvs = self.uvs
 	if region.rotate then
 	if region.rotate then
+		uvs[5] = region.u
+		uvs[6] = region.v2
+		uvs[7] = region.u
+		uvs[8] = region.v
+		uvs[1] = region.u2
+		uvs[2] = region.v
+		uvs[3] = region.u2
+		uvs[4] = region.v2
+	else
 		uvs[3] = region.u
 		uvs[3] = region.u
 		uvs[4] = region.v2
 		uvs[4] = region.v2
 		uvs[5] = region.u
 		uvs[5] = region.u
@@ -195,15 +204,6 @@ function RegionAttachment:setRegion (region)
 		uvs[8] = region.v
 		uvs[8] = region.v
 		uvs[1] = region.u2
 		uvs[1] = region.u2
 		uvs[2] = region.v2
 		uvs[2] = region.v2
-	else
-		uvs[1] = region.u
-		uvs[2] = region.v2
-		uvs[3] = region.u
-		uvs[4] = region.v
-		uvs[5] = region.u2
-		uvs[6] = region.v
-		uvs[7] = region.u2
-		uvs[8] = region.v2
 	end
 	end
 end
 end
 
 
@@ -219,26 +219,26 @@ function RegionAttachment:computeWorldVertices (bone, worldVertices, offset, str
 	local offsetX = 0
 	local offsetX = 0
 	local offsetY = 0
 	local offsetY = 0
 
 
-	offsetX = vertexOffset[OX1]
-	offsetY = vertexOffset[OY1]
+	offsetX = vertexOffset[7]
+	offsetY = vertexOffset[8]
 	worldVertices[offset] = offsetX * a + offsetY * b + x -- br
 	worldVertices[offset] = offsetX * a + offsetY * b + x -- br
 	worldVertices[offset + 1] = offsetX * c + offsetY * d + y
 	worldVertices[offset + 1] = offsetX * c + offsetY * d + y
 	offset = offset + stride
 	offset = offset + stride
 
 
-	offsetX = vertexOffset[OX2]
-	offsetY = vertexOffset[OY2]
+	offsetX = vertexOffset[1]
+	offsetY = vertexOffset[2]
 	worldVertices[offset] = offsetX * a + offsetY * b + x -- bl
 	worldVertices[offset] = offsetX * a + offsetY * b + x -- bl
 	worldVertices[offset + 1] = offsetX * c + offsetY * d + y
 	worldVertices[offset + 1] = offsetX * c + offsetY * d + y
 	offset = offset + stride
 	offset = offset + stride
 
 
-	offsetX = vertexOffset[OX3]
-	offsetY = vertexOffset[OY3]
+	offsetX = vertexOffset[3]
+	offsetY = vertexOffset[4]
 	worldVertices[offset] = offsetX * a + offsetY * b + x -- ul
 	worldVertices[offset] = offsetX * a + offsetY * b + x -- ul
 	worldVertices[offset + 1] = offsetX * c + offsetY * d + y
 	worldVertices[offset + 1] = offsetX * c + offsetY * d + y
 	offset = offset + stride
 	offset = offset + stride
 
 
-	offsetX = vertexOffset[OX4]
-	offsetY = vertexOffset[OY4]
+	offsetX = vertexOffset[5]
+	offsetY = vertexOffset[6]
 	worldVertices[offset] = offsetX * a + offsetY * b + x -- ur
 	worldVertices[offset] = offsetX * a + offsetY * b + x -- ur
 	worldVertices[offset + 1] = offsetX * c + offsetY * d + y
 	worldVertices[offset + 1] = offsetX * c + offsetY * d + y
 end
 end

+ 6 - 1
spine-lua/utils.lua

@@ -108,7 +108,12 @@ function utils.setArraySize (array, size)
 			i = i + 1
 			i = i + 1
 		end
 		end
 	else
 	else
-		array[size + 1] = nil -- dirty trick to appease # without realloc
+		local originalSize = #array
+		local i = originalSize
+		while i > size do
+			array[i] = nil -- dirty trick to appease # without realloc
+			i = i - 1
+		end
 	end
 	end
 	return array
 	return array
 end
 end