static Mesh ExtractRegionAttachment (string name, RegionAttachment attachment, Mesh mesh = null) { var bone = GetExtractionBone(); bone.X = -attachment.X; bone.Y = -attachment.Y; bone.UpdateWorldTransform(); Vector2[] uvs = ExtractUV(attachment.UVs); float[] floatVerts = new float[8]; attachment.ComputeWorldVertices(bone, floatVerts); Vector3[] verts = ExtractVerts(floatVerts); //unrotate verts now that they're centered for (int i = 0; i < verts.Length; i++) { verts[i] = Quaternion.Euler(0, 0, -attachment.Rotation) * verts[i]; } int[] triangles = new int[6] { 1, 3, 0, 2, 3, 1 }; Color color = new Color(attachment.R, attachment.G, attachment.B, attachment.A); if (mesh == null) mesh = new Mesh(); mesh.triangles = new int[0]; mesh.vertices = verts; mesh.uv = uvs; mesh.triangles = triangles; mesh.colors = new Color[] { color, color, color, color }; mesh.RecalculateBounds(); mesh.RecalculateNormals(); mesh.name = name; return mesh; }
// RegionAttachment protected void AddAttachment(Slot slot, RegionAttachment attachment) { var tempVertices = this.tempVertices; attachment.ComputeWorldVertices(slot.bone, tempVertices); float[] regionUVs = attachment.uvs; Color color = skeletonColor; color.r = color.r * attachment.r * slot.r; color.g = color.g * attachment.g * slot.g; color.b = color.b * attachment.b * slot.b; color.a = color.a * attachment.a * slot.a; if (premultiplyAlpha) { color.r *= color.a; color.g *= color.a; color.b *= color.a; if (slot.data.blendMode == BlendMode.additive) { color.a = 0; } } int fv = positions.Count; // first vertex index AddVert(new Vector3(tempVertices[RegionAttachment.X1] * scale, tempVertices[RegionAttachment.Y1] * scale), color, new Vector2(regionUVs[RegionAttachment.X1], regionUVs[RegionAttachment.Y1])); AddVert(new Vector3(tempVertices[RegionAttachment.X4] * scale, tempVertices[RegionAttachment.Y4] * scale), color, new Vector2(regionUVs[RegionAttachment.X4], regionUVs[RegionAttachment.Y4])); AddVert(new Vector3(tempVertices[RegionAttachment.X2] * scale, tempVertices[RegionAttachment.Y2] * scale), color, new Vector2(regionUVs[RegionAttachment.X2], regionUVs[RegionAttachment.Y2])); AddVert(new Vector3(tempVertices[RegionAttachment.X3] * scale, tempVertices[RegionAttachment.Y3] * scale), color, new Vector2(regionUVs[RegionAttachment.X3], regionUVs[RegionAttachment.Y3])); AddTriangle(fv, fv + 2, fv + 1); AddTriangle(fv + 2, fv + 3, fv + 1); }
private List <Vector3> ComputeAttachmentVertices(Attachment attachment, Slot slot) { var result = new List <Vector3>(); if (attachment is RegionAttachment) { RegionAttachment regionAttachment = attachment as RegionAttachment; float[] spineVertices = new float[8]; regionAttachment.ComputeWorldVertices(slot.Bone, spineVertices); result.Add(new Vector3( spineVertices[RegionAttachment.X1], -spineVertices[RegionAttachment.Y1], 0)); result.Add(new Vector3( spineVertices[RegionAttachment.X4], -spineVertices[RegionAttachment.Y4], 0)); result.Add(new Vector3( spineVertices[RegionAttachment.X3], -spineVertices[RegionAttachment.Y3], 0)); result.Add(new Vector3( spineVertices[RegionAttachment.X2], -spineVertices[RegionAttachment.Y2], 0)); } else if (attachment is MeshAttachment || attachment is WeightedMeshAttachment) { float[] spineVertices; if (attachment is MeshAttachment) { var mesh = attachment as MeshAttachment; var numVertices = mesh.Vertices.Length; spineVertices = new float[numVertices]; mesh.ComputeWorldVertices(slot, spineVertices); } else { var mesh = attachment as WeightedMeshAttachment; var numVertices = mesh.UVs.Length; spineVertices = new float[numVertices]; mesh.ComputeWorldVertices(slot, spineVertices); } for (int v = 0; v < spineVertices.Length; v += 2) { result.Add(new Vector3( spineVertices[v], -spineVertices[v + 1], 0)); } } return(result); }
//virtual cocos2d::CCTextureAtlas* getTextureAtlas (RegionAttachment regionAttachment); #region SpinesCocos2d void UpdateRegionAttachmentQuad(RegionAttachment self, Slot slot, ref CCV3F_C4B_T2F_Quad quad, bool premultipliedAlpha = false) { float[] vertices = new float[8]; self.ComputeWorldVertices(slot.Skeleton.X, slot.Skeleton.Y, slot.Bone, vertices); float r = slot.Skeleton.R * slot.R * 255; float g = slot.Skeleton.G * slot.G * 255; float b = slot.Skeleton.B * slot.B * 255; float normalizedAlpha = slot.Skeleton.A * slot.A; if (premultipliedAlpha) { r *= normalizedAlpha; g *= normalizedAlpha; b *= normalizedAlpha; } float a = normalizedAlpha * 255; quad.BottomLeft.Colors.R = (byte)r; quad.BottomLeft.Colors.G = (byte)g; quad.BottomLeft.Colors.B = (byte)b; quad.BottomLeft.Colors.A = (byte)a; quad.TopLeft.Colors.R = (byte)r; quad.TopLeft.Colors.G = (byte)g; quad.TopLeft.Colors.B = (byte)b; quad.TopLeft.Colors.A = (byte)a; quad.TopRight.Colors.R = (byte)r; quad.TopRight.Colors.G = (byte)g; quad.TopRight.Colors.B = (byte)b; quad.TopRight.Colors.A = (byte)a; quad.BottomRight.Colors.R = (byte)r; quad.BottomRight.Colors.G = (byte)g; quad.BottomRight.Colors.B = (byte)b; quad.BottomRight.Colors.A = (byte)a; quad.BottomLeft.Vertices.X = vertices[RegionAttachment.X1]; quad.BottomLeft.Vertices.Y = vertices[RegionAttachment.Y1]; quad.TopLeft.Vertices.X = vertices[RegionAttachment.X2]; quad.TopLeft.Vertices.Y = vertices[RegionAttachment.Y2]; quad.TopRight.Vertices.X = vertices[RegionAttachment.X3]; quad.TopRight.Vertices.Y = vertices[RegionAttachment.Y3]; quad.BottomRight.Vertices.X = vertices[RegionAttachment.X4]; quad.BottomRight.Vertices.Y = vertices[RegionAttachment.Y4]; quad.BottomLeft.TexCoords.U = self.UVs[RegionAttachment.X1]; quad.BottomLeft.TexCoords.V = self.UVs[RegionAttachment.Y1]; quad.TopLeft.TexCoords.U = self.UVs[RegionAttachment.X2]; quad.TopLeft.TexCoords.V = self.UVs[RegionAttachment.Y2]; quad.TopRight.TexCoords.U = self.UVs[RegionAttachment.X3]; quad.TopRight.TexCoords.V = self.UVs[RegionAttachment.Y3]; quad.BottomRight.TexCoords.U = self.UVs[RegionAttachment.X4]; quad.BottomRight.TexCoords.V = self.UVs[RegionAttachment.Y4]; }
// update the attachment with the current slot data public void Update(Slot slot) { _attachment = slot.Attachment as RegionAttachment; //_attachment.UpdateOffset(); //_attachment.UpdateVertices(slot.Bone); _attachment.ComputeWorldVertices(slot.Bone, vertices); element = _attachment.RendererObject as FAtlasElement; element = null; base.color = _slotCustomColor * new Color(slot.R, slot.G, slot.B, slot.A); UpdateLocalVertices(); }
private void DrawSlot(Skeleton skeleton, RegionAttachment attachment, Slot slot) { var region = (AtlasRegion)attachment.RendererObject; var thisMaterial = (Material)region.page.rendererObject; var thisBlendMode = slot.Data.AdditiveBlending ? BlendMode.Additive : BlendMode.Normal; var thisBatch = (Batch2D)renderer.FindOrCreateBatch(thisMaterial, thisBlendMode); if (currentBatch != null && currentBatch != thisBatch) { renderer.FlushDrawBuffer(currentBatch); } currentBatch = thisBatch; attachment.ComputeWorldVertices(skeleton.X, skeleton.Y, slot.Bone, vertices); currentColor = new Color(color.RedValue * slot.R, color.GreenValue * slot.G, color.BlueValue * slot.B, color.AlphaValue * slot.A); AddSlotIndicesAndVertices(attachment.UVs); }
private void UpdateBounds(ref ModelBound bound, Skeleton skeleton) { float[] vertices = new float[8]; var drawOrder = skeleton.DrawOrder; for (int i = 0, n = drawOrder.Count; i < n; i++) { Slot slot = drawOrder.Items[i]; Attachment attachment = slot.Attachment; if (attachment is RegionAttachment) { RegionAttachment region = (RegionAttachment)attachment; region.ComputeWorldVertices(slot.Bone, vertices); bound.Update(vertices, 8); } else if (attachment is MeshAttachment) { MeshAttachment mesh = (MeshAttachment)attachment; int vertexCount = mesh.Vertices.Length; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; } mesh.ComputeWorldVertices(slot, vertices); bound.Update(vertices, vertexCount); } else if (attachment is SkinnedMeshAttachment) { SkinnedMeshAttachment mesh = (SkinnedMeshAttachment)attachment; int vertexCount = mesh.UVs.Length; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; } mesh.ComputeWorldVertices(slot, vertices); bound.Update(vertices, vertexCount); } } }
/// <summary> /// Allows to perform custom drawing. /// </summary> /// <param name="gameTime">The elapsed game time.</param> public override void Draw(TimeSpan gameTime) { this.position.X = this.Transform2D.X; this.position.Y = this.Transform2D.Y; this.scale.X = this.Transform2D.XScale; this.scale.Y = this.Transform2D.YScale; if (this.viewportManager.IsActivated) { this.viewportManager.Translate(ref this.position, ref this.scale); } Quaternion.CreateFromYawPitchRoll(0, 0, this.Transform2D.Rotation, out this.orientation); Matrix.CreateFromQuaternion(ref this.orientation, out this.quaternionMatrix); this.internalScale.X = this.scale.X; this.internalScale.Y = this.scale.Y; Matrix.CreateScale(ref this.internalScale, out this.scaleMatrix); this.internalPosition.X = this.position.X - (this.Transform2D.Origin.X * this.Transform2D.Rectangle.Width); this.internalPosition.Y = this.position.Y - (this.Transform2D.Origin.Y * this.Transform2D.Rectangle.Height); Matrix.CreateTranslation(ref this.internalPosition, out this.translationMatrix); Matrix.Multiply(ref this.scaleMatrix, ref this.quaternionMatrix, out this.localWorld); Matrix.Multiply(ref this.localWorld, ref this.translationMatrix, out this.localWorld); float opacity = this.RenderManager.DebugLines ? this.DebugAlpha : this.Transform2D.Opacity; int numVertices = 0; int numPrimitives = 0; // Process Mesh for (int i = 0; i < this.drawOrder.Count; i++) { Slot slot = this.drawOrder[i]; Attachment attachment = slot.Attachment; float alpha = this.SkeletalAnimation.Skeleton.A * slot.A * opacity; byte r = (byte)(this.SkeletalAnimation.Skeleton.R * slot.R * 255 * alpha); byte g = (byte)(this.SkeletalAnimation.Skeleton.G * slot.G * 255 * alpha); byte b = (byte)(this.SkeletalAnimation.Skeleton.B * slot.B * 255 * alpha); byte a = (byte)(alpha * 255); Color color = new Color(r, g, b, a); if (attachment is RegionAttachment) { RegionAttachment regionAttachment = attachment as RegionAttachment; float[] spineVertices = new float[8]; float[] uvs = regionAttachment.UVs; AtlasRegion region = (AtlasRegion)regionAttachment.RendererObject; this.material.Texture = (Texture2D)region.page.rendererObject; regionAttachment.ComputeWorldVertices(0, 0, slot.Bone, spineVertices); this.vertices = new VertexPositionColorTexture[4]; // Vertex TL this.tempVertice.Position.X = spineVertices[RegionAttachment.X1]; this.tempVertice.Position.Y = -spineVertices[RegionAttachment.Y1]; this.tempVertice.Position.Z = 0; this.tempVertice.Color = color; this.tempVertice.TexCoord.X = uvs[RegionAttachment.X1]; this.tempVertice.TexCoord.Y = uvs[RegionAttachment.Y1]; this.vertices[0] = this.tempVertice; // Vertex TR this.tempVertice.Position.X = spineVertices[RegionAttachment.X4]; this.tempVertice.Position.Y = -spineVertices[RegionAttachment.Y4]; this.tempVertice.Position.Z = 0; this.tempVertice.Color = color; this.tempVertice.TexCoord.X = uvs[RegionAttachment.X4]; this.tempVertice.TexCoord.Y = uvs[RegionAttachment.Y4]; this.vertices[1] = this.tempVertice; // Vertex BR this.tempVertice.Position.X = spineVertices[RegionAttachment.X3]; this.tempVertice.Position.Y = -spineVertices[RegionAttachment.Y3]; this.tempVertice.Position.Z = 0; this.tempVertice.Color = color; this.tempVertice.TexCoord.X = uvs[RegionAttachment.X3]; this.tempVertice.TexCoord.Y = uvs[RegionAttachment.Y3]; this.vertices[2] = this.tempVertice; // Vertex BL this.tempVertice.Position.X = spineVertices[RegionAttachment.X2]; this.tempVertice.Position.Y = -spineVertices[RegionAttachment.Y2]; this.tempVertice.Position.Z = 0; this.tempVertice.Color = color; this.tempVertice.TexCoord.X = uvs[RegionAttachment.X2]; this.tempVertice.TexCoord.Y = uvs[RegionAttachment.Y2]; this.vertices[3] = this.tempVertice; numVertices = 4; numPrimitives = 2; this.indices = quadIndices; } else if (attachment is MeshAttachment) { MeshAttachment mesh = (MeshAttachment)attachment; numVertices = mesh.Vertices.Length; numPrimitives = numVertices / 2; indices = CopyIndices(mesh.Triangles); float[] spineVertices = new float[numVertices]; mesh.ComputeWorldVertices(0, 0, slot, spineVertices); AtlasRegion region = (AtlasRegion)mesh.RendererObject; this.material.Texture = (Texture2D)region.page.rendererObject; this.vertices = new VertexPositionColorTexture[numVertices / 2]; float[] uvs = mesh.UVs; for (int v = 0, j = 0; v < numVertices; v += 2, j++) { this.tempVertice.Color = color; this.tempVertice.Position.X = spineVertices[v]; this.tempVertice.Position.Y = -spineVertices[v + 1]; this.tempVertice.Position.Z = 0; this.tempVertice.TexCoord.X = uvs[v]; this.tempVertice.TexCoord.Y = uvs[v + 1]; this.vertices[j] = this.tempVertice; } } else if (attachment is SkinnedMeshAttachment) { SkinnedMeshAttachment mesh = (SkinnedMeshAttachment)attachment; numVertices = mesh.UVs.Length; numPrimitives = numVertices / 2; indices = CopyIndices(mesh.Triangles); float[] spineVertices = new float[numVertices]; mesh.ComputeWorldVertices(0, 0, slot, spineVertices); AtlasRegion region = (AtlasRegion)mesh.RendererObject; this.material.Texture = (Texture2D)region.page.rendererObject; this.vertices = new VertexPositionColorTexture[numVertices / 2]; float[] uvs = mesh.UVs; for (int v = 0, j = 0; v < numVertices; v += 2, j++) { this.tempVertice.Color = color; this.tempVertice.Position.X = spineVertices[v]; this.tempVertice.Position.Y = -spineVertices[v + 1]; this.tempVertice.Position.Z = 0; this.tempVertice.TexCoord.X = uvs[v]; this.tempVertice.TexCoord.Y = uvs[v + 1]; this.vertices[j] = this.tempVertice; } } if (attachment != null) { bool reset = false; if (this.spineMeshes[i] != null) { if (this.spineMeshes[i].VertexBuffer.VertexCount != vertices.Length || this.spineMeshes[i].IndexBuffer.Data.Length != indices.Length) { Mesh toDispose = this.spineMeshes[i]; this.GraphicsDevice.DestroyIndexBuffer(toDispose.IndexBuffer); this.GraphicsDevice.DestroyVertexBuffer(toDispose.VertexBuffer); reset = true; } } if (this.spineMeshes[i] == null || reset) { Mesh newMesh = new Mesh( 0, numVertices, 0, numPrimitives, new DynamicVertexBuffer(VertexPositionColorTexture.VertexFormat), new DynamicIndexBuffer(indices), PrimitiveType.TriangleList); this.spineMeshes[i] = newMesh; } Mesh mesh = this.spineMeshes[i]; mesh.IndexBuffer.SetData(this.indices); this.GraphicsDevice.BindIndexBuffer(mesh.IndexBuffer); mesh.VertexBuffer.SetData(this.vertices); this.GraphicsDevice.BindVertexBuffer(mesh.VertexBuffer); mesh.ZOrder = this.Transform2D.DrawOrder; this.RenderManager.DrawMesh(mesh, this.material, ref this.localWorld, false); } } }
public void UpdateSkeletonGeometry() { skeletonGeometry.ClearInstances(); BlendState blend; var drawOrder = Skeleton.DrawOrder; var drawOrderItems = Skeleton.DrawOrder.Items; float skeletonR = Skeleton.R, skeletonG = Skeleton.G, skeletonB = Skeleton.B, skeletonA = Skeleton.A; Color color; for (int i = 0, n = drawOrder.Count; i < n; i++) { Slot slot = drawOrderItems[i]; Attachment attachment = slot.Attachment; blend = slot.Data.BlendMode == BlendMode.Additive ? BlendState.Additive : PremultipliedAlpha ? BlendState.AlphaBlend : BlendState.NonPremultiplied; float attachmentColorR, attachmentColorG, attachmentColorB, attachmentColorA; CCTexture2D texture = null; int verticesCount = 0; //float[] vertices = this.vertices; int indicesCount = 0; int[] indices = null; float[] uvs = null; if (attachment is RegionAttachment) { RegionAttachment regionAttachment = (RegionAttachment)attachment; attachmentColorR = regionAttachment.R; attachmentColorG = regionAttachment.G; attachmentColorB = regionAttachment.B; attachmentColorA = regionAttachment.A; AtlasRegion region = (AtlasRegion)regionAttachment.RendererObject; texture = (CCTexture2D)region.page.rendererObject; verticesCount = 4; regionAttachment.ComputeWorldVertices(slot.Bone, vertices, 0, 2); indicesCount = 6; indices = quadTriangles; uvs = regionAttachment.UVs; } else if (attachment is MeshAttachment) { MeshAttachment mesh = (MeshAttachment)attachment; attachmentColorR = mesh.R; attachmentColorG = mesh.G; attachmentColorB = mesh.B; attachmentColorA = mesh.A; AtlasRegion region = (AtlasRegion)mesh.RendererObject; texture = (CCTexture2D)region.page.rendererObject; int vertexCount = mesh.WorldVerticesLength; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; } verticesCount = vertexCount >> 1; mesh.ComputeWorldVertices(slot, vertices); indicesCount = mesh.Triangles.Length; indices = mesh.Triangles; uvs = mesh.UVs; } else if (attachment is ClippingAttachment) { ClippingAttachment clip = (ClippingAttachment)attachment; clipper.ClipStart(slot, clip); continue; } else { continue; } // calculate color float a = skeletonA * slot.A * attachmentColorA; if (PremultipliedAlpha) { color = new Color( skeletonR * slot.R * attachmentColorR * a, skeletonG * slot.G * attachmentColorG * a, skeletonB * slot.B * attachmentColorB * a, a); } else { color = new Color( skeletonR * slot.R * attachmentColorR, skeletonG * slot.G * attachmentColorG, skeletonB * slot.B * attachmentColorB, a); } //Color darkColor = new Color(); //if (slot.HasSecondColor) //{ // darkColor = new Color(slot.R2 * a, slot.G2 * a, slot.B2 * a); //} //darkColor.A = PremultipliedAlpha ? (byte)255 : (byte)0; // clip if (clipper.IsClipping) { clipper.ClipTriangles(vertices, verticesCount << 1, indices, indicesCount, uvs); vertices = clipper.ClippedVertices.Items; verticesCount = clipper.ClippedVertices.Count >> 1; indices = clipper.ClippedTriangles.Items; indicesCount = clipper.ClippedTriangles.Count; uvs = clipper.ClippedUVs.Items; } if (verticesCount == 0 || indicesCount == 0) { continue; } // submit to batch var item = skeletonGeometry.CreateGeometryInstance(verticesCount, indicesCount); item.InstanceAttributes.BlendState = blend; item.GeometryPacket.Texture = texture; for (int ii = 0, nn = indicesCount; ii < nn; ii++) { item.GeometryPacket.Indicies[ii] = indices[ii]; } var itemVertices = item.GeometryPacket.Vertices; for (int ii = 0, v = 0, nn = verticesCount << 1; v < nn; ii++, v += 2) { itemVertices[ii].Colors = new CCColor4B(color.R, color.G, color.B, color.A); //itemVertices[ii].Colors2 = new CCColor4B(darkColor.R, darkColor.G, darkColor.B, darkColor.A); itemVertices[ii].Vertices.X = vertices[v]; itemVertices[ii].Vertices.Y = vertices[v + 1]; itemVertices[ii].Vertices.Z = 0; itemVertices[ii].TexCoords.U = uvs[v]; itemVertices[ii].TexCoords.V = uvs[v + 1]; } clipper.ClipEnd(slot); } clipper.ClipEnd(); }
public virtual void Update() { if (skeletonDataAsset == null) { Clear(); return; } SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(false); if (skeletonData == null) { Clear(); return; } // Initialize fields. if (skeleton == null || skeleton.Data != skeletonData) { Initialize(); } UpdateSkeleton(Time.deltaTime); // Count quads and submeshes. int quadCount = 0, submeshQuadCount = 0; Material lastMaterial = null; submeshMaterials.Clear(); List <Slot> drawOrder = skeleton.DrawOrder; for (int i = 0, n = drawOrder.Count; i < n; i++) { RegionAttachment regionAttachment = drawOrder[i].Attachment as RegionAttachment; if (regionAttachment == null) { continue; } // Add submesh when material changes. Material material = (Material)regionAttachment.RendererObject; if (lastMaterial != material && lastMaterial != null) { addSubmesh(lastMaterial, quadCount, submeshQuadCount, false); submeshQuadCount = 0; } lastMaterial = material; quadCount++; submeshQuadCount++; } addSubmesh(lastMaterial, quadCount, submeshQuadCount, true); // Set materials. if (submeshMaterials.Count == sharedMaterials.Length) { submeshMaterials.CopyTo(sharedMaterials); } else { sharedMaterials = submeshMaterials.ToArray(); } renderer.sharedMaterials = sharedMaterials; // Double buffer mesh. Mesh mesh = useMesh1 ? mesh1 : mesh2; meshFilter.sharedMesh = mesh; // Ensure mesh data is the right size. Vector3[] vertices = this.vertices; int vertexCount = quadCount * 4; bool newTriangles = vertexCount > vertices.Length; if (newTriangles) { // Not enough vertices, increase size. this.vertices = vertices = new Vector3[vertexCount]; this.colors = new Color32[vertexCount]; this.uvs = new Vector2[vertexCount]; mesh1.Clear(); mesh2.Clear(); } else { // Too many vertices, zero the extra. Vector3 zero = Vector3.zero; for (int i = vertexCount, n = lastVertexCount; i < n; i++) { vertices[i] = zero; } } lastVertexCount = vertexCount; // Setup mesh. float[] vertexPositions = this.vertexPositions; Vector2[] uvs = this.uvs; Color32[] colors = this.colors; int vertexIndex = 0; Color32 color = new Color32(); float a = skeleton.A * 255, r = skeleton.R, g = skeleton.G, b = skeleton.B, zSpacing = this.zSpacing; for (int i = 0, n = drawOrder.Count; i < n; i++) { Slot slot = drawOrder[i]; RegionAttachment regionAttachment = slot.Attachment as RegionAttachment; if (regionAttachment == null) { continue; } regionAttachment.ComputeWorldVertices(skeleton.X, skeleton.Y, slot.Bone, vertexPositions); float z = i * zSpacing; vertices[vertexIndex] = new Vector3(vertexPositions[RegionAttachment.X1], vertexPositions[RegionAttachment.Y1], z); vertices[vertexIndex + 1] = new Vector3(vertexPositions[RegionAttachment.X4], vertexPositions[RegionAttachment.Y4], z); vertices[vertexIndex + 2] = new Vector3(vertexPositions[RegionAttachment.X2], vertexPositions[RegionAttachment.Y2], z); vertices[vertexIndex + 3] = new Vector3(vertexPositions[RegionAttachment.X3], vertexPositions[RegionAttachment.Y3], z); color.a = (byte)(a * slot.A); color.r = (byte)(r * slot.R * color.a); color.g = (byte)(g * slot.G * color.a); color.b = (byte)(b * slot.B * color.a); if (slot.Data.AdditiveBlending) { color.a = 0; } colors[vertexIndex] = color; colors[vertexIndex + 1] = color; colors[vertexIndex + 2] = color; colors[vertexIndex + 3] = color; float[] regionUVs = regionAttachment.UVs; uvs[vertexIndex] = new Vector2(regionUVs[RegionAttachment.X1], regionUVs[RegionAttachment.Y1]); uvs[vertexIndex + 1] = new Vector2(regionUVs[RegionAttachment.X4], regionUVs[RegionAttachment.Y4]); uvs[vertexIndex + 2] = new Vector2(regionUVs[RegionAttachment.X2], regionUVs[RegionAttachment.Y2]); uvs[vertexIndex + 3] = new Vector2(regionUVs[RegionAttachment.X3], regionUVs[RegionAttachment.Y3]); vertexIndex += 4; } mesh.vertices = vertices; mesh.colors32 = colors; mesh.uv = uvs; int submeshCount = submeshMaterials.Count; mesh.subMeshCount = submeshCount; for (int i = 0; i < submeshCount; ++i) { mesh.SetTriangles(submeshes[i].indexes, i); } mesh.RecalculateBounds(); if (newTriangles && calculateNormals) { Vector3[] normals = new Vector3[vertexCount]; Vector3 normal = new Vector3(0, 0, -1); for (int i = 0; i < vertexCount; i++) { normals[i] = normal; } (useMesh1 ? mesh2 : mesh1).vertices = vertices; // Set other mesh vertices. mesh1.normals = normals; mesh2.normals = normals; if (calculateTangents) { Vector4[] tangents = new Vector4[vertexCount]; Vector3 tangent = new Vector3(0, 0, 1); for (int i = 0; i < vertexCount; i++) { tangents[i] = tangent; } mesh1.tangents = tangents; mesh2.tangents = tangents; } } useMesh1 = !useMesh1; }
public static void FillVerts(Skeleton skeleton, int startSlot, int endSlot, float zSpacing, bool pmaColors, Vector3[] verts, Vector2[] uvs, Color32[] colors, ref int vertexIndex, ref float[] tempVertBuffer, ref Vector3 boundsMin, ref Vector3 boundsMax, bool renderMeshes = true) { Color32 color = new Color32(0, 0, 0, 0); Slot[] items = skeleton.DrawOrder.Items; float num = skeleton.a * 255f; float r = skeleton.r; float g = skeleton.g; float b = skeleton.b; int num2 = vertexIndex; float[] array = tempVertBuffer; Vector3 vector = boundsMin; Vector3 vector2 = boundsMax; for (int i = startSlot; i < endSlot; i++) { Slot slot = items[i]; Attachment attachment = slot.attachment; float z = (float)i * zSpacing; RegionAttachment regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { regionAttachment.ComputeWorldVertices(slot.bone, array); float num3 = array[0]; float num4 = array[1]; float num5 = array[2]; float num6 = array[3]; float num7 = array[4]; float num8 = array[5]; float num9 = array[6]; float num10 = array[7]; verts[num2].x = num3; verts[num2].y = num4; verts[num2].z = z; verts[num2 + 1].x = num9; verts[num2 + 1].y = num10; verts[num2 + 1].z = z; verts[num2 + 2].x = num5; verts[num2 + 2].y = num6; verts[num2 + 2].z = z; verts[num2 + 3].x = num7; verts[num2 + 3].y = num8; verts[num2 + 3].z = z; if (pmaColors) { color.a = (byte)(num * slot.a * regionAttachment.a); color.r = (byte)(r * slot.r * regionAttachment.r * (float)color.a); color.g = (byte)(g * slot.g * regionAttachment.g * (float)color.a); color.b = (byte)(b * slot.b * regionAttachment.b * (float)color.a); if (slot.data.blendMode == BlendMode.additive) { color.a = 0; } } else { color.a = (byte)(num * slot.a * regionAttachment.a); color.r = (byte)(r * slot.r * regionAttachment.r * 255f); color.g = (byte)(g * slot.g * regionAttachment.g * 255f); color.b = (byte)(b * slot.b * regionAttachment.b * 255f); } colors[num2] = color; colors[num2 + 1] = color; colors[num2 + 2] = color; colors[num2 + 3] = color; float[] uvs2 = regionAttachment.uvs; uvs[num2].x = uvs2[0]; uvs[num2].y = uvs2[1]; uvs[num2 + 1].x = uvs2[6]; uvs[num2 + 1].y = uvs2[7]; uvs[num2 + 2].x = uvs2[2]; uvs[num2 + 2].y = uvs2[3]; uvs[num2 + 3].x = uvs2[4]; uvs[num2 + 3].y = uvs2[5]; if (num3 < vector.x) { vector.x = num3; } else if (num3 > vector2.x) { vector2.x = num3; } if (num5 < vector.x) { vector.x = num5; } else if (num5 > vector2.x) { vector2.x = num5; } if (num7 < vector.x) { vector.x = num7; } else if (num7 > vector2.x) { vector2.x = num7; } if (num9 < vector.x) { vector.x = num9; } else if (num9 > vector2.x) { vector2.x = num9; } if (num4 < vector.y) { vector.y = num4; } else if (num4 > vector2.y) { vector2.y = num4; } if (num6 < vector.y) { vector.y = num6; } else if (num6 > vector2.y) { vector2.y = num6; } if (num8 < vector.y) { vector.y = num8; } else if (num8 > vector2.y) { vector2.y = num8; } if (num10 < vector.y) { vector.y = num10; } else if (num10 > vector2.y) { vector2.y = num10; } num2 += 4; } else if (renderMeshes) { MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { int worldVerticesLength = meshAttachment.worldVerticesLength; if (array.Length < worldVerticesLength) { array = new float[worldVerticesLength]; } meshAttachment.ComputeWorldVertices(slot, array); if (pmaColors) { color.a = (byte)(num * slot.a * meshAttachment.a); color.r = (byte)(r * slot.r * meshAttachment.r * (float)color.a); color.g = (byte)(g * slot.g * meshAttachment.g * (float)color.a); color.b = (byte)(b * slot.b * meshAttachment.b * (float)color.a); if (slot.data.blendMode == BlendMode.additive) { color.a = 0; } } else { color.a = (byte)(num * slot.a * meshAttachment.a); color.r = (byte)(r * slot.r * meshAttachment.r * 255f); color.g = (byte)(g * slot.g * meshAttachment.g * 255f); color.b = (byte)(b * slot.b * meshAttachment.b * 255f); } float[] uvs3 = meshAttachment.uvs; for (int j = 0; j < worldVerticesLength; j += 2) { float num11 = array[j]; float num12 = array[j + 1]; verts[num2].x = num11; verts[num2].y = num12; verts[num2].z = z; colors[num2] = color; uvs[num2].x = uvs3[j]; uvs[num2].y = uvs3[j + 1]; if (num11 < vector.x) { vector.x = num11; } else if (num11 > vector2.x) { vector2.x = num11; } if (num12 < vector.y) { vector.y = num12; } else if (num12 > vector2.y) { vector2.y = num12; } num2++; } } } } vertexIndex = num2; tempVertBuffer = array; boundsMin = vector; boundsMax = vector2; }
public virtual void LateUpdate() { if (!valid) { return; } if (cpuOptimizationLevel != 0) { skipFramesLateUpdate--; if (skipFramesLateUpdate > 0) { return; } skipFramesLateUpdate = cpuOptimizationLevel + UnityEngine.Random.Range(0, cpuOptimizationLevel); } if ( ( !meshRenderer.enabled ) #if SPINE_OPTIONAL_RENDEROVERRIDE && this.generateMeshOverride == null #endif #if SPINE_OPTIONAL_SUBMESHRENDERER && submeshRenderers.Length > 0 #endif ) { return; } // STEP 1. Determine a SmartMesh.Instruction. Split up instructions into submeshes. // This method caches several .Items arrays. // Never mutate their overlying ExposedList objects. ExposedList <Slot> drawOrder = skeleton.drawOrder; var drawOrderItems = drawOrder.Items; int drawOrderCount = drawOrder.Count; int separatorSlotCount = separatorSlots.Count; bool renderMeshes = this.renderMeshes; // Clear last state of attachments and submeshes var workingInstruction = this.currentInstructions; var workingAttachments = workingInstruction.attachments; workingAttachments.Clear(false); workingAttachments.GrowIfNeeded(drawOrderCount); workingAttachments.Count = drawOrderCount; var workingAttachmentsItems = workingInstruction.attachments.Items; #if SPINE_OPTIONAL_FRONTFACING var workingFlips = workingInstruction.attachmentFlips; workingFlips.Clear(false); workingFlips.GrowIfNeeded(drawOrderCount); workingFlips.Count = drawOrderCount; var workingFlipsItems = workingFlips.Items; #endif var workingSubmeshInstructions = workingInstruction.submeshInstructions; // Items array should not be cached. There is dynamic writing to this list. workingSubmeshInstructions.Clear(false); #if !SPINE_TK2D bool isCustomSlotMaterialsPopulated = customSlotMaterials.Count > 0; #endif int vertexCount = 0; int submeshVertexCount = 0; int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0; Material lastMaterial = null; for (int i = 0; i < drawOrderCount; i++) { Slot slot = drawOrderItems[i]; Attachment attachment = slot.attachment; workingAttachmentsItems[i] = attachment; #if SPINE_OPTIONAL_FRONTFACING bool flip = frontFacing && (slot.bone.WorldSignX != slot.bone.WorldSignY); workingFlipsItems[i] = flip; #endif object rendererObject; // An AtlasRegion in plain Spine-Unity. Spine-TK2D hooks into TK2D's system. eventual source of Material object. int attachmentVertexCount, attachmentTriangleCount; var regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { rendererObject = regionAttachment.RendererObject; attachmentVertexCount = 4; attachmentTriangleCount = 6; } else { if (!renderMeshes) { continue; } var meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { rendererObject = meshAttachment.RendererObject; attachmentVertexCount = meshAttachment.worldVerticesLength >> 1; attachmentTriangleCount = meshAttachment.triangles.Length; } else { continue; } } #if !SPINE_TK2D // Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject; // For no customSlotMaterials Material material; if (isCustomSlotMaterialsPopulated) { if (!customSlotMaterials.TryGetValue(slot, out material)) { material = (Material)((AtlasRegion)rendererObject).page.rendererObject; } } else { material = (Material)((AtlasRegion)rendererObject).page.rendererObject; } #else Material material = (rendererObject.GetType() == typeof(Material)) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject; #endif // Create a new SubmeshInstruction when material changes. (or when forced to separate by a submeshSeparator) bool forceSeparate = (separatorSlotCount > 0 && separatorSlots.Contains(slot)); if ((vertexCount > 0 && lastMaterial.GetInstanceID() != material.GetInstanceID()) || forceSeparate) { workingSubmeshInstructions.Add( new Spine.Unity.MeshGeneration.SubmeshInstruction { skeleton = this.skeleton, material = lastMaterial, startSlot = submeshStartSlotIndex, endSlot = i, triangleCount = submeshTriangleCount, firstVertexIndex = submeshFirstVertex, vertexCount = submeshVertexCount, forceSeparate = forceSeparate } ); submeshTriangleCount = 0; submeshVertexCount = 0; submeshFirstVertex = vertexCount; submeshStartSlotIndex = i; } lastMaterial = material; submeshTriangleCount += attachmentTriangleCount; vertexCount += attachmentVertexCount; submeshVertexCount += attachmentVertexCount; } if (submeshVertexCount != 0) { workingSubmeshInstructions.Add( new Spine.Unity.MeshGeneration.SubmeshInstruction { skeleton = this.skeleton, material = lastMaterial, startSlot = submeshStartSlotIndex, endSlot = drawOrderCount, triangleCount = submeshTriangleCount, firstVertexIndex = submeshFirstVertex, vertexCount = submeshVertexCount, forceSeparate = false } ); } workingInstruction.vertexCount = vertexCount; workingInstruction.immutableTriangles = this.immutableTriangles; #if SPINE_OPTIONAL_FRONTFACING workingInstruction.frontFacing = this.frontFacing; #endif // STEP 1.9. Post-process workingInstructions. #if SPINE_OPTIONAL_MATERIALOVERRIDE // Material overrides are done here so they can be applied per submesh instead of per slot // but they will still be passed through the GenerateMeshOverride delegate, // and will still go through the normal material match check step in STEP 3. if (customMaterialOverride.Count > 0) // isCustomMaterialOverridePopulated { var workingSubmeshInstructionsItems = workingSubmeshInstructions.Items; for (int i = 0; i < workingSubmeshInstructions.Count; i++) { var m = workingSubmeshInstructionsItems[i].material; Material mo; if (customMaterialOverride.TryGetValue(m, out mo)) { workingSubmeshInstructionsItems[i].material = mo; } } } #endif #if SPINE_OPTIONAL_RENDEROVERRIDE if (this.generateMeshOverride != null) { this.generateMeshOverride(workingInstruction); if (disableRenderingOnOverride) { return; } } #endif // STEP 2. Update vertex buffer based on verts from the attachments. // Uses values that were also stored in workingInstruction. Vector3[] vertices = this.vertices; bool vertexCountIncreased = vertexCount > vertices.Length; if (vertexCountIncreased) { this.vertices = vertices = new Vector3[vertexCount]; this.colors = new Color32[vertexCount]; this.uvs = new Vector2[vertexCount]; #if SPINE_OPTIONAL_NORMALS if (calculateNormals) { Vector3[] localNormals = this.normals = new Vector3[vertexCount]; Vector3 normal = new Vector3(0, 0, -1); for (int i = 0; i < vertexCount; i++) { localNormals[i] = normal; } } // For dynamic tangent calculation, you can remove the tangent-filling logic and add tangent calculation logic below. if (calculateTangents) { Vector4[] localTangents = this.tangents = new Vector4[vertexCount]; Vector4 tangent = new Vector4(1, 0, 0, -1); for (int i = 0; i < vertexCount; i++) { localTangents[i] = tangent; } } #endif } else { Vector3 zero = Vector3.zero; for (int i = vertexCount, n = vertices.Length; i < n; i++) { vertices[i] = zero; } } float zSpacing = this.zSpacing; float[] tempVertices = this.tempVertices; Vector2[] uvs = this.uvs; Color32[] colors = this.colors; int vertexIndex = 0; bool pmaVertexColors = this.pmaVertexColors; Color32 color; float a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b; Vector3 meshBoundsMin; Vector3 meshBoundsMax; if (vertexCount == 0) { meshBoundsMin = new Vector3(0, 0, 0); meshBoundsMax = new Vector3(0, 0, 0); } else { meshBoundsMin.x = int.MaxValue; meshBoundsMin.y = int.MaxValue; meshBoundsMax.x = int.MinValue; meshBoundsMax.y = int.MinValue; if (zSpacing > 0f) { meshBoundsMin.z = 0f; meshBoundsMax.z = zSpacing * (drawOrderCount - 1); } else { meshBoundsMin.z = zSpacing * (drawOrderCount - 1); meshBoundsMax.z = 0f; } int i = 0; do { Slot slot = drawOrderItems[i]; Attachment attachment = slot.attachment; RegionAttachment regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { regionAttachment.ComputeWorldVertices(slot.bone, tempVertices); float z = i * zSpacing; float x1 = tempVertices[RegionAttachment.X1], y1 = tempVertices[RegionAttachment.Y1]; float x2 = tempVertices[RegionAttachment.X2], y2 = tempVertices[RegionAttachment.Y2]; float x3 = tempVertices[RegionAttachment.X3], y3 = tempVertices[RegionAttachment.Y3]; float x4 = tempVertices[RegionAttachment.X4], y4 = tempVertices[RegionAttachment.Y4]; vertices[vertexIndex].x = x1; vertices[vertexIndex].y = y1; vertices[vertexIndex].z = z; vertices[vertexIndex + 1].x = x4; vertices[vertexIndex + 1].y = y4; vertices[vertexIndex + 1].z = z; vertices[vertexIndex + 2].x = x2; vertices[vertexIndex + 2].y = y2; vertices[vertexIndex + 2].z = z; vertices[vertexIndex + 3].x = x3; vertices[vertexIndex + 3].y = y3; vertices[vertexIndex + 3].z = z; if (pmaVertexColors) { color.a = (byte)(a * slot.a * regionAttachment.a); color.r = (byte)(r * slot.r * regionAttachment.r * color.a); color.g = (byte)(g * slot.g * regionAttachment.g * color.a); color.b = (byte)(b * slot.b * regionAttachment.b * color.a); if (slot.data.blendMode == BlendMode.additive) { color.a = 0; } } else { color.a = (byte)(a * slot.a * regionAttachment.a); color.r = (byte)(r * slot.r * regionAttachment.r * 255); color.g = (byte)(g * slot.g * regionAttachment.g * 255); color.b = (byte)(b * slot.b * regionAttachment.b * 255); } colors[vertexIndex] = color; colors[vertexIndex + 1] = color; colors[vertexIndex + 2] = color; colors[vertexIndex + 3] = color; float[] regionUVs = regionAttachment.uvs; uvs[vertexIndex].x = regionUVs[RegionAttachment.X1]; uvs[vertexIndex].y = regionUVs[RegionAttachment.Y1]; uvs[vertexIndex + 1].x = regionUVs[RegionAttachment.X4]; uvs[vertexIndex + 1].y = regionUVs[RegionAttachment.Y4]; uvs[vertexIndex + 2].x = regionUVs[RegionAttachment.X2]; uvs[vertexIndex + 2].y = regionUVs[RegionAttachment.Y2]; uvs[vertexIndex + 3].x = regionUVs[RegionAttachment.X3]; uvs[vertexIndex + 3].y = regionUVs[RegionAttachment.Y3]; // Calculate min/max X if (x1 < meshBoundsMin.x) { meshBoundsMin.x = x1; } else if (x1 > meshBoundsMax.x) { meshBoundsMax.x = x1; } if (x2 < meshBoundsMin.x) { meshBoundsMin.x = x2; } else if (x2 > meshBoundsMax.x) { meshBoundsMax.x = x2; } if (x3 < meshBoundsMin.x) { meshBoundsMin.x = x3; } else if (x3 > meshBoundsMax.x) { meshBoundsMax.x = x3; } if (x4 < meshBoundsMin.x) { meshBoundsMin.x = x4; } else if (x4 > meshBoundsMax.x) { meshBoundsMax.x = x4; } // Calculate min/max Y if (y1 < meshBoundsMin.y) { meshBoundsMin.y = y1; } else if (y1 > meshBoundsMax.y) { meshBoundsMax.y = y1; } if (y2 < meshBoundsMin.y) { meshBoundsMin.y = y2; } else if (y2 > meshBoundsMax.y) { meshBoundsMax.y = y2; } if (y3 < meshBoundsMin.y) { meshBoundsMin.y = y3; } else if (y3 > meshBoundsMax.y) { meshBoundsMax.y = y3; } if (y4 < meshBoundsMin.y) { meshBoundsMin.y = y4; } else if (y4 > meshBoundsMax.y) { meshBoundsMax.y = y4; } vertexIndex += 4; } else { if (!renderMeshes) { continue; } MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { int meshVertexCount = meshAttachment.worldVerticesLength; if (tempVertices.Length < meshVertexCount) { this.tempVertices = tempVertices = new float[meshVertexCount]; } meshAttachment.ComputeWorldVertices(slot, tempVertices); if (pmaVertexColors) { color.a = (byte)(a * slot.a * meshAttachment.a); color.r = (byte)(r * slot.r * meshAttachment.r * color.a); color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.b = (byte)(b * slot.b * meshAttachment.b * color.a); if (slot.data.blendMode == BlendMode.additive) { color.a = 0; } } else { color.a = (byte)(a * slot.a * meshAttachment.a); color.r = (byte)(r * slot.r * meshAttachment.r * 255); color.g = (byte)(g * slot.g * meshAttachment.g * 255); color.b = (byte)(b * slot.b * meshAttachment.b * 255); } float[] meshUVs = meshAttachment.uvs; float z = i * zSpacing; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { float x = tempVertices[ii], y = tempVertices[ii + 1]; vertices[vertexIndex].x = x; vertices[vertexIndex].y = y; vertices[vertexIndex].z = z; colors[vertexIndex] = color; uvs[vertexIndex].x = meshUVs[ii]; uvs[vertexIndex].y = meshUVs[ii + 1]; if (x < meshBoundsMin.x) { meshBoundsMin.x = x; } else if (x > meshBoundsMax.x) { meshBoundsMax.x = x; } if (y < meshBoundsMin.y) { meshBoundsMin.y = y; } else if (y > meshBoundsMax.y) { meshBoundsMax.y = y; } } } } } while (++i < drawOrderCount); } // Step 3. Move the mesh data into a UnityEngine.Mesh var currentSmartMesh = doubleBufferedMesh.GetNext(); // Double-buffer for performance. var currentMesh = currentSmartMesh.mesh; currentMesh.vertices = vertices; currentMesh.colors32 = colors; currentMesh.uv = uvs; Vector3 meshBoundsExtents = meshBoundsMax - meshBoundsMin; Vector3 meshBoundsCenter = meshBoundsMin + meshBoundsExtents * 0.5f; currentMesh.bounds = new Bounds(meshBoundsCenter, meshBoundsExtents); var currentSmartMeshInstructionUsed = currentSmartMesh.instructionUsed; #if SPINE_OPTIONAL_NORMALS if (currentSmartMeshInstructionUsed.vertexCount < vertexCount) { if (calculateNormals) { currentMesh.normals = normals; } // For dynamic calculated tangents, this needs to be moved out of the vertexCount check block when replacing the logic, also ensuring the size. if (calculateTangents) { currentMesh.tangents = this.tangents; } } #endif // Check if the triangles should also be updated. // This thorough structure check is cheaper than updating triangles every frame. bool mustUpdateMeshStructure = CheckIfMustUpdateMeshStructure(workingInstruction, currentSmartMeshInstructionUsed); if (mustUpdateMeshStructure) { var thisSubmeshMaterials = this.submeshMaterials; thisSubmeshMaterials.Clear(false); int submeshCount = workingSubmeshInstructions.Count; int oldSubmeshCount = submeshes.Count; submeshes.Capacity = submeshCount; for (int i = oldSubmeshCount; i < submeshCount; i++) { submeshes.Items[i] = new SubmeshTriangleBuffer(); } var mutableTriangles = !workingInstruction.immutableTriangles; for (int i = 0, last = submeshCount - 1; i < submeshCount; i++) { var submeshInstruction = workingSubmeshInstructions.Items[i]; if (mutableTriangles || i >= oldSubmeshCount) { SetSubmesh(i, submeshInstruction, #if SPINE_OPTIONAL_FRONTFACING currentInstructions.attachmentFlips, #endif i == last); } thisSubmeshMaterials.Add(submeshInstruction.material); } currentMesh.subMeshCount = submeshCount; for (int i = 0; i < submeshCount; ++i) { currentMesh.SetTriangles(submeshes.Items[i].triangles, i); } } // CheckIfMustUpdateMaterialArray (last pushed materials vs currently parsed materials) // Needs to check against the Working Submesh Instructions Materials instead of the cached submeshMaterials. { var lastPushedMaterials = this.sharedMaterials; bool mustUpdateRendererMaterials = mustUpdateMeshStructure || (lastPushedMaterials.Length != workingSubmeshInstructions.Count); if (!mustUpdateRendererMaterials) { var workingSubmeshInstructionsItems = workingSubmeshInstructions.Items; for (int i = 0, n = lastPushedMaterials.Length; i < n; i++) { if (lastPushedMaterials[i].GetInstanceID() != workingSubmeshInstructionsItems[i].material.GetInstanceID()) // Bounds check is implied above. { mustUpdateRendererMaterials = true; break; } } } if (mustUpdateRendererMaterials) { if (submeshMaterials.Count == sharedMaterials.Length) { submeshMaterials.CopyTo(sharedMaterials); } else { sharedMaterials = submeshMaterials.ToArray(); } meshRenderer.sharedMaterials = sharedMaterials; } } // Step 4. The UnityEngine.Mesh is ready. Set it as the MeshFilter's mesh. Store the instructions used for that mesh. meshFilter.sharedMesh = currentMesh; currentSmartMesh.instructionUsed.Set(workingInstruction); // Step 5. Miscellaneous // Add stuff here if you want #if SPINE_OPTIONAL_SUBMESHRENDERER if (submeshRenderers.Length > 0) { for (int i = 0; i < submeshRenderers.Length; i++) { var submeshRenderer = submeshRenderers[i]; if (submeshRenderer.submeshIndex < sharedMaterials.Length) { submeshRenderer.SetMesh(meshRenderer, currentMesh, sharedMaterials[submeshRenderer.submeshIndex]); } else { submeshRenderer.GetComponent <Renderer>().enabled = false; } } } #endif }
// RegionAttachment protected void AddAttachment(Slot slot, RegionAttachment attachment) { var tempVertices = this.tempVertices; attachment.ComputeWorldVertices(slot.bone, tempVertices); float[] regionUVs = attachment.uvs; Color color = skeletonColor; color.r = color.r * attachment.r * slot.r; color.g = color.g * attachment.g * slot.g; color.b = color.b * attachment.b * slot.b; color.a = color.a * attachment.a * slot.a; if (premultiplyAlpha) { color.r *= color.a; color.g *= color.a; color.b *= color.a; if (slot.data.blendMode == BlendMode.additive) color.a = 0; } int fv = positions.Count; // first vertex index AddVert(new Vector3(tempVertices[RegionAttachment.X1] * scale, tempVertices[RegionAttachment.Y1] * scale), color, new Vector2(regionUVs[RegionAttachment.X1], regionUVs[RegionAttachment.Y1])); AddVert(new Vector3(tempVertices[RegionAttachment.X4] * scale, tempVertices[RegionAttachment.Y4] * scale), color, new Vector2(regionUVs[RegionAttachment.X4], regionUVs[RegionAttachment.Y4])); AddVert(new Vector3(tempVertices[RegionAttachment.X2] * scale, tempVertices[RegionAttachment.Y2] * scale), color, new Vector2(regionUVs[RegionAttachment.X2], regionUVs[RegionAttachment.Y2])); AddVert(new Vector3(tempVertices[RegionAttachment.X3] * scale, tempVertices[RegionAttachment.Y3] * scale), color, new Vector2(regionUVs[RegionAttachment.X3], regionUVs[RegionAttachment.Y3])); AddTriangle(fv, fv+2, fv+1); AddTriangle(fv+2, fv+3, fv+1); }
public void AddSubmesh(SubmeshInstruction instruction, bool updateTriangles = true) { Settings settings = this.settings; if (submeshes.Count - 1 < submeshIndex) { submeshes.Resize(submeshIndex + 1); if (submeshes.Items[submeshIndex] == null) { submeshes.Items[submeshIndex] = new ExposedList <int>(); } } ExposedList <int> exposedList = submeshes.Items[submeshIndex]; exposedList.Clear(clearArray: false); Skeleton skeleton = instruction.skeleton; Slot[] items = skeleton.drawOrder.Items; Color32 color = default(Color32); float num = skeleton.a * 255f; float r = skeleton.r; float g = skeleton.g; float b = skeleton.b; Vector2 vector = meshBoundsMin; Vector2 vector2 = meshBoundsMax; float zSpacing = settings.zSpacing; bool pmaVertexColors = settings.pmaVertexColors; bool tintBlack = settings.tintBlack; bool flag = settings.useClipping && instruction.hasClipping; if (flag && instruction.preActiveClippingSlotSource >= 0) { Slot slot = items[instruction.preActiveClippingSlotSource]; clipper.ClipStart(slot, slot.attachment as ClippingAttachment); } for (int i = instruction.startSlot; i < instruction.endSlot; i++) { Slot slot2 = items[i]; Attachment attachment = slot2.attachment; float z = zSpacing * (float)i; float[] array = tempVerts; Color color2 = default(Color); RegionAttachment regionAttachment = attachment as RegionAttachment; float[] array2; int[] array3; int num2; int num3; if (regionAttachment != null) { regionAttachment.ComputeWorldVertices(slot2.bone, array, 0); array2 = regionAttachment.uvs; array3 = regionTriangles; color2.r = regionAttachment.r; color2.g = regionAttachment.g; color2.b = regionAttachment.b; color2.a = regionAttachment.a; num2 = 4; num3 = 6; } else { MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment == null) { if (flag) { ClippingAttachment clippingAttachment = attachment as ClippingAttachment; if (clippingAttachment != null) { clipper.ClipStart(slot2, clippingAttachment); } } continue; } int worldVerticesLength = meshAttachment.worldVerticesLength; if (array.Length < worldVerticesLength) { array = (tempVerts = new float[worldVerticesLength]); } meshAttachment.ComputeWorldVertices(slot2, 0, worldVerticesLength, array, 0); array2 = meshAttachment.uvs; array3 = meshAttachment.triangles; color2.r = meshAttachment.r; color2.g = meshAttachment.g; color2.b = meshAttachment.b; color2.a = meshAttachment.a; num2 = worldVerticesLength >> 1; num3 = meshAttachment.triangles.Length; } if (pmaVertexColors) { color.a = (byte)(num * slot2.a * color2.a); color.r = (byte)(r * slot2.r * color2.r * (float)(int)color.a); color.g = (byte)(g * slot2.g * color2.g * (float)(int)color.a); color.b = (byte)(b * slot2.b * color2.b * (float)(int)color.a); if (slot2.data.blendMode == BlendMode.Additive) { color.a = 0; } } else { color.a = (byte)(num * slot2.a * color2.a); color.r = (byte)(r * slot2.r * color2.r * 255f); color.g = (byte)(g * slot2.g * color2.g * 255f); color.b = (byte)(b * slot2.b * color2.b * 255f); } if (flag && clipper.IsClipping()) { clipper.ClipTriangles(array, num2 << 1, array3, num3, array2); array = clipper.clippedVertices.Items; num2 = clipper.clippedVertices.Count >> 1; array3 = clipper.clippedTriangles.Items; num3 = clipper.clippedTriangles.Count; array2 = clipper.clippedUVs.Items; } if (num2 != 0 && num3 != 0) { if (tintBlack) { AddAttachmentTintBlack(slot2.r2, slot2.g2, slot2.b2, num2); } int count = vertexBuffer.Count; int num4 = count + num2; if (num4 > vertexBuffer.Items.Length) { Array.Resize(ref vertexBuffer.Items, num4); Array.Resize(ref uvBuffer.Items, num4); Array.Resize(ref colorBuffer.Items, num4); } vertexBuffer.Count = (uvBuffer.Count = (colorBuffer.Count = num4)); Vector3[] items2 = vertexBuffer.Items; Vector2[] items3 = uvBuffer.Items; Color32[] items4 = colorBuffer.Items; if (count == 0) { for (int j = 0; j < num2; j++) { int num5 = count + j; int num6 = j << 1; float num7 = array[num6]; float num8 = array[num6 + 1]; items2[num5].x = num7; items2[num5].y = num8; items2[num5].z = z; items3[num5].x = array2[num6]; items3[num5].y = array2[num6 + 1]; items4[num5] = color; if (num7 < vector.x) { vector.x = num7; } if (num7 > vector2.x) { vector2.x = num7; } if (num8 < vector.y) { vector.y = num8; } if (num8 > vector2.y) { vector2.y = num8; } } } else { for (int k = 0; k < num2; k++) { int num9 = count + k; int num10 = k << 1; float num11 = array[num10]; float num12 = array[num10 + 1]; items2[num9].x = num11; items2[num9].y = num12; items2[num9].z = z; items3[num9].x = array2[num10]; items3[num9].y = array2[num10 + 1]; items4[num9] = color; if (num11 < vector.x) { vector.x = num11; } else if (num11 > vector2.x) { vector2.x = num11; } if (num12 < vector.y) { vector.y = num12; } else if (num12 > vector2.y) { vector2.y = num12; } } } if (updateTriangles) { int count2 = exposedList.Count; int num13 = count2 + num3; if (num13 > exposedList.Items.Length) { Array.Resize(ref exposedList.Items, num13); } exposedList.Count = num13; int[] items5 = exposedList.Items; for (int l = 0; l < num3; l++) { items5[count2 + l] = array3[l] + count; } } } clipper.ClipEnd(slot2); } clipper.ClipEnd(); meshBoundsMin = vector; meshBoundsMax = vector2; meshBoundsThickness = (float)instruction.endSlot * zSpacing; int[] items6 = exposedList.Items; int m = exposedList.Count; for (int num14 = items6.Length; m < num14; m++) { items6[m] = 0; } submeshIndex++; }
public virtual void LateUpdate() { if (!valid) { return; } // Exit early if there is nothing to render if (!meshRenderer.enabled && submeshRenderers.Length == 0) { return; } // This method caches several .Items arrays. Whenever it does, there should be no mutations done on the overlying ExposedList object. // Count vertices and submesh triangles. int vertexCount = 0; int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0; Material lastMaterial = null; ExposedList <Slot> drawOrder = skeleton.drawOrder; var drawOrderItems = drawOrder.Items; int drawOrderCount = drawOrder.Count; int submeshSeparatorSlotsCount = submeshSeparatorSlots.Count; bool renderMeshes = this.renderMeshes; // Clear last state of attachments and submeshes MeshState.SingleMeshState workingState = meshState.buffer; var workingAttachments = workingState.attachments; workingAttachments.Clear(true); workingState.UpdateAttachmentCount(drawOrderCount); var workingAttachmentsItems = workingAttachments.Items; var workingFlips = workingState.attachmentsFlipState; var workingFlipsItems = workingState.attachmentsFlipState.Items; var workingSubmeshArguments = workingState.addSubmeshArguments; // Items array should not be cached. There is dynamic writing to this object. workingSubmeshArguments.Clear(false); MeshState.SingleMeshState storedState = useMesh1 ? meshState.stateMesh1 : meshState.stateMesh2; var storedAttachments = storedState.attachments; var storedAttachmentsItems = storedAttachments.Items; var storedFlips = storedState.attachmentsFlipState; var storedFlipsItems = storedFlips.Items; bool mustUpdateMeshStructure = storedState.requiresUpdate || // Force update if the mesh was cleared. (prevents flickering due to incorrect state) drawOrderCount != storedAttachments.Count || // Number of slots changed (when does this happen?) immutableTriangles != storedState.immutableTriangles; // Immutable Triangles flag changed. bool isCustomMaterialsPopulated = customSlotMaterials.Count > 0; for (int i = 0; i < drawOrderCount; i++) { Slot slot = drawOrderItems[i]; Bone bone = slot.bone; Attachment attachment = slot.attachment; object rendererObject; // An AtlasRegion in plain Spine-Unity. Spine-TK2D hooks into TK2D's system. eventual source of Material object. int attachmentVertexCount, attachmentTriangleCount; // Handle flipping for triangle winding (for lighting?). bool flip = frontFacing && (bone.WorldSignX != bone.WorldSignY); workingFlipsItems[i] = flip; workingAttachmentsItems[i] = attachment; mustUpdateMeshStructure = mustUpdateMeshStructure || // Always prefer short circuited or. || and not |=. (attachment != storedAttachmentsItems[i]) || // Attachment order changed. // This relies on the drawOrder.Count != storedAttachments.Count check above as a bounds check. (flip != storedFlipsItems[i]); // Flip states changed. var regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { rendererObject = regionAttachment.RendererObject; attachmentVertexCount = 4; attachmentTriangleCount = 6; } else { if (!renderMeshes) { continue; } var meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { rendererObject = meshAttachment.RendererObject; attachmentVertexCount = meshAttachment.vertices.Length >> 1; attachmentTriangleCount = meshAttachment.triangles.Length; } else { var skinnedMeshAttachment = attachment as WeightedMeshAttachment; if (skinnedMeshAttachment != null) { rendererObject = skinnedMeshAttachment.RendererObject; attachmentVertexCount = skinnedMeshAttachment.uvs.Length >> 1; attachmentTriangleCount = skinnedMeshAttachment.triangles.Length; } else { continue; } } } #if !SPINE_TK2D // Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject; // For no customSlotMaterials Material material; if (isCustomMaterialsPopulated) { if (!customSlotMaterials.TryGetValue(slot, out material)) { material = (Material)((AtlasRegion)rendererObject).page.rendererObject; } } else { material = (Material)((AtlasRegion)rendererObject).page.rendererObject; } #else Material material = (rendererObject.GetType() == typeof(Material)) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject; #endif // Populate submesh when material changes. (or when forced to separate by a submeshSeparator) if ((vertexCount > 0 && lastMaterial.GetInstanceID() != material.GetInstanceID()) || (submeshSeparatorSlotsCount > 0 && submeshSeparatorSlots.Contains(slot))) { workingSubmeshArguments.Add( new MeshState.AddSubmeshArguments { material = lastMaterial, startSlot = submeshStartSlotIndex, endSlot = i, triangleCount = submeshTriangleCount, firstVertex = submeshFirstVertex, isLastSubmesh = false } ); submeshTriangleCount = 0; submeshFirstVertex = vertexCount; submeshStartSlotIndex = i; } lastMaterial = material; submeshTriangleCount += attachmentTriangleCount; vertexCount += attachmentVertexCount; } workingSubmeshArguments.Add( new MeshState.AddSubmeshArguments { material = lastMaterial, startSlot = submeshStartSlotIndex, endSlot = drawOrderCount, triangleCount = submeshTriangleCount, firstVertex = submeshFirstVertex, isLastSubmesh = true } ); mustUpdateMeshStructure = mustUpdateMeshStructure || this.sharedMaterials.Length != workingSubmeshArguments.Count || // Material array changed in size CheckIfMustUpdateMeshStructure(workingSubmeshArguments); // Submesh Argument Array changed. // CheckIfMustUpdateMaterialArray (workingMaterials, sharedMaterials) if (!mustUpdateMeshStructure) { // Narrow phase material array check. var workingMaterials = workingSubmeshArguments.Items; for (int i = 0, n = sharedMaterials.Length; i < n; i++) { if (this.sharedMaterials[i] != workingMaterials[i].material) // Bounds check is implied above. { mustUpdateMeshStructure = true; break; } } } // NOT ELSE if (mustUpdateMeshStructure) { this.submeshMaterials.Clear(); var workingSubmeshArgumentsItems = workingSubmeshArguments.Items; for (int i = 0, n = workingSubmeshArguments.Count; i < n; i++) { AddSubmesh(workingSubmeshArgumentsItems[i], workingFlips); } // Set materials. if (submeshMaterials.Count == sharedMaterials.Length) { submeshMaterials.CopyTo(sharedMaterials); } else { sharedMaterials = submeshMaterials.ToArray(); } meshRenderer.sharedMaterials = sharedMaterials; } // Ensure mesh data is the right size. Vector3[] vertices = this.vertices; bool newTriangles = vertexCount > vertices.Length; if (newTriangles) { // Not enough vertices, increase size. this.vertices = vertices = new Vector3[vertexCount]; this.colors = new Color32[vertexCount]; this.uvs = new Vector2[vertexCount]; mesh1.Clear(); mesh2.Clear(); meshState.stateMesh1.requiresUpdate = true; meshState.stateMesh2.requiresUpdate = true; } else { // Too many vertices, zero the extra. Vector3 zero = Vector3.zero; for (int i = vertexCount, n = meshState.vertexCount; i < n; i++) { vertices[i] = zero; } } meshState.vertexCount = vertexCount; // Setup mesh. float zSpacing = this.zSpacing; float[] tempVertices = this.tempVertices; Vector2[] uvs = this.uvs; Color32[] colors = this.colors; int vertexIndex = 0; Color32 color; float a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b; Vector3 meshBoundsMin; Vector3 meshBoundsMax; if (vertexCount == 0) { meshBoundsMin = new Vector3(0, 0, 0); meshBoundsMax = new Vector3(0, 0, 0); } else { meshBoundsMin.x = int.MaxValue; meshBoundsMin.y = int.MaxValue; meshBoundsMax.x = int.MinValue; meshBoundsMax.y = int.MinValue; if (zSpacing > 0f) { meshBoundsMin.z = 0f; meshBoundsMax.z = zSpacing * (drawOrderCount - 1); } else { meshBoundsMin.z = zSpacing * (drawOrderCount - 1); meshBoundsMax.z = 0f; } int i = 0; do { Slot slot = drawOrderItems[i]; Attachment attachment = slot.attachment; RegionAttachment regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { regionAttachment.ComputeWorldVertices(slot.bone, tempVertices); float z = i * zSpacing; float x1 = tempVertices[RegionAttachment.X1], y1 = tempVertices[RegionAttachment.Y1]; float x2 = tempVertices[RegionAttachment.X2], y2 = tempVertices[RegionAttachment.Y2]; float x3 = tempVertices[RegionAttachment.X3], y3 = tempVertices[RegionAttachment.Y3]; float x4 = tempVertices[RegionAttachment.X4], y4 = tempVertices[RegionAttachment.Y4]; vertices[vertexIndex].x = x1; vertices[vertexIndex].y = y1; vertices[vertexIndex].z = z; vertices[vertexIndex + 1].x = x4; vertices[vertexIndex + 1].y = y4; vertices[vertexIndex + 1].z = z; vertices[vertexIndex + 2].x = x2; vertices[vertexIndex + 2].y = y2; vertices[vertexIndex + 2].z = z; vertices[vertexIndex + 3].x = x3; vertices[vertexIndex + 3].y = y3; vertices[vertexIndex + 3].z = z; color.a = (byte)(a * slot.a * regionAttachment.a); color.r = (byte)(r * slot.r * regionAttachment.r * color.a); color.g = (byte)(g * slot.g * regionAttachment.g * color.a); color.b = (byte)(b * slot.b * regionAttachment.b * color.a); if (slot.data.blendMode == BlendMode.additive) { color.a = 0; } colors[vertexIndex] = color; colors[vertexIndex + 1] = color; colors[vertexIndex + 2] = color; colors[vertexIndex + 3] = color; float[] regionUVs = regionAttachment.uvs; uvs[vertexIndex].x = regionUVs[RegionAttachment.X1]; uvs[vertexIndex].y = regionUVs[RegionAttachment.Y1]; uvs[vertexIndex + 1].x = regionUVs[RegionAttachment.X4]; uvs[vertexIndex + 1].y = regionUVs[RegionAttachment.Y4]; uvs[vertexIndex + 2].x = regionUVs[RegionAttachment.X2]; uvs[vertexIndex + 2].y = regionUVs[RegionAttachment.Y2]; uvs[vertexIndex + 3].x = regionUVs[RegionAttachment.X3]; uvs[vertexIndex + 3].y = regionUVs[RegionAttachment.Y3]; // Calculate min/max X if (x1 < meshBoundsMin.x) { meshBoundsMin.x = x1; } else if (x1 > meshBoundsMax.x) { meshBoundsMax.x = x1; } if (x2 < meshBoundsMin.x) { meshBoundsMin.x = x2; } else if (x2 > meshBoundsMax.x) { meshBoundsMax.x = x2; } if (x3 < meshBoundsMin.x) { meshBoundsMin.x = x3; } else if (x3 > meshBoundsMax.x) { meshBoundsMax.x = x3; } if (x4 < meshBoundsMin.x) { meshBoundsMin.x = x4; } else if (x4 > meshBoundsMax.x) { meshBoundsMax.x = x4; } // Calculate min/max Y if (y1 < meshBoundsMin.y) { meshBoundsMin.y = y1; } else if (y1 > meshBoundsMax.y) { meshBoundsMax.y = y1; } if (y2 < meshBoundsMin.y) { meshBoundsMin.y = y2; } else if (y2 > meshBoundsMax.y) { meshBoundsMax.y = y2; } if (y3 < meshBoundsMin.y) { meshBoundsMin.y = y3; } else if (y3 > meshBoundsMax.y) { meshBoundsMax.y = y3; } if (y4 < meshBoundsMin.y) { meshBoundsMin.y = y4; } else if (y4 > meshBoundsMax.y) { meshBoundsMax.y = y4; } vertexIndex += 4; } else { if (!renderMeshes) { continue; } MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { int meshVertexCount = meshAttachment.vertices.Length; if (tempVertices.Length < meshVertexCount) { this.tempVertices = tempVertices = new float[meshVertexCount]; } meshAttachment.ComputeWorldVertices(slot, tempVertices); color.a = (byte)(a * slot.a * meshAttachment.a); color.r = (byte)(r * slot.r * meshAttachment.r * color.a); color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.b = (byte)(b * slot.b * meshAttachment.b * color.a); if (slot.data.blendMode == BlendMode.additive) { color.a = 0; } float[] meshUVs = meshAttachment.uvs; float z = i * zSpacing; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { float x = tempVertices[ii], y = tempVertices[ii + 1]; vertices[vertexIndex].x = x; vertices[vertexIndex].y = y; vertices[vertexIndex].z = z; colors[vertexIndex] = color; uvs[vertexIndex].x = meshUVs[ii]; uvs[vertexIndex].y = meshUVs[ii + 1]; if (x < meshBoundsMin.x) { meshBoundsMin.x = x; } else if (x > meshBoundsMax.x) { meshBoundsMax.x = x; } if (y < meshBoundsMin.y) { meshBoundsMin.y = y; } else if (y > meshBoundsMax.y) { meshBoundsMax.y = y; } } } else { WeightedMeshAttachment weightedMeshAttachment = attachment as WeightedMeshAttachment; if (weightedMeshAttachment != null) { int meshVertexCount = weightedMeshAttachment.uvs.Length; if (tempVertices.Length < meshVertexCount) { this.tempVertices = tempVertices = new float[meshVertexCount]; } weightedMeshAttachment.ComputeWorldVertices(slot, tempVertices); color.a = (byte)(a * slot.a * weightedMeshAttachment.a); color.r = (byte)(r * slot.r * weightedMeshAttachment.r * color.a); color.g = (byte)(g * slot.g * weightedMeshAttachment.g * color.a); color.b = (byte)(b * slot.b * weightedMeshAttachment.b * color.a); if (slot.data.blendMode == BlendMode.additive) { color.a = 0; } float[] meshUVs = weightedMeshAttachment.uvs; float z = i * zSpacing; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { float x = tempVertices[ii], y = tempVertices[ii + 1]; vertices[vertexIndex].x = x; vertices[vertexIndex].y = y; vertices[vertexIndex].z = z; colors[vertexIndex] = color; uvs[vertexIndex].x = meshUVs[ii]; uvs[vertexIndex].y = meshUVs[ii + 1]; if (x < meshBoundsMin.x) { meshBoundsMin.x = x; } else if (x > meshBoundsMax.x) { meshBoundsMax.x = x; } if (y < meshBoundsMin.y) { meshBoundsMin.y = y; } else if (y > meshBoundsMax.y) { meshBoundsMax.y = y; } } } } } } while (++i < drawOrderCount); } // Double buffer mesh. Mesh mesh = useMesh1 ? mesh1 : mesh2; meshFilter.sharedMesh = mesh; mesh.vertices = vertices; mesh.colors32 = colors; mesh.uv = uvs; if (mustUpdateMeshStructure) { int submeshCount = submeshMaterials.Count; mesh.subMeshCount = submeshCount; for (int i = 0; i < submeshCount; ++i) { mesh.SetTriangles(submeshes.Items[i].triangles, i); } // Done updating mesh. storedState.requiresUpdate = false; } Vector3 meshBoundsExtents = meshBoundsMax - meshBoundsMin; Vector3 meshBoundsCenter = meshBoundsMin + meshBoundsExtents * 0.5f; mesh.bounds = new Bounds(meshBoundsCenter, meshBoundsExtents); if (newTriangles && calculateNormals) { Vector3[] normals = new Vector3[vertexCount]; Vector3 normal = new Vector3(0, 0, -1); for (int i = 0; i < vertexCount; i++) { normals[i] = normal; } (useMesh1 ? mesh2 : mesh1).vertices = vertices; // Set other mesh vertices. mesh1.normals = normals; mesh2.normals = normals; if (calculateTangents) { Vector4[] tangents = new Vector4[vertexCount]; Vector4 tangent = new Vector4(1, 0, 0, -1); for (int i = 0; i < vertexCount; i++) { tangents[i] = tangent; } mesh1.tangents = tangents; mesh2.tangents = tangents; } } // Update previous state storedState.immutableTriangles = immutableTriangles; storedAttachments.Clear(true); storedAttachments.GrowIfNeeded(workingAttachments.Capacity); storedAttachments.Count = workingAttachments.Count; workingAttachments.CopyTo(storedAttachments.Items); storedFlips.GrowIfNeeded(workingFlips.Capacity); storedFlips.Count = workingFlips.Count; workingFlips.CopyTo(storedFlips.Items); storedState.addSubmeshArguments.GrowIfNeeded(workingSubmeshArguments.Capacity); storedState.addSubmeshArguments.Count = workingSubmeshArguments.Count; workingSubmeshArguments.CopyTo(storedState.addSubmeshArguments.Items); // Submesh Renderers if (submeshRenderers.Length > 0) { for (int i = 0; i < submeshRenderers.Length; i++) { SkeletonUtilitySubmeshRenderer submeshRenderer = submeshRenderers[i]; if (submeshRenderer.submeshIndex < sharedMaterials.Length) { submeshRenderer.SetMesh(meshRenderer, useMesh1 ? mesh1 : mesh2, sharedMaterials[submeshRenderer.submeshIndex]); } else { submeshRenderer.GetComponent <Renderer>().enabled = false; } } } useMesh1 = !useMesh1; }
protected void UpdateSkeletonGeometry() { skeletonGeometry.ClearInstances(); //defaultBlendState = PremultipliedAlpha ? BlendState.AlphaBlend : BlendState.NonPremultiplied; float[] vertices = this.vertices; List <Slot> drawOrder = Skeleton.DrawOrder; float x = Skeleton.X, y = Skeleton.Y; CCColor3B color3b = Color; float skeletonR = color3b.R / 255f; float skeletonG = color3b.G / 255f; float skeletonB = color3b.B / 255f; float skeletonA = Opacity / 255f; for (int i = 0, n = drawOrder.Count; i < n; i++) { Slot slot = drawOrder[i]; Attachment attachment = slot.Attachment; if (attachment is RegionAttachment) { RegionAttachment regionAttachment = (RegionAttachment)attachment; //BlendState blend = slot.Data.AdditiveBlending ? BlendState.Additive : defaultBlendState; var item = skeletonGeometry.CreateGeometryInstance(4, 6); //item.InstanceAttributes.BlendState = blend; //item.InstanceAttributes.AdditionalTransform = AffineWorldTransform; item.GeometryPacket.Indicies = quadTriangles; var itemVertices = item.GeometryPacket.Vertices; AtlasRegion region = (AtlasRegion)regionAttachment.RendererObject; item.GeometryPacket.Texture = (CCTexture2D)region.page.rendererObject; CCColor4B color; float a = skeletonA * slot.A * regionAttachment.A; if (PremultipliedAlpha) { color = new CCColor4B( skeletonR * slot.R * regionAttachment.R * a, skeletonG * slot.G * regionAttachment.G * a, skeletonB * slot.B * regionAttachment.B * a, a); } else { color = new CCColor4B( skeletonR * slot.R * regionAttachment.R, skeletonG * slot.G * regionAttachment.G, skeletonB * slot.B * regionAttachment.B, a); } itemVertices[TL].Colors = color; itemVertices[BL].Colors = color; itemVertices[BR].Colors = color; itemVertices[TR].Colors = color; regionAttachment.ComputeWorldVertices(x, y, slot.Bone, vertices); itemVertices[TL].Vertices.X = vertices[RegionAttachment.X1]; itemVertices[TL].Vertices.Y = vertices[RegionAttachment.Y1]; itemVertices[TL].Vertices.Z = 0; itemVertices[BL].Vertices.X = vertices[RegionAttachment.X2]; itemVertices[BL].Vertices.Y = vertices[RegionAttachment.Y2]; itemVertices[BL].Vertices.Z = 0; itemVertices[BR].Vertices.X = vertices[RegionAttachment.X3]; itemVertices[BR].Vertices.Y = vertices[RegionAttachment.Y3]; itemVertices[BR].Vertices.Z = 0; itemVertices[TR].Vertices.X = vertices[RegionAttachment.X4]; itemVertices[TR].Vertices.Y = vertices[RegionAttachment.Y4]; itemVertices[TR].Vertices.Z = 0; float[] uvs = regionAttachment.UVs; itemVertices[TL].TexCoords.U = uvs[RegionAttachment.X1]; itemVertices[TL].TexCoords.V = uvs[RegionAttachment.Y1]; itemVertices[BL].TexCoords.U = uvs[RegionAttachment.X2]; itemVertices[BL].TexCoords.V = uvs[RegionAttachment.Y2]; itemVertices[BR].TexCoords.U = uvs[RegionAttachment.X3]; itemVertices[BR].TexCoords.V = uvs[RegionAttachment.Y3]; itemVertices[TR].TexCoords.U = uvs[RegionAttachment.X4]; itemVertices[TR].TexCoords.V = uvs[RegionAttachment.Y4]; } else if (attachment is MeshAttachment) { MeshAttachment mesh = (MeshAttachment)attachment; int vertexCount = mesh.Vertices.Length; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; } mesh.ComputeWorldVertices(x, y, slot, vertices); int[] triangles = mesh.Triangles; var item = skeletonGeometry.CreateGeometryInstance(vertexCount, triangles.Length); //item.InstanceAttributes.AdditionalTransform = AffineWorldTransform; item.GeometryPacket.Indicies = triangles; AtlasRegion region = (AtlasRegion)mesh.RendererObject; item.GeometryPacket.Texture = (CCTexture2D)region.page.rendererObject; CCColor4B color; float a = skeletonA * slot.A * mesh.A; if (PremultipliedAlpha) { color = new CCColor4B( skeletonR * slot.R * mesh.R * a, skeletonG * slot.G * mesh.G * a, skeletonB * slot.B * mesh.B * a, a); } else { color = new CCColor4B( skeletonR * slot.R * mesh.R, skeletonG * slot.G * mesh.G, skeletonB * slot.B * mesh.B, a); } float[] uvs = mesh.UVs; var itemVertices = item.GeometryPacket.Vertices; for (int ii = 0, v = 0; v < vertexCount; ii++, v += 2) { itemVertices[ii].Colors = color; itemVertices[ii].Vertices.X = vertices[v]; itemVertices[ii].Vertices.Y = vertices[v + 1]; itemVertices[ii].Vertices.Z = 0; itemVertices[ii].TexCoords.U = uvs[v]; itemVertices[ii].TexCoords.V = uvs[v + 1]; } } else if (attachment is SkinnedMeshAttachment) { SkinnedMeshAttachment mesh = (SkinnedMeshAttachment)attachment; int vertexCount = mesh.UVs.Length; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; } mesh.ComputeWorldVertices(x, y, slot, vertices); int[] triangles = mesh.Triangles; var item = skeletonGeometry.CreateGeometryInstance(vertexCount, triangles.Length); item.GeometryPacket.Indicies = triangles; //item.InstanceAttributes.AdditionalTransform = AffineWorldTransform; AtlasRegion region = (AtlasRegion)mesh.RendererObject; item.GeometryPacket.Texture = (CCTexture2D)region.page.rendererObject; CCColor4B color; float a = skeletonA * slot.A * mesh.A; if (PremultipliedAlpha) { color = new CCColor4B( skeletonR * slot.R * mesh.R * a, skeletonG * slot.G * mesh.G * a, skeletonB * slot.B * mesh.B * a, a); } else { color = new CCColor4B( skeletonR * slot.R * mesh.R, skeletonG * slot.G * mesh.G, skeletonB * slot.B * mesh.B, a); } float[] uvs = mesh.UVs; var itemVertices = item.GeometryPacket.Vertices; for (int ii = 0, v = 0; v < vertexCount; ii++, v += 2) { itemVertices[ii].Colors = color; itemVertices[ii].Vertices.X = vertices[v]; itemVertices[ii].Vertices.Y = vertices[v + 1]; itemVertices[ii].Vertices.Z = 0; itemVertices[ii].TexCoords.U = uvs[v]; itemVertices[ii].TexCoords.V = uvs[v + 1]; } } } debugger.Clear(); if (DebugBones || DebugSlots) { if (DebugSlots) { for (int i = 0; i < Skeleton.Slots.Count; ++i) { var slot = Skeleton.Slots[i]; if (slot.Attachment == null) { continue; } var verticesCount = 0; var worldVertices = new float[1000]; // Max number of vertices per mesh. if (slot.Attachment is RegionAttachment) { var attachment = (RegionAttachment)slot.Attachment; attachment.ComputeWorldVertices(Skeleton.X, Skeleton.Y, slot.bone, worldVertices); verticesCount = 8; } else if (slot.Attachment is MeshAttachment) { var mesh = (MeshAttachment)slot.Attachment; mesh.ComputeWorldVertices(Skeleton.X, Skeleton.Y, slot, worldVertices); verticesCount = mesh.Vertices.Length; } else if (slot.Attachment is SkinnedMeshAttachment) { var mesh = (SkinnedMeshAttachment)slot.Attachment; mesh.ComputeWorldVertices(Skeleton.X, Skeleton.Y, slot, worldVertices); verticesCount = mesh.UVs.Length; } else { continue; } CCPoint[] slotVertices = new CCPoint[verticesCount / 2]; for (int ii = 0, si = 0; ii < verticesCount; ii += 2, si++) { slotVertices[si].X = worldVertices[ii] * ScaleX; slotVertices[si].Y = worldVertices[ii + 1] * ScaleY; } debugger.DrawPolygon(slotVertices, verticesCount / 2, CCColor4B.Transparent, 1, DebugSlotColor); } } if (DebugBones) { // Bone lengths. for (int i = 0; i < Skeleton.Bones.Count; i++) { Bone bone = Skeleton.Bones[i]; x = bone.Data.Length * bone.M00 + bone.WorldX; y = bone.Data.Length * bone.M10 + bone.WorldY; debugger.DrawLine(new CCPoint(bone.WorldX, bone.WorldY), new CCPoint(x, y), 1, DebugJointColor); } // Bone origins. for (int i = 0; i < Skeleton.Bones.Count; i++) { Bone bone = Skeleton.Bones[i]; debugger.DrawDot(new CCPoint(bone.WorldX, bone.WorldY), 3, DebugBoneColor); } } } }
public void BuildMeshWithArrays(SkeletonRendererInstruction instruction, bool updateTriangles) { Settings settings = this.settings; int rawVertexCount = instruction.rawVertexCount; if (rawVertexCount > vertexBuffer.Items.Length) { Array.Resize(ref vertexBuffer.Items, rawVertexCount); Array.Resize(ref uvBuffer.Items, rawVertexCount); Array.Resize(ref colorBuffer.Items, rawVertexCount); } vertexBuffer.Count = (uvBuffer.Count = (colorBuffer.Count = rawVertexCount)); Color32 color = default(Color32); int num = 0; float[] array = tempVerts; Vector3 v = meshBoundsMin; Vector3 v2 = meshBoundsMax; Vector3[] items = vertexBuffer.Items; Vector2[] items2 = uvBuffer.Items; Color32[] items3 = colorBuffer.Items; int num2 = 0; int i = 0; Vector2 vector = default(Vector2); Vector2 vector2 = default(Vector2); for (int count = instruction.submeshInstructions.Count; i < count; i++) { SubmeshInstruction submeshInstruction = instruction.submeshInstructions.Items[i]; Skeleton skeleton = submeshInstruction.skeleton; Slot[] items4 = skeleton.drawOrder.Items; float num3 = skeleton.a * 255f; float r = skeleton.r; float g = skeleton.g; float b = skeleton.b; int endSlot = submeshInstruction.endSlot; int startSlot = submeshInstruction.startSlot; num2 = endSlot; if (settings.tintBlack) { int num4 = num; vector.y = 1f; if (uv2 == null) { uv2 = new ExposedList <Vector2>(); uv3 = new ExposedList <Vector2>(); } if (rawVertexCount > uv2.Items.Length) { Array.Resize(ref uv2.Items, rawVertexCount); Array.Resize(ref uv3.Items, rawVertexCount); } uv2.Count = (uv3.Count = rawVertexCount); Vector2[] items5 = uv2.Items; Vector2[] items6 = uv3.Items; for (int j = startSlot; j < endSlot; j++) { Slot slot = items4[j]; Attachment attachment = slot.attachment; vector2.x = slot.r2; vector2.y = slot.g2; vector.x = slot.b2; RegionAttachment regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { items5[num4] = vector2; items5[num4 + 1] = vector2; items5[num4 + 2] = vector2; items5[num4 + 3] = vector2; items6[num4] = vector; items6[num4 + 1] = vector; items6[num4 + 2] = vector; items6[num4 + 3] = vector; num4 += 4; continue; } MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { int worldVerticesLength = meshAttachment.worldVerticesLength; for (int k = 0; k < worldVerticesLength; k += 2) { items5[num4] = vector2; items6[num4] = vector; num4++; } } } } for (int l = startSlot; l < endSlot; l++) { Slot slot2 = items4[l]; Attachment attachment2 = slot2.attachment; float z = (float)l * settings.zSpacing; RegionAttachment regionAttachment2 = attachment2 as RegionAttachment; if (regionAttachment2 != null) { regionAttachment2.ComputeWorldVertices(slot2.bone, array, 0); float num5 = array[0]; float num6 = array[1]; float num7 = array[2]; float num8 = array[3]; float num9 = array[4]; float num10 = array[5]; float num11 = array[6]; float num12 = array[7]; items[num].x = num5; items[num].y = num6; items[num].z = z; items[num + 1].x = num11; items[num + 1].y = num12; items[num + 1].z = z; items[num + 2].x = num7; items[num + 2].y = num8; items[num + 2].z = z; items[num + 3].x = num9; items[num + 3].y = num10; items[num + 3].z = z; if (settings.pmaVertexColors) { color.a = (byte)(num3 * slot2.a * regionAttachment2.a); color.r = (byte)(r * slot2.r * regionAttachment2.r * (float)(int)color.a); color.g = (byte)(g * slot2.g * regionAttachment2.g * (float)(int)color.a); color.b = (byte)(b * slot2.b * regionAttachment2.b * (float)(int)color.a); if (slot2.data.blendMode == BlendMode.Additive) { color.a = 0; } } else { color.a = (byte)(num3 * slot2.a * regionAttachment2.a); color.r = (byte)(r * slot2.r * regionAttachment2.r * 255f); color.g = (byte)(g * slot2.g * regionAttachment2.g * 255f); color.b = (byte)(b * slot2.b * regionAttachment2.b * 255f); } items3[num] = color; items3[num + 1] = color; items3[num + 2] = color; items3[num + 3] = color; float[] uvs = regionAttachment2.uvs; items2[num].x = uvs[0]; items2[num].y = uvs[1]; items2[num + 1].x = uvs[6]; items2[num + 1].y = uvs[7]; items2[num + 2].x = uvs[2]; items2[num + 2].y = uvs[3]; items2[num + 3].x = uvs[4]; items2[num + 3].y = uvs[5]; if (num5 < v.x) { v.x = num5; } if (num5 > v2.x) { v2.x = num5; } if (num7 < v.x) { v.x = num7; } else if (num7 > v2.x) { v2.x = num7; } if (num9 < v.x) { v.x = num9; } else if (num9 > v2.x) { v2.x = num9; } if (num11 < v.x) { v.x = num11; } else if (num11 > v2.x) { v2.x = num11; } if (num6 < v.y) { v.y = num6; } if (num6 > v2.y) { v2.y = num6; } if (num8 < v.y) { v.y = num8; } else if (num8 > v2.y) { v2.y = num8; } if (num10 < v.y) { v.y = num10; } else if (num10 > v2.y) { v2.y = num10; } if (num12 < v.y) { v.y = num12; } else if (num12 > v2.y) { v2.y = num12; } num += 4; continue; } MeshAttachment meshAttachment2 = attachment2 as MeshAttachment; if (meshAttachment2 == null) { continue; } int worldVerticesLength2 = meshAttachment2.worldVerticesLength; if (array.Length < worldVerticesLength2) { array = (tempVerts = new float[worldVerticesLength2]); } meshAttachment2.ComputeWorldVertices(slot2, array); if (settings.pmaVertexColors) { color.a = (byte)(num3 * slot2.a * meshAttachment2.a); color.r = (byte)(r * slot2.r * meshAttachment2.r * (float)(int)color.a); color.g = (byte)(g * slot2.g * meshAttachment2.g * (float)(int)color.a); color.b = (byte)(b * slot2.b * meshAttachment2.b * (float)(int)color.a); if (slot2.data.blendMode == BlendMode.Additive) { color.a = 0; } } else { color.a = (byte)(num3 * slot2.a * meshAttachment2.a); color.r = (byte)(r * slot2.r * meshAttachment2.r * 255f); color.g = (byte)(g * slot2.g * meshAttachment2.g * 255f); color.b = (byte)(b * slot2.b * meshAttachment2.b * 255f); } float[] uvs2 = meshAttachment2.uvs; if (num == 0) { float num13 = array[0]; float num14 = array[1]; if (num13 < v.x) { v.x = num13; } if (num13 > v2.x) { v2.x = num13; } if (num14 < v.y) { v.y = num14; } if (num14 > v2.y) { v2.y = num14; } } for (int m = 0; m < worldVerticesLength2; m += 2) { float num15 = array[m]; float num16 = array[m + 1]; items[num].x = num15; items[num].y = num16; items[num].z = z; items3[num] = color; items2[num].x = uvs2[m]; items2[num].y = uvs2[m + 1]; if (num15 < v.x) { v.x = num15; } else if (num15 > v2.x) { v2.x = num15; } if (num16 < v.y) { v.y = num16; } else if (num16 > v2.y) { v2.y = num16; } num++; } } } meshBoundsMin = v; meshBoundsMax = v2; meshBoundsThickness = (float)num2 * settings.zSpacing; if (!updateTriangles) { return; } int count2 = instruction.submeshInstructions.Count; if (submeshes.Count < count2) { submeshes.Resize(count2); int n = 0; for (int num17 = count2; n < num17; n++) { ExposedList <int> exposedList = submeshes.Items[n]; if (exposedList == null) { submeshes.Items[n] = new ExposedList <int>(); } else { exposedList.Clear(clearArray: false); } } } SubmeshInstruction[] items7 = instruction.submeshInstructions.Items; int num18 = 0; for (int num19 = 0; num19 < count2; num19++) { SubmeshInstruction submeshInstruction2 = items7[num19]; ExposedList <int> exposedList2 = submeshes.Items[num19]; int rawTriangleCount = submeshInstruction2.rawTriangleCount; if (rawTriangleCount > exposedList2.Items.Length) { Array.Resize(ref exposedList2.Items, rawTriangleCount); } else if (rawTriangleCount < exposedList2.Items.Length) { int[] items8 = exposedList2.Items; int num20 = rawTriangleCount; for (int num21 = items8.Length; num20 < num21; num20++) { items8[num20] = 0; } } exposedList2.Count = rawTriangleCount; int[] items9 = exposedList2.Items; int num22 = 0; Skeleton skeleton2 = submeshInstruction2.skeleton; Slot[] items10 = skeleton2.drawOrder.Items; int num23 = submeshInstruction2.startSlot; for (int endSlot2 = submeshInstruction2.endSlot; num23 < endSlot2; num23++) { Attachment attachment3 = items10[num23].attachment; if (attachment3 is RegionAttachment) { items9[num22] = num18; items9[num22 + 1] = num18 + 2; items9[num22 + 2] = num18 + 1; items9[num22 + 3] = num18 + 2; items9[num22 + 4] = num18 + 3; items9[num22 + 5] = num18 + 1; num22 += 6; num18 += 4; continue; } MeshAttachment meshAttachment3 = attachment3 as MeshAttachment; if (meshAttachment3 != null) { int[] triangles = meshAttachment3.triangles; int num24 = 0; int num25 = triangles.Length; while (num24 < num25) { items9[num22] = num18 + triangles[num24]; num24++; num22++; } num18 += meshAttachment3.worldVerticesLength >> 1; } } } }
public virtual void LateUpdate() { if (!valid) { return; } // Exit early if there is nothing to render if (!meshRenderer.enabled && submeshRenderers.Length == 0) { return; } // Count vertices and submesh triangles. int vertexCount = 0; int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0; Material lastMaterial = null; ExposedList <Slot> drawOrder = skeleton.drawOrder; int drawOrderCount = drawOrder.Count; int submeshSeparatorSlotsCount = submeshSeparatorSlots.Count; bool renderMeshes = this.renderMeshes; // Clear last state of attachments and submeshes ExposedList <int> attachmentsTriangleCountTemp = lastState.attachmentsTriangleCountTemp; attachmentsTriangleCountTemp.GrowIfNeeded(drawOrderCount); attachmentsTriangleCountTemp.Count = drawOrderCount; ExposedList <bool> attachmentsFlipStateTemp = lastState.attachmentsFlipStateTemp; attachmentsFlipStateTemp.GrowIfNeeded(drawOrderCount); attachmentsFlipStateTemp.Count = drawOrderCount; ExposedList <LastState.AddSubmeshArguments> addSubmeshArgumentsTemp = lastState.addSubmeshArgumentsTemp; addSubmeshArgumentsTemp.Clear(false); bool noRender = false; for (int i = 0; i < drawOrderCount; i++) { Slot slot = drawOrder.Items[i]; Bone bone = slot.bone; Attachment attachment = slot.attachment; object rendererObject; int attachmentVertexCount, attachmentTriangleCount; bool worldScaleXIsPositive = bone.worldScaleX >= 0f; bool worldScaleYIsPositive = bone.worldScaleY >= 0f; bool worldScaleIsSameSigns = (worldScaleXIsPositive && worldScaleYIsPositive) || (!worldScaleXIsPositive && !worldScaleYIsPositive); bool flip = frontFacing && ((bone.worldFlipX != bone.worldFlipY) == worldScaleIsSameSigns); attachmentsFlipStateTemp.Items[i] = flip; attachmentsTriangleCountTemp.Items[i] = -1; RegionAttachment regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { rendererObject = regionAttachment.RendererObject; attachmentVertexCount = 4; attachmentTriangleCount = 6; } else { if (!renderMeshes) { continue; } MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { rendererObject = meshAttachment.RendererObject; attachmentVertexCount = meshAttachment.vertices.Length >> 1; attachmentTriangleCount = meshAttachment.triangles.Length; } else { SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment; if (skinnedMeshAttachment != null) { rendererObject = skinnedMeshAttachment.RendererObject; attachmentVertexCount = skinnedMeshAttachment.uvs.Length >> 1; attachmentTriangleCount = skinnedMeshAttachment.triangles.Length; } else { continue; } } } // Populate submesh when material changes. // tsteil - added support for mask material Material material = null; if (useMaskMaterial) { if (maskProvider != null) { if (maskMaterial == null) { var prefabMat = (Material)((AtlasRegion)rendererObject).page.rendererObjectMask; material = new Material(prefabMat); material.hideFlags = HideFlags.HideAndDontSave; maskMaterial = material; SetMaskId(); } else { material = maskMaterial; } } else { material = (Material)((AtlasRegion)rendererObject).page.rendererObjectMask; } } else { #if !SPINE_TK2D material = (Material)((AtlasRegion)rendererObject).page.rendererObject; #else material = (rendererObject.GetType() == typeof(Material)) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject; #endif } if ((lastMaterial != null && lastMaterial.GetInstanceID() != material.GetInstanceID()) || (submeshSeparatorSlotsCount > 0 && submeshSeparatorSlots.Contains(slot))) { addSubmeshArgumentsTemp.Add( new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false) ); submeshTriangleCount = 0; submeshFirstVertex = vertexCount; submeshStartSlotIndex = i; } lastMaterial = material; submeshTriangleCount += attachmentTriangleCount; vertexCount += attachmentVertexCount; attachmentsTriangleCountTemp.Items[i] = attachmentTriangleCount; } // tsteil - we need to keep track if we're rendering or not if (lastMaterial == null) { noRender = true; } addSubmeshArgumentsTemp.Add( new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true) ); bool mustUpdateMeshStructure = CheckIfMustUpdateMeshStructure(attachmentsTriangleCountTemp, attachmentsFlipStateTemp, addSubmeshArgumentsTemp); var submeshMatCount = 0; if (mustUpdateMeshStructure) { submeshMaterials.Clear(); for (int i = 0, n = addSubmeshArgumentsTemp.Count; i < n; i++) { LastState.AddSubmeshArguments arguments = addSubmeshArgumentsTemp.Items[i]; AddSubmesh( arguments.material, arguments.startSlot, arguments.endSlot, arguments.triangleCount, arguments.firstVertex, arguments.lastSubmesh, attachmentsFlipStateTemp ); } // Set materials. submeshMatCount = submeshMaterials.Count; if (submeshMatCount == sharedMaterials.Length) { submeshMaterials.CopyTo(sharedMaterials); } else { sharedMaterials = submeshMaterials.ToArray(); } meshRenderer.sharedMaterials = sharedMaterials; } // Ensure mesh data is the right size. Vector3[] vertices = this.vertices; bool newTriangles = vertexCount > vertices.Length; if (newTriangles) { // Not enough vertices, increase size. this.vertices = vertices = new Vector3[vertexCount]; this.colors = new Color32[vertexCount]; this.uvs = new Vector2[vertexCount]; if (setupUv2) { this.uvs2 = new Vector2[vertexCount]; } mesh1.Clear(); mesh2.Clear(); } else { // Too many vertices, zero the extra. Vector3 zero = Vector3.zero; for (int i = vertexCount, n = lastState.vertexCount; i < n; i++) { vertices[i] = zero; } } lastState.vertexCount = vertexCount; // Setup mesh. float zSpacing = this.zSpacing; float[] tempVertices = this.tempVertices; Vector2[] uvs = this.uvs; Vector2[] uvs2 = this.uvs2; Color32[] colors = this.colors; int vertexIndex = 0; Color32 color; float a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b; Vector3 meshBoundsMin; meshBoundsMin.x = float.MaxValue; meshBoundsMin.y = float.MaxValue; meshBoundsMin.z = zSpacing > 0f ? 0f : zSpacing * (drawOrderCount - 1); Vector3 meshBoundsMax; meshBoundsMax.x = float.MinValue; meshBoundsMax.y = float.MinValue; meshBoundsMax.z = zSpacing < 0f ? 0f : zSpacing * (drawOrderCount - 1); for (int i = 0; i < drawOrderCount; i++) { Slot slot = drawOrder.Items[i]; Attachment attachment = slot.attachment; RegionAttachment regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { regionAttachment.ComputeWorldVertices(slot.bone, tempVertices); float z = i * zSpacing; vertices[vertexIndex].x = tempVertices[RegionAttachment.X1]; vertices[vertexIndex].y = tempVertices[RegionAttachment.Y1]; vertices[vertexIndex].z = z; vertices[vertexIndex + 1].x = tempVertices[RegionAttachment.X4]; vertices[vertexIndex + 1].y = tempVertices[RegionAttachment.Y4]; vertices[vertexIndex + 1].z = z; vertices[vertexIndex + 2].x = tempVertices[RegionAttachment.X2]; vertices[vertexIndex + 2].y = tempVertices[RegionAttachment.Y2]; vertices[vertexIndex + 2].z = z; vertices[vertexIndex + 3].x = tempVertices[RegionAttachment.X3]; vertices[vertexIndex + 3].y = tempVertices[RegionAttachment.Y3]; vertices[vertexIndex + 3].z = z; // Eugene - added if (overrideVertexColor) { color = vertexColor; colors[vertexIndex] = color; colors[vertexIndex + 1] = color; colors[vertexIndex + 2] = color; colors[vertexIndex + 3] = color; } else { color.a = (byte)(a * slot.a * regionAttachment.a); color.r = (byte)(r * slot.r * regionAttachment.r * color.a); color.g = (byte)(g * slot.g * regionAttachment.g * color.a); color.b = (byte)(b * slot.b * regionAttachment.b * color.a); if (slot.data.blendMode == BlendMode.additive) { color.a = 0; } colors[vertexIndex] = color; colors[vertexIndex + 1] = color; colors[vertexIndex + 2] = color; colors[vertexIndex + 3] = color; } float[] regionUVs = regionAttachment.uvs; uvs[vertexIndex].x = regionUVs[RegionAttachment.X1]; uvs[vertexIndex].y = regionUVs[RegionAttachment.Y1]; uvs[vertexIndex + 1].x = regionUVs[RegionAttachment.X4]; uvs[vertexIndex + 1].y = regionUVs[RegionAttachment.Y4]; uvs[vertexIndex + 2].x = regionUVs[RegionAttachment.X2]; uvs[vertexIndex + 2].y = regionUVs[RegionAttachment.Y2]; uvs[vertexIndex + 3].x = regionUVs[RegionAttachment.X3]; uvs[vertexIndex + 3].y = regionUVs[RegionAttachment.Y3]; // Calculate min/max X if (tempVertices[RegionAttachment.X1] < meshBoundsMin.x) { meshBoundsMin.x = tempVertices[RegionAttachment.X1]; } else if (tempVertices[RegionAttachment.X1] > meshBoundsMax.x) { meshBoundsMax.x = tempVertices[RegionAttachment.X1]; } if (tempVertices[RegionAttachment.X2] < meshBoundsMin.x) { meshBoundsMin.x = tempVertices[RegionAttachment.X2]; } else if (tempVertices[RegionAttachment.X2] > meshBoundsMax.x) { meshBoundsMax.x = tempVertices[RegionAttachment.X2]; } if (tempVertices[RegionAttachment.X3] < meshBoundsMin.x) { meshBoundsMin.x = tempVertices[RegionAttachment.X3]; } else if (tempVertices[RegionAttachment.X3] > meshBoundsMax.x) { meshBoundsMax.x = tempVertices[RegionAttachment.X3]; } if (tempVertices[RegionAttachment.X4] < meshBoundsMin.x) { meshBoundsMin.x = tempVertices[RegionAttachment.X4]; } else if (tempVertices[RegionAttachment.X4] > meshBoundsMax.x) { meshBoundsMax.x = tempVertices[RegionAttachment.X4]; } // Calculate min/max Y if (tempVertices[RegionAttachment.Y1] < meshBoundsMin.y) { meshBoundsMin.y = tempVertices[RegionAttachment.Y1]; } else if (tempVertices[RegionAttachment.Y1] > meshBoundsMax.y) { meshBoundsMax.y = tempVertices[RegionAttachment.Y1]; } if (tempVertices[RegionAttachment.Y2] < meshBoundsMin.y) { meshBoundsMin.y = tempVertices[RegionAttachment.Y2]; } else if (tempVertices[RegionAttachment.Y2] > meshBoundsMax.y) { meshBoundsMax.y = tempVertices[RegionAttachment.Y2]; } if (tempVertices[RegionAttachment.Y3] < meshBoundsMin.y) { meshBoundsMin.y = tempVertices[RegionAttachment.Y3]; } else if (tempVertices[RegionAttachment.Y3] > meshBoundsMax.y) { meshBoundsMax.y = tempVertices[RegionAttachment.Y3]; } if (tempVertices[RegionAttachment.Y4] < meshBoundsMin.y) { meshBoundsMin.y = tempVertices[RegionAttachment.Y4]; } else if (tempVertices[RegionAttachment.Y4] > meshBoundsMax.y) { meshBoundsMax.y = tempVertices[RegionAttachment.Y4]; } vertexIndex += 4; } else { if (!renderMeshes) { continue; } MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { int meshVertexCount = meshAttachment.vertices.Length; if (tempVertices.Length < meshVertexCount) { this.tempVertices = tempVertices = new float[meshVertexCount]; } meshAttachment.ComputeWorldVertices(slot, tempVertices); // Eugene - added if (overrideVertexColor) { color = vertexColor; } else { color.a = (byte)(a * slot.a * meshAttachment.a); color.r = (byte)(r * slot.r * meshAttachment.r * color.a); color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.b = (byte)(b * slot.b * meshAttachment.b * color.a); if (slot.data.blendMode == BlendMode.additive) { color.a = 0; } } float[] meshUVs = meshAttachment.uvs; float z = i * zSpacing; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { vertices[vertexIndex].x = tempVertices[ii]; vertices[vertexIndex].y = tempVertices[ii + 1]; vertices[vertexIndex].z = z; colors[vertexIndex] = color; uvs[vertexIndex].x = meshUVs[ii]; uvs[vertexIndex].y = meshUVs[ii + 1]; if (tempVertices[ii] < meshBoundsMin.x) { meshBoundsMin.x = tempVertices[ii]; } else if (tempVertices[ii] > meshBoundsMax.x) { meshBoundsMax.x = tempVertices[ii]; } if (tempVertices[ii + 1] < meshBoundsMin.y) { meshBoundsMin.y = tempVertices[ii + 1]; } else if (tempVertices[ii + 1] > meshBoundsMax.y) { meshBoundsMax.y = tempVertices[ii + 1]; } } } else { SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment; if (skinnedMeshAttachment != null) { int meshVertexCount = skinnedMeshAttachment.uvs.Length; if (tempVertices.Length < meshVertexCount) { this.tempVertices = tempVertices = new float[meshVertexCount]; } skinnedMeshAttachment.ComputeWorldVertices(slot, tempVertices); // Eugene - added if (overrideVertexColor) { color = vertexColor; } else { color.a = (byte)(a * slot.a * skinnedMeshAttachment.a); color.r = (byte)(r * slot.r * skinnedMeshAttachment.r * color.a); color.g = (byte)(g * slot.g * skinnedMeshAttachment.g * color.a); color.b = (byte)(b * slot.b * skinnedMeshAttachment.b * color.a); if (slot.data.blendMode == BlendMode.additive) { color.a = 0; } } float[] meshUVs = skinnedMeshAttachment.uvs; float z = i * zSpacing; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { vertices[vertexIndex].x = tempVertices[ii]; vertices[vertexIndex].y = tempVertices[ii + 1]; vertices[vertexIndex].z = z; colors[vertexIndex] = color; uvs[vertexIndex].x = meshUVs[ii]; uvs[vertexIndex].y = meshUVs[ii + 1]; if (tempVertices[ii] < meshBoundsMin.x) { meshBoundsMin.x = tempVertices[ii]; } else if (tempVertices[ii] > meshBoundsMax.x) { meshBoundsMax.x = tempVertices[ii]; } if (tempVertices[ii + 1] < meshBoundsMin.y) { meshBoundsMin.y = tempVertices[ii + 1]; } else if (tempVertices[ii + 1] > meshBoundsMax.y) { meshBoundsMax.y = tempVertices[ii + 1]; } } } } } } // Double buffer mesh. Mesh mesh = useMesh1 ? mesh1 : mesh2; meshFilter.sharedMesh = mesh; mesh.vertices = vertices; mesh.colors32 = colors; mesh.uv = uvs; // tsteil - added UV2 stuff if (setupUv2) { float minX = 1f; float minY = 1f; float maxX = 0f; float maxY = 0f; float sizeX = 0f; float sizeY = 0f; // go through our vertices and find the min and max so we can normalize the UVs against it for (int i = 0; i < vertexCount; ++i) { var x = vertices[i].x; var y = vertices[i].y; if (x < minX) { minX = x; } else if (x > maxX) { maxX = x; } if (y < minY) { minY = y; } else if (y > maxY) { maxY = y; } } sizeX = maxX - minX; sizeY = maxY - minY; // now set the uvs2 for (int i = 0; i < vertexCount; ++i) { uvs2[i].x = (vertices[i].x - minX) / sizeX; uvs2[i].y = (vertices[i].y - minY) / sizeY; } mesh.uv2 = uvs2; } if (mustUpdateMeshStructure) { int submeshCount = submeshMatCount; mesh.subMeshCount = submeshCount; for (int i = 0; i < submeshCount; ++i) { mesh.SetTriangles(submeshes.Items[i].triangles, i); } } // tsteil: if we're not rendering, we dont need to calculate the bounds (this fixes the crazy AABB math errors) if (noRender == false) { Vector3 meshBoundsExtents = meshBoundsMax - meshBoundsMin; Vector3 meshBoundsCenter = meshBoundsMin + meshBoundsExtents * 0.5f; mesh.bounds = new Bounds(meshBoundsCenter, meshBoundsExtents); } if (newTriangles && calculateNormals) { Vector3[] normals = new Vector3[vertexCount]; Vector3 normal = new Vector3(0, 0, -1); for (int i = 0; i < vertexCount; i++) { normals[i] = normal; } (useMesh1 ? mesh2 : mesh1).vertices = vertices; // Set other mesh vertices. mesh1.normals = normals; mesh2.normals = normals; if (calculateTangents) { Vector4[] tangents = new Vector4[vertexCount]; Vector3 tangent = new Vector3(0, 0, 1); for (int i = 0; i < vertexCount; i++) { tangents[i] = tangent; } mesh1.tangents = tangents; mesh2.tangents = tangents; } } // Update previous state ExposedList <int> attachmentsTriangleCountCurrentMesh; ExposedList <bool> attachmentsFlipStateCurrentMesh; ExposedList <LastState.AddSubmeshArguments> addSubmeshArgumentsCurrentMesh; if (useMesh1) { attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh1; addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh1; attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh1; lastState.immutableTrianglesMesh1 = immutableTriangles; } else { attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh2; addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh2; attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh2; lastState.immutableTrianglesMesh2 = immutableTriangles; } attachmentsTriangleCountCurrentMesh.GrowIfNeeded(attachmentsTriangleCountTemp.Capacity); attachmentsTriangleCountCurrentMesh.Count = attachmentsTriangleCountTemp.Count; attachmentsTriangleCountTemp.CopyTo(attachmentsTriangleCountCurrentMesh.Items, 0); attachmentsFlipStateCurrentMesh.GrowIfNeeded(attachmentsFlipStateTemp.Capacity); attachmentsFlipStateCurrentMesh.Count = attachmentsFlipStateTemp.Count; attachmentsFlipStateTemp.CopyTo(attachmentsFlipStateCurrentMesh.Items, 0); addSubmeshArgumentsCurrentMesh.GrowIfNeeded(addSubmeshArgumentsTemp.Count); addSubmeshArgumentsCurrentMesh.Count = addSubmeshArgumentsTemp.Count; addSubmeshArgumentsTemp.CopyTo(addSubmeshArgumentsCurrentMesh.Items); if (submeshRenderers.Length > 0) { for (int i = 0; i < submeshRenderers.Length; i++) { SkeletonUtilitySubmeshRenderer submeshRenderer = submeshRenderers[i]; if (submeshRenderer.submeshIndex < sharedMaterials.Length) { submeshRenderer.SetMesh(meshRenderer, useMesh1 ? mesh1 : mesh2, sharedMaterials[submeshRenderer.submeshIndex]); } else { submeshRenderer.GetComponent <Renderer>().enabled = false; } } } useMesh1 = !useMesh1; }
protected override void Draw() { defaultBlendState = PremultipliedAlpha ? BlendState.AlphaBlend : BlendState.NonPremultiplied; float[] vertices = this.vertices; List <Slot> drawOrder = Skeleton.DrawOrder; float x = Skeleton.X, y = Skeleton.Y; CCColor3B color3b = Color; float skeletonR = color3b.R / 255f; float skeletonG = color3b.G / 255f; float skeletonB = color3b.B / 255f; float skeletonA = Opacity / 255f; batcher.BlendState = defaultBlendState; batcher.Begin(); for (int i = 0, n = drawOrder.Count; i < n; i++) { Slot slot = drawOrder[i]; Attachment attachment = slot.Attachment; if (attachment is RegionAttachment) { RegionAttachment regionAttachment = (RegionAttachment)attachment; BlendState blend = slot.Data.AdditiveBlending ? BlendState.Additive : defaultBlendState; //batcher.BlendState = blend; if (CCDrawManager.GraphicsDevice.BlendState != blend) { batcher.End(); batcher.BlendState = blend; batcher.Begin(); } MeshItem item = batcher.NextItem(4, 6); item.triangles = quadTriangles; VertexPositionColorTexture[] itemVertices = item.vertices; AtlasRegion region = (AtlasRegion)regionAttachment.RendererObject; item.texture = (Texture2D)region.page.rendererObject; Color color; float a = skeletonA * slot.A * regionAttachment.A; if (PremultipliedAlpha) { color = new Color( skeletonR * slot.R * regionAttachment.R * a, skeletonG * slot.G * regionAttachment.G * a, skeletonB * slot.B * regionAttachment.B * a, a); } else { color = new Color( skeletonR * slot.R * regionAttachment.R, skeletonG * slot.G * regionAttachment.G, skeletonB * slot.B * regionAttachment.B, a); } itemVertices[TL].Color = color; itemVertices[BL].Color = color; itemVertices[BR].Color = color; itemVertices[TR].Color = color; regionAttachment.ComputeWorldVertices(x, y, slot.Bone, vertices); itemVertices[TL].Position.X = vertices[RegionAttachment.X1]; itemVertices[TL].Position.Y = vertices[RegionAttachment.Y1]; itemVertices[TL].Position.Z = 0; itemVertices[BL].Position.X = vertices[RegionAttachment.X2]; itemVertices[BL].Position.Y = vertices[RegionAttachment.Y2]; itemVertices[BL].Position.Z = 0; itemVertices[BR].Position.X = vertices[RegionAttachment.X3]; itemVertices[BR].Position.Y = vertices[RegionAttachment.Y3]; itemVertices[BR].Position.Z = 0; itemVertices[TR].Position.X = vertices[RegionAttachment.X4]; itemVertices[TR].Position.Y = vertices[RegionAttachment.Y4]; itemVertices[TR].Position.Z = 0; float[] uvs = regionAttachment.UVs; itemVertices[TL].TextureCoordinate.X = uvs[RegionAttachment.X1]; itemVertices[TL].TextureCoordinate.Y = uvs[RegionAttachment.Y1]; itemVertices[BL].TextureCoordinate.X = uvs[RegionAttachment.X2]; itemVertices[BL].TextureCoordinate.Y = uvs[RegionAttachment.Y2]; itemVertices[BR].TextureCoordinate.X = uvs[RegionAttachment.X3]; itemVertices[BR].TextureCoordinate.Y = uvs[RegionAttachment.Y3]; itemVertices[TR].TextureCoordinate.X = uvs[RegionAttachment.X4]; itemVertices[TR].TextureCoordinate.Y = uvs[RegionAttachment.Y4]; } else if (attachment is MeshAttachment) { MeshAttachment mesh = (MeshAttachment)attachment; int vertexCount = mesh.Vertices.Length; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; } mesh.ComputeWorldVertices(x, y, slot, vertices); int[] triangles = mesh.Triangles; MeshItem item = batcher.NextItem(vertexCount, triangles.Length); item.triangles = triangles; AtlasRegion region = (AtlasRegion)mesh.RendererObject; item.texture = (Texture2D)region.page.rendererObject; Color color; float a = skeletonA * slot.A * mesh.A; if (PremultipliedAlpha) { color = new Color( skeletonR * slot.R * mesh.R * a, skeletonG * slot.G * mesh.G * a, skeletonB * slot.B * mesh.B * a, a); } else { color = new Color( skeletonR * slot.R * mesh.R, skeletonG * slot.G * mesh.G, skeletonB * slot.B * mesh.B, a); } float[] uvs = mesh.UVs; VertexPositionColorTexture[] itemVertices = item.vertices; for (int ii = 0, v = 0; v < vertexCount; ii++, v += 2) { itemVertices[ii].Color = color; itemVertices[ii].Position.X = vertices[v]; itemVertices[ii].Position.Y = vertices[v + 1]; itemVertices[ii].Position.Z = 0; itemVertices[ii].TextureCoordinate.X = uvs[v]; itemVertices[ii].TextureCoordinate.Y = uvs[v + 1]; } } else if (attachment is SkinnedMeshAttachment) { SkinnedMeshAttachment mesh = (SkinnedMeshAttachment)attachment; int vertexCount = mesh.UVs.Length; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; } mesh.ComputeWorldVertices(x, y, slot, vertices); int[] triangles = mesh.Triangles; MeshItem item = batcher.NextItem(vertexCount, triangles.Length); item.triangles = triangles; AtlasRegion region = (AtlasRegion)mesh.RendererObject; item.texture = (Texture2D)region.page.rendererObject; Color color; float a = skeletonA * slot.A * mesh.A; if (PremultipliedAlpha) { color = new Color( skeletonR * slot.R * mesh.R * a, skeletonG * slot.G * mesh.G * a, skeletonB * slot.B * mesh.B * a, a); } else { color = new Color( skeletonR * slot.R * mesh.R, skeletonG * slot.G * mesh.G, skeletonB * slot.B * mesh.B, a); } float[] uvs = mesh.UVs; VertexPositionColorTexture[] itemVertices = item.vertices; for (int ii = 0, v = 0; v < vertexCount; ii++, v += 2) { itemVertices[ii].Color = color; itemVertices[ii].Position.X = vertices[v]; itemVertices[ii].Position.Y = vertices[v + 1]; itemVertices[ii].Position.Z = 0; itemVertices[ii].TextureCoordinate.X = uvs[v]; itemVertices[ii].TextureCoordinate.Y = uvs[v + 1]; } } } batcher.End(); if (DebugBones || DebugSlots) { if (DebugSlots) { for (int i = 0; i < Skeleton.Slots.Count; ++i) { var slot = Skeleton.Slots[i]; if (slot.Attachment == null) { continue; } var verticesCount = 0; var worldVertices = new float[1000]; // Max number of vertices per mesh. if (slot.Attachment is RegionAttachment) { var attachment = (RegionAttachment)slot.Attachment; attachment.ComputeWorldVertices(Skeleton.X, Skeleton.Y, slot.bone, worldVertices); verticesCount = 8; } else if (slot.Attachment is MeshAttachment) { var mesh = (MeshAttachment)slot.Attachment; mesh.ComputeWorldVertices(Skeleton.X, Skeleton.Y, slot, worldVertices); verticesCount = mesh.Vertices.Length; } else if (slot.Attachment is SkinnedMeshAttachment) { var mesh = (SkinnedMeshAttachment)slot.Attachment; mesh.ComputeWorldVertices(Skeleton.X, Skeleton.Y, slot, worldVertices); verticesCount = mesh.UVs.Length; } else { continue; } CCPoint[] slotVertices = new CCPoint[verticesCount / 2]; for (int ii = 0, si = 0; ii < verticesCount; ii += 2, si++) { slotVertices[si].X = worldVertices[ii] * ScaleX; slotVertices[si].Y = worldVertices[ii + 1] * ScaleY; } CCDrawingPrimitives.Begin(); CCDrawingPrimitives.DrawPoly(slotVertices, verticesCount / 2, true, DebugSlotColor); CCDrawingPrimitives.End(); } } if (DebugBones) { // Bone lengths. for (int i = 0; i < Skeleton.Bones.Count; i++) { Bone bone = Skeleton.Bones[i]; x = bone.Data.Length * bone.M00 + bone.WorldX; y = bone.Data.Length * bone.M10 + bone.WorldY; CCDrawingPrimitives.Begin(); CCDrawingPrimitives.DrawLine(new CCPoint(bone.WorldX, bone.WorldY), new CCPoint(x, y), DebugJointColor); CCDrawingPrimitives.End(); } // Bone origins. for (int i = 0; i < Skeleton.Bones.Count; i++) { Bone bone = Skeleton.Bones[i]; CCDrawingPrimitives.Begin(); CCDrawingPrimitives.DrawPoint(new CCPoint(bone.WorldX, bone.WorldY), 4, DebugBoneColor); CCDrawingPrimitives.End(); } } } }
public void Draw(OpenGL gl, Skeleton skeleton) { if (skeleton == null) { return; } var drawOrder = skeleton.DrawOrder; var drawOrderItems = skeleton.DrawOrder.Items; float skeletonR = skeleton.R, skeletonG = skeleton.G, skeletonB = skeleton.B, skeletonA = skeleton.A; for (int i = 0, n = drawOrder.Count; i < n; i++) { float[] vertices = this.vertices; Slot slot = drawOrderItems[i]; Attachment attachment = slot.Attachment; if (attachment is RegionAttachment) { RegionAttachment regionAttachment = (RegionAttachment)attachment; MeshItem item = batcher.NextItem(4, 6); item.triangles = quadTriangles; VertexPositionColorTexture[] itemVertices = item.vertices; AtlasRegion region = (AtlasRegion)regionAttachment.RendererObject; item.texture = (uint)region.page.rendererObject; Color color; float a = skeletonA * slot.A * regionAttachment.A; if (premultipliedAlpha) { color = new Color( skeletonR * slot.R * regionAttachment.R * a, skeletonG * slot.G * regionAttachment.G * a, skeletonB * slot.B * regionAttachment.B * a, a); } else { color = new Color( skeletonR * slot.R * regionAttachment.R, skeletonG * slot.G * regionAttachment.G, skeletonB * slot.B * regionAttachment.B, a); } itemVertices[TL].color = color; itemVertices[BL].color = color; itemVertices[BR].color = color; itemVertices[TR].color = color; regionAttachment.ComputeWorldVertices(slot.Bone, vertices); itemVertices[TL].position = new Vector2(vertices[RegionAttachment.X1], vertices[RegionAttachment.Y1]); itemVertices[BL].position = new Vector2(vertices[RegionAttachment.X2], vertices[RegionAttachment.Y2]); itemVertices[BR].position = new Vector2(vertices[RegionAttachment.X3], vertices[RegionAttachment.Y3]); itemVertices[TR].position = new Vector2(vertices[RegionAttachment.X4], vertices[RegionAttachment.Y4]); float[] uvs = regionAttachment.UVs; itemVertices[TL].textureCoordinate = new Vector2(uvs[RegionAttachment.X1], uvs[RegionAttachment.Y1]); itemVertices[BL].textureCoordinate = new Vector2(uvs[RegionAttachment.X2], uvs[RegionAttachment.Y2]); itemVertices[BR].textureCoordinate = new Vector2(uvs[RegionAttachment.X3], uvs[RegionAttachment.Y3]); itemVertices[TR].textureCoordinate = new Vector2(uvs[RegionAttachment.X4], uvs[RegionAttachment.Y4]); } else if (attachment is MeshAttachment) { MeshAttachment mesh = (MeshAttachment)attachment; int vertexCount = mesh.WorldVerticesLength; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; } mesh.ComputeWorldVertices(slot, vertices); int[] triangles = mesh.Triangles; MeshItem item = batcher.NextItem(vertexCount, triangles.Length); item.triangles = triangles; AtlasRegion region = (AtlasRegion)mesh.RendererObject; item.texture = (uint)region.page.rendererObject; Color color; float a = skeletonA * slot.A * mesh.A; if (premultipliedAlpha) { color = new Color( skeletonR * slot.R * mesh.R * a, skeletonG * slot.G * mesh.G * a, skeletonB * slot.B * mesh.B * a, a); } else { color = new Color( skeletonR * slot.R * mesh.R, skeletonG * slot.G * mesh.G, skeletonB * slot.B * mesh.B, a); } float[] uvs = mesh.UVs; VertexPositionColorTexture[] itemVertices = item.vertices; for (int ii = 0, v = 0; v < vertexCount; ii++, v += 2) { itemVertices[ii].color = color; itemVertices[ii].position = new Vector2(vertices[v], vertices[v + 1]); itemVertices[ii].textureCoordinate = new Vector2(uvs[v], uvs[v + 1]); } } } batcher.Draw(gl); }
/// <summary> /// Helper method that draws debug lines. /// </summary> /// <remarks> /// This method will only work on debug mode and if RenderManager.DebugLines /> /// is set to <c>true</c>. /// </remarks> protected override void DrawDebugLines() { base.DrawDebugLines(); var platform = WaveServices.Platform; Vector2 start = new Vector2(); Vector2 end = new Vector2(); Color color = Color.Red; // Draw bones if ((this.ActualDebugMode & DebugMode.Bones) == DebugMode.Bones) { foreach (var bone in this.SkeletalAnimation.Skeleton.Bones) { if (bone.Parent != null) { start.X = bone.WorldX; start.Y = -bone.WorldY; end.X = (bone.Data.Length * bone.M00) + bone.WorldX; end.Y = -((bone.Data.Length * bone.M10) + bone.WorldY); Vector2.Transform(ref start, ref this.localWorld, out start); Vector2.Transform(ref end, ref this.localWorld, out end); RenderManager.LineBatch2D.DrawLine(ref start, ref end, ref color); } } } // Draw quads if ((this.ActualDebugMode & DebugMode.Quads) == DebugMode.Quads) { color = Color.Yellow; for (int i = 0; i < this.drawOrder.Count; i++) { Slot slot = this.drawOrder[i]; Attachment attachment = slot.Attachment; if (attachment is RegionAttachment) { float[] spineVertices = new float[8]; RegionAttachment mesh = (RegionAttachment)attachment; mesh.ComputeWorldVertices(0, 0, slot.Bone, spineVertices); // Edge1 start.X = spineVertices[RegionAttachment.X1]; start.Y = -spineVertices[RegionAttachment.Y1]; end.X = spineVertices[RegionAttachment.X2]; end.Y = -spineVertices[RegionAttachment.Y2]; Vector2.Transform(ref start, ref this.localWorld, out start); Vector2.Transform(ref end, ref this.localWorld, out end); RenderManager.LineBatch2D.DrawLine(ref start, ref end, ref color); // Edge2 start.X = spineVertices[RegionAttachment.X2]; start.Y = -spineVertices[RegionAttachment.Y2]; end.X = spineVertices[RegionAttachment.X3]; end.Y = -spineVertices[RegionAttachment.Y3]; Vector2.Transform(ref start, ref this.localWorld, out start); Vector2.Transform(ref end, ref this.localWorld, out end); RenderManager.LineBatch2D.DrawLine(ref start, ref end, ref color); // Edge3 start.X = spineVertices[RegionAttachment.X3]; start.Y = -spineVertices[RegionAttachment.Y3]; end.X = spineVertices[RegionAttachment.X4]; end.Y = -spineVertices[RegionAttachment.Y4]; Vector2.Transform(ref start, ref this.localWorld, out start); Vector2.Transform(ref end, ref this.localWorld, out end); RenderManager.LineBatch2D.DrawLine(ref start, ref end, ref color); // Edge4 start.X = spineVertices[RegionAttachment.X4]; start.Y = -spineVertices[RegionAttachment.Y4]; end.X = spineVertices[RegionAttachment.X1]; end.Y = -spineVertices[RegionAttachment.Y1]; Vector2.Transform(ref start, ref this.localWorld, out start); Vector2.Transform(ref end, ref this.localWorld, out end); RenderManager.LineBatch2D.DrawLine(ref start, ref end, ref color); } else if (attachment is MeshAttachment) { MeshAttachment mesh = (MeshAttachment)attachment; int vertexCount = mesh.Vertices.Length; float[] spineVertices = new float[vertexCount]; mesh.ComputeWorldVertices(0, 0, slot, spineVertices); for (int j = 0; j < vertexCount; j += 2) { start.X = spineVertices[j]; start.Y = -spineVertices[j + 1]; if (j < vertexCount - 2) { end.X = spineVertices[j + 2]; end.Y = -spineVertices[j + 3]; } else { end.X = spineVertices[0]; end.Y = -spineVertices[1]; } Vector2.Transform(ref start, ref this.localWorld, out start); Vector2.Transform(ref end, ref this.localWorld, out end); RenderManager.LineBatch2D.DrawLine(ref start, ref end, ref color); } } else if (attachment is SkinnedMeshAttachment) { SkinnedMeshAttachment mesh = (SkinnedMeshAttachment)attachment; int vertexCount = mesh.UVs.Length; float[] spineVertices = new float[vertexCount]; mesh.ComputeWorldVertices(0, 0, slot, spineVertices); for (int j = 0; j < vertexCount; j += 2) { start.X = spineVertices[j]; start.Y = -spineVertices[j + 1]; if (j < vertexCount - 2) { end.X = spineVertices[j + 2]; end.Y = -spineVertices[j + 3]; } else { end.X = spineVertices[0]; end.Y = -spineVertices[1]; } Vector2.Transform(ref start, ref this.localWorld, out start); Vector2.Transform(ref end, ref this.localWorld, out end); RenderManager.LineBatch2D.DrawLine(ref start, ref end, ref color); } } } } }
public virtual void LateUpdate() { if (!valid) { return; } // Exit early if there is nothing to render if (!meshRenderer.enabled && submeshRenderers.Length == 0) { return; } // Count vertices and submesh triangles. int vertexCount = 0; int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0; Material lastMaterial = null; ExposedList <Slot> drawOrder = skeleton.drawOrder; int drawOrderCount = drawOrder.Count; int submeshSeparatorSlotsCount = submeshSeparatorSlots.Count; bool renderMeshes = this.renderMeshes; // Clear last state of attachments and submeshes ExposedList <int> attachmentsTriangleCountTemp = lastState.attachmentsTriangleCountTemp; attachmentsTriangleCountTemp.GrowIfNeeded(drawOrderCount); attachmentsTriangleCountTemp.Count = drawOrderCount; ExposedList <bool> attachmentsFlipStateTemp = lastState.attachmentsFlipStateTemp; attachmentsFlipStateTemp.GrowIfNeeded(drawOrderCount); attachmentsFlipStateTemp.Count = drawOrderCount; ExposedList <LastState.AddSubmeshArguments> addSubmeshArgumentsTemp = lastState.addSubmeshArgumentsTemp; addSubmeshArgumentsTemp.Clear(false); for (int i = 0; i < drawOrderCount; i++) { Slot slot = drawOrder.Items[i]; Bone bone = slot.bone; Attachment attachment = slot.attachment; object rendererObject; int attachmentVertexCount, attachmentTriangleCount; bool worldScaleXIsPositive = bone.worldScaleX >= 0f; bool worldScaleYIsPositive = bone.worldScaleY >= 0f; bool worldScaleIsSameSigns = (worldScaleXIsPositive && worldScaleYIsPositive) || (!worldScaleXIsPositive && !worldScaleYIsPositive); bool flip = frontFacing && ((bone.worldFlipX != bone.worldFlipY) == worldScaleIsSameSigns); attachmentsFlipStateTemp.Items[i] = flip; attachmentsTriangleCountTemp.Items[i] = -1; RegionAttachment regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { rendererObject = regionAttachment.RendererObject; attachmentVertexCount = 4; attachmentTriangleCount = 6; } else { if (!renderMeshes) { continue; } MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { rendererObject = meshAttachment.RendererObject; attachmentVertexCount = meshAttachment.vertices.Length >> 1; attachmentTriangleCount = meshAttachment.triangles.Length; } else { SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment; if (skinnedMeshAttachment != null) { rendererObject = skinnedMeshAttachment.RendererObject; attachmentVertexCount = skinnedMeshAttachment.uvs.Length >> 1; attachmentTriangleCount = skinnedMeshAttachment.triangles.Length; } else { continue; } } } // Populate submesh when material changes. #if !SPINE_TK2D Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject; #else Material material = (rendererObject.GetType() == typeof(Material)) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject; #endif if ((lastMaterial != null && lastMaterial.GetInstanceID() != material.GetInstanceID()) || (submeshSeparatorSlotsCount > 0 && submeshSeparatorSlots.Contains(slot))) { addSubmeshArgumentsTemp.Add( new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false) ); submeshTriangleCount = 0; submeshFirstVertex = vertexCount; submeshStartSlotIndex = i; } lastMaterial = material; submeshTriangleCount += attachmentTriangleCount; vertexCount += attachmentVertexCount; attachmentsTriangleCountTemp.Items[i] = attachmentTriangleCount; } addSubmeshArgumentsTemp.Add( new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true) ); bool mustUpdateMeshStructure = CheckIfMustUpdateMeshStructure(attachmentsTriangleCountTemp, attachmentsFlipStateTemp, addSubmeshArgumentsTemp); if (mustUpdateMeshStructure) { submeshMaterials.Clear(); for (int i = 0, n = addSubmeshArgumentsTemp.Count; i < n; i++) { LastState.AddSubmeshArguments arguments = addSubmeshArgumentsTemp.Items[i]; AddSubmesh( arguments.material, arguments.startSlot, arguments.endSlot, arguments.triangleCount, arguments.firstVertex, arguments.lastSubmesh, attachmentsFlipStateTemp ); } // Set materials. if (submeshMaterials.Count == sharedMaterials.Length) { submeshMaterials.CopyTo(sharedMaterials); } else { sharedMaterials = submeshMaterials.ToArray(); } meshRenderer.sharedMaterials = sharedMaterials; } // Ensure mesh data is the right size. Vector3[] vertices = this.vertices; bool newTriangles = vertexCount > vertices.Length; if (newTriangles) { // Not enough vertices, increase size. this.vertices = vertices = new Vector3[vertexCount]; this.colors = new Color32[vertexCount]; this.uvs = new Vector2[vertexCount]; mesh1.Clear(); mesh2.Clear(); } else { // Too many vertices, zero the extra. Vector3 zero = Vector3.zero; for (int i = vertexCount, n = lastState.vertexCount; i < n; i++) { vertices[i] = zero; } } lastState.vertexCount = vertexCount; // Setup mesh. float zSpacing = this.zSpacing; float[] tempVertices = this.tempVertices; Vector2[] uvs = this.uvs; Color32[] colors = this.colors; int vertexIndex = 0; Color32 color; float a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b; Vector3 meshBoundsMin; Vector3 meshBoundsMax; if (vertexCount == 0) { meshBoundsMin = new Vector3(0, 0, 0); meshBoundsMax = new Vector3(0, 0, 0); } else { meshBoundsMin.x = int.MaxValue; meshBoundsMin.y = int.MaxValue; meshBoundsMax.x = int.MinValue; meshBoundsMax.y = int.MinValue; if (zSpacing > 0f) { meshBoundsMin.z = 0f; meshBoundsMax.z = zSpacing * (drawOrderCount - 1); } else { meshBoundsMin.z = zSpacing * (drawOrderCount - 1); meshBoundsMax.z = 0f; } int i = 0; do { Slot slot = drawOrder.Items[i]; Attachment attachment = slot.attachment; RegionAttachment regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { regionAttachment.ComputeWorldVertices(slot.bone, tempVertices); float z = i * zSpacing; float x1 = tempVertices[RegionAttachment.X1], y1 = tempVertices[RegionAttachment.Y1]; float x2 = tempVertices[RegionAttachment.X2], y2 = tempVertices[RegionAttachment.Y2]; float x3 = tempVertices[RegionAttachment.X3], y3 = tempVertices[RegionAttachment.Y3]; float x4 = tempVertices[RegionAttachment.X4], y4 = tempVertices[RegionAttachment.Y4]; vertices[vertexIndex].x = x1; vertices[vertexIndex].y = y1; vertices[vertexIndex].z = z; vertices[vertexIndex + 1].x = x4; vertices[vertexIndex + 1].y = y4; vertices[vertexIndex + 1].z = z; vertices[vertexIndex + 2].x = x2; vertices[vertexIndex + 2].y = y2; vertices[vertexIndex + 2].z = z; vertices[vertexIndex + 3].x = x3; vertices[vertexIndex + 3].y = y3; vertices[vertexIndex + 3].z = z; color.a = (byte)(a * slot.a * regionAttachment.a); color.r = (byte)(r * slot.r * regionAttachment.r * color.a); color.g = (byte)(g * slot.g * regionAttachment.g * color.a); color.b = (byte)(b * slot.b * regionAttachment.b * color.a); if (slot.data.blendMode == BlendMode.additive) { color.a = 0; } colors[vertexIndex] = color; colors[vertexIndex + 1] = color; colors[vertexIndex + 2] = color; colors[vertexIndex + 3] = color; float[] regionUVs = regionAttachment.uvs; uvs[vertexIndex].x = regionUVs[RegionAttachment.X1]; uvs[vertexIndex].y = regionUVs[RegionAttachment.Y1]; uvs[vertexIndex + 1].x = regionUVs[RegionAttachment.X4]; uvs[vertexIndex + 1].y = regionUVs[RegionAttachment.Y4]; uvs[vertexIndex + 2].x = regionUVs[RegionAttachment.X2]; uvs[vertexIndex + 2].y = regionUVs[RegionAttachment.Y2]; uvs[vertexIndex + 3].x = regionUVs[RegionAttachment.X3]; uvs[vertexIndex + 3].y = regionUVs[RegionAttachment.Y3]; // Calculate min/max X if (x1 < meshBoundsMin.x) { meshBoundsMin.x = x1; } else if (x1 > meshBoundsMax.x) { meshBoundsMax.x = x1; } if (x2 < meshBoundsMin.x) { meshBoundsMin.x = x2; } else if (x2 > meshBoundsMax.x) { meshBoundsMax.x = x2; } if (x3 < meshBoundsMin.x) { meshBoundsMin.x = x3; } else if (x3 > meshBoundsMax.x) { meshBoundsMax.x = x3; } if (x4 < meshBoundsMin.x) { meshBoundsMin.x = x4; } else if (x4 > meshBoundsMax.x) { meshBoundsMax.x = x4; } // Calculate min/max Y if (y1 < meshBoundsMin.y) { meshBoundsMin.y = y1; } else if (y1 > meshBoundsMax.y) { meshBoundsMax.y = y1; } if (y2 < meshBoundsMin.y) { meshBoundsMin.y = y2; } else if (y2 > meshBoundsMax.y) { meshBoundsMax.y = y2; } if (y3 < meshBoundsMin.y) { meshBoundsMin.y = y3; } else if (y3 > meshBoundsMax.y) { meshBoundsMax.y = y3; } if (y4 < meshBoundsMin.y) { meshBoundsMin.y = y4; } else if (y4 > meshBoundsMax.y) { meshBoundsMax.y = y4; } vertexIndex += 4; } else { if (!renderMeshes) { continue; } MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { int meshVertexCount = meshAttachment.vertices.Length; if (tempVertices.Length < meshVertexCount) { this.tempVertices = tempVertices = new float[meshVertexCount]; } meshAttachment.ComputeWorldVertices(slot, tempVertices); color.a = (byte)(a * slot.a * meshAttachment.a); color.r = (byte)(r * slot.r * meshAttachment.r * color.a); color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.b = (byte)(b * slot.b * meshAttachment.b * color.a); if (slot.data.blendMode == BlendMode.additive) { color.a = 0; } float[] meshUVs = meshAttachment.uvs; float z = i * zSpacing; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { float x = tempVertices[ii], y = tempVertices[ii + 1]; vertices[vertexIndex].x = x; vertices[vertexIndex].y = y; vertices[vertexIndex].z = z; colors[vertexIndex] = color; uvs[vertexIndex].x = meshUVs[ii]; uvs[vertexIndex].y = meshUVs[ii + 1]; if (x < meshBoundsMin.x) { meshBoundsMin.x = x; } else if (x > meshBoundsMax.x) { meshBoundsMax.x = x; } if (y < meshBoundsMin.y) { meshBoundsMin.y = y; } else if (y > meshBoundsMax.y) { meshBoundsMax.y = y; } } } else { SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment; if (skinnedMeshAttachment != null) { int meshVertexCount = skinnedMeshAttachment.uvs.Length; if (tempVertices.Length < meshVertexCount) { this.tempVertices = tempVertices = new float[meshVertexCount]; } skinnedMeshAttachment.ComputeWorldVertices(slot, tempVertices); color.a = (byte)(a * slot.a * skinnedMeshAttachment.a); color.r = (byte)(r * slot.r * skinnedMeshAttachment.r * color.a); color.g = (byte)(g * slot.g * skinnedMeshAttachment.g * color.a); color.b = (byte)(b * slot.b * skinnedMeshAttachment.b * color.a); if (slot.data.blendMode == BlendMode.additive) { color.a = 0; } float[] meshUVs = skinnedMeshAttachment.uvs; float z = i * zSpacing; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { float x = tempVertices[ii], y = tempVertices[ii + 1]; vertices[vertexIndex].x = x; vertices[vertexIndex].y = y; vertices[vertexIndex].z = z; colors[vertexIndex] = color; uvs[vertexIndex].x = meshUVs[ii]; uvs[vertexIndex].y = meshUVs[ii + 1]; if (x < meshBoundsMin.x) { meshBoundsMin.x = x; } else if (x > meshBoundsMax.x) { meshBoundsMax.x = x; } if (y < meshBoundsMin.y) { meshBoundsMin.y = y; } else if (y > meshBoundsMax.y) { meshBoundsMax.y = y; } } } } } } while (++i < drawOrderCount); } // Double buffer mesh. Mesh mesh = useMesh1 ? mesh1 : mesh2; meshFilter.sharedMesh = mesh; mesh.vertices = vertices; mesh.colors32 = colors; mesh.uv = uvs; if (mustUpdateMeshStructure) { int submeshCount = submeshMaterials.Count; mesh.subMeshCount = submeshCount; for (int i = 0; i < submeshCount; ++i) { mesh.SetTriangles(submeshes.Items[i].triangles, i); } } Vector3 meshBoundsExtents = meshBoundsMax - meshBoundsMin; Vector3 meshBoundsCenter = meshBoundsMin + meshBoundsExtents * 0.5f; mesh.bounds = new Bounds(meshBoundsCenter, meshBoundsExtents); if (newTriangles && calculateNormals) { Vector3[] normals = new Vector3[vertexCount]; Vector3 normal = new Vector3(0, 0, -1); for (int i = 0; i < vertexCount; i++) { normals[i] = normal; } (useMesh1 ? mesh2 : mesh1).vertices = vertices; // Set other mesh vertices. mesh1.normals = normals; mesh2.normals = normals; if (calculateTangents) { Vector4[] tangents = new Vector4[vertexCount]; Vector3 tangent = new Vector3(0, 0, 1); for (int i = 0; i < vertexCount; i++) { tangents[i] = tangent; } mesh1.tangents = tangents; mesh2.tangents = tangents; } } // Update previous state ExposedList <int> attachmentsTriangleCountCurrentMesh; ExposedList <bool> attachmentsFlipStateCurrentMesh; ExposedList <LastState.AddSubmeshArguments> addSubmeshArgumentsCurrentMesh; if (useMesh1) { attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh1; addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh1; attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh1; lastState.immutableTrianglesMesh1 = immutableTriangles; } else { attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh2; addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh2; attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh2; lastState.immutableTrianglesMesh2 = immutableTriangles; } attachmentsTriangleCountCurrentMesh.GrowIfNeeded(attachmentsTriangleCountTemp.Capacity); attachmentsTriangleCountCurrentMesh.Count = attachmentsTriangleCountTemp.Count; attachmentsTriangleCountTemp.CopyTo(attachmentsTriangleCountCurrentMesh.Items, 0); attachmentsFlipStateCurrentMesh.GrowIfNeeded(attachmentsFlipStateTemp.Capacity); attachmentsFlipStateCurrentMesh.Count = attachmentsFlipStateTemp.Count; attachmentsFlipStateTemp.CopyTo(attachmentsFlipStateCurrentMesh.Items, 0); addSubmeshArgumentsCurrentMesh.GrowIfNeeded(addSubmeshArgumentsTemp.Count); addSubmeshArgumentsCurrentMesh.Count = addSubmeshArgumentsTemp.Count; addSubmeshArgumentsTemp.CopyTo(addSubmeshArgumentsCurrentMesh.Items); if (submeshRenderers.Length > 0) { for (int i = 0; i < submeshRenderers.Length; i++) { SkeletonUtilitySubmeshRenderer submeshRenderer = submeshRenderers[i]; if (submeshRenderer.submeshIndex < sharedMaterials.Length) { submeshRenderer.SetMesh(meshRenderer, useMesh1 ? mesh1 : mesh2, sharedMaterials[submeshRenderer.submeshIndex]); } else { submeshRenderer.GetComponent <Renderer>().enabled = false; } } } useMesh1 = !useMesh1; }
public virtual void LateUpdate() { if (!valid) { return; } // Count vertices and submesh triangles. int vertexCount = 0; int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0; Material lastMaterial = null; submeshMaterials.Clear(); List <Slot> drawOrder = skeleton.DrawOrder; int drawOrderCount = drawOrder.Count; bool renderMeshes = this.renderMeshes; for (int i = 0; i < drawOrderCount; i++) { Slot slot = drawOrder[i]; Attachment attachment = slot.attachment; object rendererObject; int attachmentVertexCount, attachmentTriangleCount; if (attachment is RegionAttachment) { rendererObject = ((RegionAttachment)attachment).RendererObject; attachmentVertexCount = 4; attachmentTriangleCount = 6; } else { if (!renderMeshes) { continue; } if (attachment is MeshAttachment) { MeshAttachment meshAttachment = (MeshAttachment)attachment; rendererObject = meshAttachment.RendererObject; attachmentVertexCount = meshAttachment.vertices.Length >> 1; attachmentTriangleCount = meshAttachment.triangles.Length; } else if (attachment is SkinnedMeshAttachment) { SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; rendererObject = meshAttachment.RendererObject; attachmentVertexCount = meshAttachment.uvs.Length >> 1; attachmentTriangleCount = meshAttachment.triangles.Length; } else { continue; } } // Populate submesh when material changes. Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject; if ((lastMaterial != material && lastMaterial != null) || slot.Data.name[0] == '*') { AddSubmesh(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false); submeshTriangleCount = 0; submeshFirstVertex = vertexCount; submeshStartSlotIndex = i; } lastMaterial = material; submeshTriangleCount += attachmentTriangleCount; vertexCount += attachmentVertexCount; } AddSubmesh(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true); // Set materials. if (submeshMaterials.Count == sharedMaterials.Length) { submeshMaterials.CopyTo(sharedMaterials); } else { sharedMaterials = submeshMaterials.ToArray(); } renderer.sharedMaterials = sharedMaterials; // Ensure mesh data is the right size. Vector3[] vertices = this.vertices; bool newTriangles = vertexCount > vertices.Length; if (newTriangles) { // Not enough vertices, increase size. this.vertices = vertices = new Vector3[vertexCount]; this.colors = new Color32[vertexCount]; this.uvs = new Vector2[vertexCount]; mesh1.Clear(); mesh2.Clear(); } else { // Too many vertices, zero the extra. Vector3 zero = Vector3.zero; for (int i = vertexCount, n = lastVertexCount; i < n; i++) { vertices[i] = zero; } } lastVertexCount = vertexCount; // Setup mesh. float[] tempVertices = this.tempVertices; Vector2[] uvs = this.uvs; Color32[] colors = this.colors; int vertexIndex = 0; Color32 color = new Color32(); float zSpacing = this.zSpacing; float a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b; for (int i = 0; i < drawOrderCount; i++) { Slot slot = drawOrder[i]; Attachment attachment = slot.attachment; if (attachment is RegionAttachment) { RegionAttachment regionAttachment = (RegionAttachment)attachment; regionAttachment.ComputeWorldVertices(slot.bone, tempVertices); float z = i * zSpacing; vertices[vertexIndex] = new Vector3(tempVertices[RegionAttachment.X1], tempVertices[RegionAttachment.Y1], z); vertices[vertexIndex + 1] = new Vector3(tempVertices[RegionAttachment.X4], tempVertices[RegionAttachment.Y4], z); vertices[vertexIndex + 2] = new Vector3(tempVertices[RegionAttachment.X2], tempVertices[RegionAttachment.Y2], z); vertices[vertexIndex + 3] = new Vector3(tempVertices[RegionAttachment.X3], tempVertices[RegionAttachment.Y3], z); color.a = (byte)(a * slot.a * regionAttachment.a); color.r = (byte)(r * slot.r * regionAttachment.r * color.a); color.g = (byte)(g * slot.g * regionAttachment.g * color.a); color.b = (byte)(b * slot.b * regionAttachment.b * color.a); if (slot.data.additiveBlending) { color.a = 0; } colors[vertexIndex] = color; colors[vertexIndex + 1] = color; colors[vertexIndex + 2] = color; colors[vertexIndex + 3] = color; float[] regionUVs = regionAttachment.uvs; uvs[vertexIndex] = new Vector2(regionUVs[RegionAttachment.X1], regionUVs[RegionAttachment.Y1]); uvs[vertexIndex + 1] = new Vector2(regionUVs[RegionAttachment.X4], regionUVs[RegionAttachment.Y4]); uvs[vertexIndex + 2] = new Vector2(regionUVs[RegionAttachment.X2], regionUVs[RegionAttachment.Y2]); uvs[vertexIndex + 3] = new Vector2(regionUVs[RegionAttachment.X3], regionUVs[RegionAttachment.Y3]); vertexIndex += 4; } else { if (!renderMeshes) { continue; } if (attachment is MeshAttachment) { MeshAttachment meshAttachment = (MeshAttachment)attachment; int meshVertexCount = meshAttachment.vertices.Length; if (tempVertices.Length < meshVertexCount) { tempVertices = new float[meshVertexCount]; } meshAttachment.ComputeWorldVertices(slot, tempVertices); color.a = (byte)(a * slot.a * meshAttachment.a); color.r = (byte)(r * slot.r * meshAttachment.r * color.a); color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.b = (byte)(b * slot.b * meshAttachment.b * color.a); if (slot.data.additiveBlending) { color.a = 0; } float[] meshUVs = meshAttachment.uvs; float z = i * zSpacing; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z); colors[vertexIndex] = color; uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]); } } else if (attachment is SkinnedMeshAttachment) { SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; int meshVertexCount = meshAttachment.uvs.Length; if (tempVertices.Length < meshVertexCount) { tempVertices = new float[meshVertexCount]; } meshAttachment.ComputeWorldVertices(slot, tempVertices); color.a = (byte)(a * slot.a * meshAttachment.a); color.r = (byte)(r * slot.r * meshAttachment.r * color.a); color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.b = (byte)(b * slot.b * meshAttachment.b * color.a); if (slot.data.additiveBlending) { color.a = 0; } float[] meshUVs = meshAttachment.uvs; float z = i * zSpacing; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z); colors[vertexIndex] = color; uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]); } } } } // Double buffer mesh. Mesh mesh = useMesh1 ? mesh1 : mesh2; meshFilter.sharedMesh = mesh; mesh.vertices = vertices; mesh.colors32 = colors; mesh.uv = uvs; int submeshCount = submeshMaterials.Count; mesh.subMeshCount = submeshCount; for (int i = 0; i < submeshCount; ++i) { mesh.SetTriangles(submeshes[i].triangles, i); } mesh.RecalculateBounds(); if (newTriangles && calculateNormals) { Vector3[] normals = new Vector3[vertexCount]; Vector3 normal = new Vector3(0, 0, -1); for (int i = 0; i < vertexCount; i++) { normals[i] = normal; } (useMesh1 ? mesh2 : mesh1).vertices = vertices; // Set other mesh vertices. mesh1.normals = normals; mesh2.normals = normals; if (calculateTangents) { Vector4[] tangents = new Vector4[vertexCount]; Vector3 tangent = new Vector3(0, 0, 1); for (int i = 0; i < vertexCount; i++) { tangents[i] = tangent; } mesh1.tangents = tangents; mesh2.tangents = tangents; } } useMesh1 = !useMesh1; }
private void InternalDraw(Skeleton pSkeleton, Texture2D[] pTextureArray, float pDepth, float scale, Color pColor) { if (!isBegin) { throw new Exception("Beginn muss vor Draw aufgerufen werden!"); } float[] vertices = this.mSkeletonVertecies; List <Slot> drawOrder = pSkeleton.DrawOrder; float x = pSkeleton.X, y = pSkeleton.Y; int textId = this.mBatch.AddTextures(pTextureArray); for (int i = 0, n = drawOrder.Count; i < n; i++) { Slot slot = drawOrder[i]; Attachment attachment = slot.Attachment; if (attachment is RegionAttachment) { RegionAttachment regionAttachment = (RegionAttachment)attachment; MeshData item = this.mBatch.NextItem(4, 6); item.triangles = quadIndecies; AtlasRegion region = (AtlasRegion)regionAttachment.RendererObject; regionAttachment.ComputeWorldVertices(x, y, slot.Bone, vertices); item.vertices[TL].Position.X = vertices[RegionAttachment.X1]; item.vertices[TL].Position.Y = vertices[RegionAttachment.Y1]; item.vertices[TL].Position.Z = pDepth; // -orderDepth * (n - (i + 1)); item.vertices[BL].Position.X = vertices[RegionAttachment.X2]; item.vertices[BL].Position.Y = vertices[RegionAttachment.Y2]; item.vertices[BL].Position.Z = pDepth;// -orderDepth * (n - (i + 1)); item.vertices[BR].Position.X = vertices[RegionAttachment.X3]; item.vertices[BR].Position.Y = vertices[RegionAttachment.Y3]; item.vertices[BR].Position.Z = pDepth;// -orderDepth * (n - (i + 1)); item.vertices[TR].Position.X = vertices[RegionAttachment.X4]; item.vertices[TR].Position.Y = vertices[RegionAttachment.Y4]; item.vertices[TR].Position.Z = pDepth;// -orderDepth * (n - (i + 1)); float[] uvs = regionAttachment.UVs; item.vertices[TL].TextureCoordinate.X = uvs[RegionAttachment.X1]; item.vertices[TL].TextureCoordinate.Y = uvs[RegionAttachment.Y1]; item.vertices[BL].TextureCoordinate.X = uvs[RegionAttachment.X2]; item.vertices[BL].TextureCoordinate.Y = uvs[RegionAttachment.Y2]; item.vertices[BR].TextureCoordinate.X = uvs[RegionAttachment.X3]; item.vertices[BR].TextureCoordinate.Y = uvs[RegionAttachment.Y3]; item.vertices[TR].TextureCoordinate.X = uvs[RegionAttachment.X4]; item.vertices[TR].TextureCoordinate.Y = uvs[RegionAttachment.Y4]; item.vertices[TL].Color = pColor; item.vertices[BL].Color = pColor; item.vertices[BR].Color = pColor; item.vertices[TR].Color = pColor; item.TextureID = textId; } else if (attachment is MeshAttachment) { MeshAttachment mesh = (MeshAttachment)attachment; int vertexCount = mesh.Vertices.Length; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; } mesh.ComputeWorldVertices(x, y, slot, vertices); int[] triangles = mesh.triangles; MeshData item = mBatch.NextItem(vertexCount, triangles.Length); item.triangles = triangles; item.TextureID = textId; AtlasRegion region = (AtlasRegion)mesh.RendererObject; float[] uvs = mesh.UVs; VertexPositionColorTexture[] itemVertices = item.vertices; for (int ii = 0, v = 0; v < vertexCount; ii++, v += 2) { itemVertices[ii].Position.X = vertices[v]; itemVertices[ii].Position.Y = vertices[v + 1]; itemVertices[ii].Position.Z = pDepth; itemVertices[ii].TextureCoordinate.X = uvs[v]; itemVertices[ii].TextureCoordinate.Y = uvs[v + 1]; itemVertices[ii].Color = pColor; } } else if (attachment is SkinnedMeshAttachment) { SkinnedMeshAttachment mesh = (SkinnedMeshAttachment)attachment; int vertexCount = mesh.UVs.Length; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; } mesh.ComputeWorldVertices(x, y, slot, vertices); int[] triangles = mesh.Triangles; MeshData item = mBatch.NextItem(vertexCount, triangles.Length); item.triangles = triangles; item.TextureID = textId; float[] uvs = mesh.UVs; VertexPositionColorTexture[] itemVertices = item.vertices; for (int ii = 0, v = 0; v < vertexCount; ii++, v += 2) { itemVertices[ii].Position.X = vertices[v]; itemVertices[ii].Position.Y = vertices[v + 1]; itemVertices[ii].Position.Z = 0; itemVertices[ii].TextureCoordinate.X = uvs[v]; itemVertices[ii].TextureCoordinate.Y = uvs[v + 1]; itemVertices[ii].Color = pColor; } } } }