public Mesh GenerateMesh(Skeleton skeleton) { int totalVertexCount = 0; // size of vertex arrays int totalTriangleCount = 0; // size of index array // STEP 1 : GenerateInstruction(). Count verts and tris to determine array sizes. var drawOrderItems = skeleton.drawOrder.Items; int drawOrderCount = skeleton.drawOrder.Count; for (int i = 0; i < drawOrderCount; i++) { Slot slot = drawOrderItems[i]; Attachment attachment = slot.attachment; int attachmentVertexCount, attachmentTriangleCount; var regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { attachmentVertexCount = 4; attachmentTriangleCount = 6; } else { var meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { attachmentVertexCount = meshAttachment.worldVerticesLength >> 1; attachmentTriangleCount = meshAttachment.triangles.Length; } else { continue; } } totalTriangleCount += attachmentTriangleCount; totalVertexCount += attachmentVertexCount; } // STEP 2 : Ensure buffers are the correct size ArraysMeshGenerator.EnsureSize(totalVertexCount, ref this.meshVertices, ref this.meshUVs, ref this.meshColors32); this.triangles = this.triangles ?? new int[totalTriangleCount]; // STEP 3 : Update vertex buffer const float zFauxHalfThickness = 0.01f; // Somehow needs this thickness for bounds to work properly in some cases (eg, Unity UI clipping) Vector3 meshBoundsMin; Vector3 meshBoundsMax; if (totalVertexCount == 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; meshBoundsMin.z = -zFauxHalfThickness * scale; meshBoundsMax.z = zFauxHalfThickness * scale; int vertexIndex = 0; ArraysMeshGenerator.FillVerts(skeleton, 0, drawOrderCount, this.ZSpacing, this.PremultiplyVertexColors, this.meshVertices, this.meshUVs, this.meshColors32, ref vertexIndex, ref this.attachmentVertexBuffer, ref meshBoundsMin, ref meshBoundsMax); // Apply scale to vertices meshBoundsMax.x *= scale; meshBoundsMax.y *= scale; meshBoundsMin.x *= scale; meshBoundsMin.y *= scale; var vertices = this.meshVertices; for (int i = 0; i < totalVertexCount; i++) { Vector3 p = vertices[i]; p.x *= scale; p.y *= scale; vertices[i] = p; } } // Step 4 : Update Triangles buffer ArraysMeshGenerator.FillTriangles(ref this.triangles, skeleton, totalTriangleCount, 0, 0, drawOrderCount, true); // Step 5 : Update Mesh with buffers var mesh = doubleBufferedMesh.GetNextMesh(); mesh.vertices = this.meshVertices; mesh.colors32 = meshColors32; mesh.uv = meshUVs; mesh.bounds = ArraysMeshGenerator.ToBounds(meshBoundsMin, meshBoundsMax); mesh.triangles = triangles; TryAddNormalsTo(mesh, totalVertexCount); if (addTangents) { SolveTangents2DEnsureSize(ref this.meshTangents, ref this.tempTanBuffer, totalVertexCount); SolveTangents2DTriangles(this.tempTanBuffer, triangles, totalTriangleCount, meshVertices, meshUVs, totalVertexCount); SolveTangents2DBuffer(this.meshTangents, this.tempTanBuffer, totalVertexCount); } lastGeneratedMesh = mesh; return(mesh); }
public MeshAndMaterials GenerateMesh(ExposedList <SubmeshInstruction> instructions, int startSubmesh, int endSubmesh) { // STEP 0: Prepare instructions. var paramItems = instructions.Items; currentInstructions.Clear(false); for (int i = startSubmesh, n = endSubmesh; i < n; i++) { this.currentInstructions.Add(paramItems[i]); } var smartMesh = doubleBufferedSmartMesh.GetNext(); var mesh = smartMesh.mesh; int submeshCount = currentInstructions.Count; var currentInstructionsItems = currentInstructions.Items; int vertexCount = 0; for (int i = 0; i < submeshCount; i++) { currentInstructionsItems[i].firstVertexIndex = vertexCount; // Ensure current instructions have correct cached values. vertexCount += currentInstructionsItems[i].vertexCount; // vertexCount will also be used for the rest of this method. } // STEP 1: Ensure correct buffer sizes. bool vertBufferResized = ArraysMeshGenerator.EnsureSize(vertexCount, ref this.meshVertices, ref this.meshUVs, ref this.meshColors32); bool submeshBuffersResized = ArraysMeshGenerator.EnsureTriangleBuffersSize(submeshBuffers, submeshCount, currentInstructionsItems); // STEP 2: Update buffers based on Skeleton. // Initial values for manual Mesh Bounds calculation Vector3 meshBoundsMin; Vector3 meshBoundsMax; float zSpacing = this.zSpacing; 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; int endSlot = currentInstructionsItems[submeshCount - 1].endSlot; if (zSpacing > 0f) { meshBoundsMin.z = 0f; meshBoundsMax.z = zSpacing * endSlot; } else { meshBoundsMin.z = zSpacing * endSlot; meshBoundsMax.z = 0f; } } // For each submesh, add vertex data from attachments. var workingAttachments = this.attachmentBuffer; workingAttachments.Clear(false); int vertexIndex = 0; // modified by FillVerts for (int submeshIndex = 0; submeshIndex < submeshCount; submeshIndex++) { var currentInstruction = currentInstructionsItems[submeshIndex]; int startSlot = currentInstruction.startSlot; int endSlot = currentInstruction.endSlot; var skeleton = currentInstruction.skeleton; var skeletonDrawOrderItems = skeleton.DrawOrder.Items; for (int i = startSlot; i < endSlot; i++) { var ca = skeletonDrawOrderItems[i].attachment; if (ca != null) { workingAttachments.Add(ca); // Includes BoundingBoxes. This is ok. } } ArraysMeshGenerator.FillVerts(skeleton, startSlot, endSlot, zSpacing, this.premultiplyVertexColors, this.meshVertices, this.meshUVs, this.meshColors32, ref vertexIndex, ref this.attachmentVertexBuffer, ref meshBoundsMin, ref meshBoundsMax); } bool structureDoesntMatch = vertBufferResized || submeshBuffersResized || smartMesh.StructureDoesntMatch(workingAttachments, currentInstructions); for (int submeshIndex = 0; submeshIndex < submeshCount; submeshIndex++) { var currentInstruction = currentInstructionsItems[submeshIndex]; if (structureDoesntMatch) { var currentBuffer = submeshBuffers.Items[submeshIndex]; bool isLastSubmesh = (submeshIndex == submeshCount - 1); ArraysMeshGenerator.FillTriangles(currentInstruction.skeleton, currentInstruction.triangleCount, currentInstruction.firstVertexIndex, currentInstruction.startSlot, currentInstruction.endSlot, ref currentBuffer.triangles, isLastSubmesh); } } if (structureDoesntMatch) { mesh.Clear(); this.sharedMaterials = currentInstructions.GetUpdatedMaterialArray(this.sharedMaterials); } // STEP 3: Assign the buffers into the Mesh. smartMesh.Set(this.meshVertices, this.meshUVs, this.meshColors32, workingAttachments, currentInstructions); mesh.bounds = ArraysMeshGenerator.ToBounds(meshBoundsMin, meshBoundsMax); #if SPINE_OPTIONAL_NORMALS this.TryAddNormalsTo(mesh, vertexCount); #endif if (structureDoesntMatch) { // Push new triangles if doesn't match. mesh.subMeshCount = submeshCount; for (int i = 0; i < submeshCount; i++) { mesh.SetTriangles(submeshBuffers.Items[i].triangles, i); } } return(new MeshAndMaterials(smartMesh.mesh, sharedMaterials)); }
// ISubmeshedMeshGenerator.GenerateMesh /// <summary>Generates a mesh based on SubmeshedMeshInstructions</summary> public MeshAndMaterials GenerateMesh(SubmeshedMeshInstruction meshInstructions) { var smartMesh = doubleBufferedSmartMesh.GetNext(); var mesh = smartMesh.mesh; int submeshCount = meshInstructions.submeshInstructions.Count; var instructionList = meshInstructions.submeshInstructions; // STEP 1: Ensure correct buffer sizes. int vertexCount = meshInstructions.vertexCount; bool submeshBuffersResized = ArraysMeshGenerator.EnsureTriangleBuffersSize(submeshBuffers, submeshCount, instructionList.Items); bool vertBufferResized = ArraysMeshGenerator.EnsureSize(vertexCount, ref this.meshVertices, ref this.meshUVs, ref this.meshColors32); Vector3[] vertices = this.meshVertices; // STEP 2: Update buffers based on Skeleton. float zSpacing = this.ZSpacing; Vector3 meshBoundsMin; Vector3 meshBoundsMax; int attachmentCount = meshInstructions.attachmentList.Count; if (attachmentCount <= 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 * (attachmentCount - 1); } else { meshBoundsMin.z = zSpacing * (attachmentCount - 1); meshBoundsMax.z = 0f; } } bool structureDoesntMatch = vertBufferResized || submeshBuffersResized || smartMesh.StructureDoesntMatch(meshInstructions); // For each submesh, add vertex data From attachments. Also triangles, but only if needed. int vertexIndex = 0; // modified by FillVerts for (int submeshIndex = 0; submeshIndex < submeshCount; submeshIndex++) { var submeshInstruction = instructionList.Items[submeshIndex]; int start = submeshInstruction.startSlot; int end = submeshInstruction.endSlot; var skeleton = submeshInstruction.skeleton; ArraysMeshGenerator.FillVerts(skeleton, start, end, zSpacing, this.PremultiplyVertexColors, vertices, this.meshUVs, this.meshColors32, ref vertexIndex, ref this.attachmentVertexBuffer, ref meshBoundsMin, ref meshBoundsMax); if (structureDoesntMatch) { var currentBuffer = submeshBuffers.Items[submeshIndex]; bool isLastSubmesh = (submeshIndex == submeshCount - 1); ArraysMeshGenerator.FillTriangles(ref currentBuffer.triangles, skeleton, submeshInstruction.triangleCount, submeshInstruction.firstVertexIndex, start, end, isLastSubmesh); currentBuffer.triangleCount = submeshInstruction.triangleCount; currentBuffer.firstVertex = submeshInstruction.firstVertexIndex; } } if (structureDoesntMatch) { mesh.Clear(); this.sharedMaterials = meshInstructions.GetUpdatedMaterialArray(this.sharedMaterials); } // STEP 3: Assign the buffers into the Mesh. smartMesh.Set(this.meshVertices, this.meshUVs, this.meshColors32, meshInstructions); mesh.bounds = ArraysMeshGenerator.ToBounds(meshBoundsMin, meshBoundsMax); if (structureDoesntMatch) { // Push new triangles if doesn't match. mesh.subMeshCount = submeshCount; for (int i = 0; i < submeshCount; i++) { mesh.SetTriangles(submeshBuffers.Items[i].triangles, i); } TryAddNormalsTo(mesh, vertexCount); } if (addTangents) { SolveTangents2DEnsureSize(ref this.meshTangents, ref this.tempTanBuffer, vertexCount); for (int i = 0, n = submeshCount; i < n; i++) { var submesh = submeshBuffers.Items[i]; SolveTangents2DTriangles(this.tempTanBuffer, submesh.triangles, submesh.triangleCount, meshVertices, meshUVs, vertexCount); } SolveTangents2DBuffer(this.meshTangents, this.tempTanBuffer, vertexCount); } return(new MeshAndMaterials(smartMesh.mesh, sharedMaterials)); }
public MeshAndMaterials GenerateMesh(ExposedList <SubmeshInstruction> instructions, int startSubmesh, int endSubmesh) { SubmeshInstruction[] items = instructions.Items; this.currentInstructions.Clear(false); for (int i = startSubmesh; i < endSubmesh; i++) { this.currentInstructions.Add(items[i]); } SmartMesh next = this.doubleBufferedSmartMesh.GetNext(); Mesh mesh = next.mesh; int count = this.currentInstructions.Count; SubmeshInstruction[] items2 = this.currentInstructions.Items; int num = 0; for (int j = 0; j < count; j++) { items2[j].firstVertexIndex = num; num += items2[j].vertexCount; } bool flag = ArraysMeshGenerator.EnsureSize(num, ref this.meshVertices, ref this.meshUVs, ref this.meshColors32); bool flag2 = ArraysMeshGenerator.EnsureTriangleBuffersSize(this.submeshBuffers, count, items2); float zspacing = this.ZSpacing; Vector3 boundsMin; Vector3 boundsMax; if (num <= 0) { boundsMin = new Vector3(0f, 0f, 0f); boundsMax = new Vector3(0f, 0f, 0f); } else { boundsMin.x = 2.14748365E+09f; boundsMin.y = 2.14748365E+09f; boundsMax.x = -2.14748365E+09f; boundsMax.y = -2.14748365E+09f; int endSlot = items2[count - 1].endSlot; if (zspacing > 0f) { boundsMin.z = 0f; boundsMax.z = zspacing * (float)endSlot; } else { boundsMin.z = zspacing * (float)endSlot; boundsMax.z = 0f; } } ExposedList <Attachment> exposedList = this.attachmentBuffer; exposedList.Clear(false); int num2 = 0; for (int k = 0; k < count; k++) { SubmeshInstruction submeshInstruction = items2[k]; int startSlot = submeshInstruction.startSlot; int endSlot2 = submeshInstruction.endSlot; Skeleton skeleton = submeshInstruction.skeleton; Slot[] items3 = skeleton.DrawOrder.Items; for (int l = startSlot; l < endSlot2; l++) { Attachment attachment = items3[l].attachment; if (attachment != null) { exposedList.Add(attachment); } } ArraysMeshGenerator.FillVerts(skeleton, startSlot, endSlot2, zspacing, base.PremultiplyVertexColors, this.meshVertices, this.meshUVs, this.meshColors32, ref num2, ref this.attachmentVertexBuffer, ref boundsMin, ref boundsMax, true); } bool flag3 = flag || flag2 || next.StructureDoesntMatch(exposedList, this.currentInstructions); for (int m = 0; m < count; m++) { SubmeshInstruction submeshInstruction2 = items2[m]; if (flag3) { SubmeshTriangleBuffer submeshTriangleBuffer = this.submeshBuffers.Items[m]; bool isLastSubmesh = m == count - 1; ArraysMeshGenerator.FillTriangles(ref submeshTriangleBuffer.triangles, submeshInstruction2.skeleton, submeshInstruction2.triangleCount, submeshInstruction2.firstVertexIndex, submeshInstruction2.startSlot, submeshInstruction2.endSlot, isLastSubmesh); submeshTriangleBuffer.triangleCount = submeshInstruction2.triangleCount; submeshTriangleBuffer.firstVertex = submeshInstruction2.firstVertexIndex; } } if (flag3) { mesh.Clear(); this.sharedMaterials = this.currentInstructions.GetUpdatedMaterialArray(this.sharedMaterials); } next.Set(this.meshVertices, this.meshUVs, this.meshColors32, exposedList, this.currentInstructions); mesh.bounds = ArraysMeshGenerator.ToBounds(boundsMin, boundsMax); if (flag3) { mesh.subMeshCount = count; for (int n = 0; n < count; n++) { mesh.SetTriangles(this.submeshBuffers.Items[n].triangles, n); } base.TryAddNormalsTo(mesh, num); } if (this.addTangents) { ArraysMeshGenerator.SolveTangents2DEnsureSize(ref this.meshTangents, ref this.tempTanBuffer, num); int num3 = 0; int num4 = count; while (num3 < num4) { SubmeshTriangleBuffer submeshTriangleBuffer2 = this.submeshBuffers.Items[num3]; ArraysMeshGenerator.SolveTangents2DTriangles(this.tempTanBuffer, submeshTriangleBuffer2.triangles, submeshTriangleBuffer2.triangleCount, this.meshVertices, this.meshUVs, num); num3++; } ArraysMeshGenerator.SolveTangents2DBuffer(this.meshTangents, this.tempTanBuffer, num); } return(new MeshAndMaterials(next.mesh, this.sharedMaterials)); }
public MeshAndMaterials GenerateMesh(SubmeshedMeshInstruction meshInstructions) { SmartMesh next = this.doubleBufferedSmartMesh.GetNext(); Mesh mesh = next.mesh; int count = meshInstructions.submeshInstructions.Count; ExposedList <SubmeshInstruction> submeshInstructions = meshInstructions.submeshInstructions; int vertexCount = meshInstructions.vertexCount; bool flag = ArraysMeshGenerator.EnsureTriangleBuffersSize(this.submeshBuffers, count, submeshInstructions.Items); bool flag2 = ArraysMeshGenerator.EnsureSize(vertexCount, ref this.meshVertices, ref this.meshUVs, ref this.meshColors32); Vector3[] meshVertices = this.meshVertices; float zspacing = this.ZSpacing; int count2 = meshInstructions.attachmentList.Count; Vector3 boundsMin; Vector3 boundsMax; if (count2 <= 0) { boundsMin = new Vector3(0f, 0f, 0f); boundsMax = new Vector3(0f, 0f, 0f); } else { boundsMin.x = 2.14748365E+09f; boundsMin.y = 2.14748365E+09f; boundsMax.x = -2.14748365E+09f; boundsMax.y = -2.14748365E+09f; if (zspacing > 0f) { boundsMin.z = 0f; boundsMax.z = zspacing * (float)(count2 - 1); } else { boundsMin.z = zspacing * (float)(count2 - 1); boundsMax.z = 0f; } } bool flag3 = flag2 || flag || next.StructureDoesntMatch(meshInstructions); int num = 0; for (int i = 0; i < count; i++) { SubmeshInstruction submeshInstruction = submeshInstructions.Items[i]; int startSlot = submeshInstruction.startSlot; int endSlot = submeshInstruction.endSlot; Skeleton skeleton = submeshInstruction.skeleton; ArraysMeshGenerator.FillVerts(skeleton, startSlot, endSlot, zspacing, base.PremultiplyVertexColors, meshVertices, this.meshUVs, this.meshColors32, ref num, ref this.attachmentVertexBuffer, ref boundsMin, ref boundsMax, true); if (flag3) { SubmeshTriangleBuffer submeshTriangleBuffer = this.submeshBuffers.Items[i]; bool isLastSubmesh = i == count - 1; ArraysMeshGenerator.FillTriangles(ref submeshTriangleBuffer.triangles, skeleton, submeshInstruction.triangleCount, submeshInstruction.firstVertexIndex, startSlot, endSlot, isLastSubmesh); submeshTriangleBuffer.triangleCount = submeshInstruction.triangleCount; submeshTriangleBuffer.firstVertex = submeshInstruction.firstVertexIndex; } } if (flag3) { mesh.Clear(); this.sharedMaterials = meshInstructions.GetUpdatedMaterialArray(this.sharedMaterials); } next.Set(this.meshVertices, this.meshUVs, this.meshColors32, meshInstructions); mesh.bounds = ArraysMeshGenerator.ToBounds(boundsMin, boundsMax); if (flag3) { mesh.subMeshCount = count; for (int j = 0; j < count; j++) { mesh.SetTriangles(this.submeshBuffers.Items[j].triangles, j); } base.TryAddNormalsTo(mesh, vertexCount); } if (this.addTangents) { ArraysMeshGenerator.SolveTangents2DEnsureSize(ref this.meshTangents, ref this.tempTanBuffer, vertexCount); int k = 0; int num2 = count; while (k < num2) { SubmeshTriangleBuffer submeshTriangleBuffer2 = this.submeshBuffers.Items[k]; ArraysMeshGenerator.SolveTangents2DTriangles(this.tempTanBuffer, submeshTriangleBuffer2.triangles, submeshTriangleBuffer2.triangleCount, this.meshVertices, this.meshUVs, vertexCount); k++; } ArraysMeshGenerator.SolveTangents2DBuffer(this.meshTangents, this.tempTanBuffer, vertexCount); } return(new MeshAndMaterials(next.mesh, this.sharedMaterials)); }
public Mesh GenerateMesh(Skeleton skeleton) { int num = 0; int num2 = 0; Slot[] items = skeleton.drawOrder.Items; int count = skeleton.drawOrder.Count; int i = 0; while (i < count) { Slot slot = items[i]; Attachment attachment = slot.attachment; RegionAttachment regionAttachment = attachment as RegionAttachment; int num3; int num4; if (regionAttachment != null) { num3 = 4; num4 = 6; goto IL_7E; } MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { num3 = meshAttachment.worldVerticesLength >> 1; num4 = meshAttachment.triangles.Length; goto IL_7E; } IL_88: i++; continue; IL_7E: num2 += num4; num += num3; goto IL_88; } ArraysMeshGenerator.EnsureSize(num, ref this.meshVertices, ref this.meshUVs, ref this.meshColors32); this.triangles = (this.triangles ?? new int[num2]); Vector3 boundsMin; Vector3 boundsMax; if (num == 0) { boundsMin = new Vector3(0f, 0f, 0f); boundsMax = new Vector3(0f, 0f, 0f); } else { boundsMin.x = 2.14748365E+09f; boundsMin.y = 2.14748365E+09f; boundsMax.x = -2.14748365E+09f; boundsMax.y = -2.14748365E+09f; boundsMin.z = -0.01f * this.scale; boundsMax.z = 0.01f * this.scale; int num5 = 0; ArraysMeshGenerator.FillVerts(skeleton, 0, count, this.ZSpacing, base.PremultiplyVertexColors, this.meshVertices, this.meshUVs, this.meshColors32, ref num5, ref this.attachmentVertexBuffer, ref boundsMin, ref boundsMax, true); boundsMax.x *= this.scale; boundsMax.y *= this.scale; boundsMin.x *= this.scale; boundsMax.y *= this.scale; Vector3[] meshVertices = this.meshVertices; for (int j = 0; j < num; j++) { Vector3 vector = meshVertices[j]; vector.x *= this.scale; vector.y *= this.scale; meshVertices[j] = vector; } } ArraysMeshGenerator.FillTriangles(ref this.triangles, skeleton, num2, 0, 0, count, true); Mesh nextMesh = this.doubleBufferedMesh.GetNextMesh(); nextMesh.vertices = this.meshVertices; nextMesh.colors32 = this.meshColors32; nextMesh.uv = this.meshUVs; nextMesh.bounds = ArraysMeshGenerator.ToBounds(boundsMin, boundsMax); nextMesh.triangles = this.triangles; base.TryAddNormalsTo(nextMesh, num); if (this.addTangents) { ArraysMeshGenerator.SolveTangents2DEnsureSize(ref this.meshTangents, ref this.tempTanBuffer, num); ArraysMeshGenerator.SolveTangents2DTriangles(this.tempTanBuffer, this.triangles, num2, this.meshVertices, this.meshUVs, num); ArraysMeshGenerator.SolveTangents2DBuffer(this.meshTangents, this.tempTanBuffer, num); } this.lastGeneratedMesh = nextMesh; return(nextMesh); }