public Material[] GetUpdatedShaderdMaterialsArray() { if (submeshMaterials.Count == sharedMaterials.Length) { submeshMaterials.CopyTo(sharedMaterials); } else { sharedMaterials = submeshMaterials.ToArray(); } return(sharedMaterials); }
public void Set(Vector3[] verts, Vector2[] uvs, Color32[] colors, ExposedList <Attachment> attachments, ExposedList <SubmeshInstruction> instructions) { this.mesh.vertices = verts; this.mesh.uv = uvs; this.mesh.colors32 = colors; this.attachmentsUsed.Clear(false); this.attachmentsUsed.GrowIfNeeded(attachments.Capacity); this.attachmentsUsed.Count = attachments.Count; attachments.CopyTo(this.attachmentsUsed.Items); this.instructionsUsed.Clear(false); this.instructionsUsed.GrowIfNeeded(instructions.Capacity); this.instructionsUsed.Count = instructions.Count; instructions.CopyTo(this.instructionsUsed.Items); }
public void Set(Vector3[] verts, Vector2[] uvs, Color32[] colors, ExposedList<Attachment> attachments, ExposedList<SubmeshInstruction> instructions) { mesh.vertices = verts; mesh.uv = uvs; mesh.colors32 = colors; attachmentsUsed.Clear(false); attachmentsUsed.GrowIfNeeded(attachments.Capacity); attachmentsUsed.Count = attachments.Count; attachments.CopyTo(attachmentsUsed.Items); instructionsUsed.Clear(false); instructionsUsed.GrowIfNeeded(instructions.Capacity); instructionsUsed.Count = instructions.Count; instructions.CopyTo(instructionsUsed.Items); }
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; } // 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; }
public void UpdateMesh() { //Debug.Log("UpdateMesh"); if (!valid) { return; } float scale = canvas.referencePixelsPerUnit; // 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; 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; 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 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 var currentMaterial = (Material)((AtlasRegion)rendererObject).page.rendererObject; #else var currentMaterial = (rendererObject.GetType() == typeof(Material)) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject; #endif if ((lastMaterial != null && lastMaterial.GetInstanceID() != currentMaterial.GetInstanceID())) { addSubmeshArgumentsTemp.Add( new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false) ); submeshTriangleCount = 0; submeshFirstVertex = vertexCount; submeshStartSlotIndex = i; } lastMaterial = currentMaterial; 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; this.material = sharedMaterials[0]; canvasRenderer.SetMaterial(sharedMaterials[0], (Texture)null); } // 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 vertColor = new Color32(); Color graphicColor = base.color; float a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b; // Mesh bounds 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; var regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { regionAttachment.ComputeWorldVertices(slot.bone, tempVertices); float z = i * zSpacing; vertices[vertexIndex].x = tempVertices[RegionAttachment.X1] * scale; vertices[vertexIndex].y = tempVertices[RegionAttachment.Y1] * scale; vertices[vertexIndex].z = z; vertices[vertexIndex + 1].x = tempVertices[RegionAttachment.X4] * scale; vertices[vertexIndex + 1].y = tempVertices[RegionAttachment.Y4] * scale; vertices[vertexIndex + 1].z = z; vertices[vertexIndex + 2].x = tempVertices[RegionAttachment.X2] * scale; vertices[vertexIndex + 2].y = tempVertices[RegionAttachment.Y2] * scale; vertices[vertexIndex + 2].z = z; vertices[vertexIndex + 3].x = tempVertices[RegionAttachment.X3] * scale; vertices[vertexIndex + 3].y = tempVertices[RegionAttachment.Y3] * scale; vertices[vertexIndex + 3].z = z; vertColor.a = (byte)(a * slot.a * regionAttachment.a * graphicColor.a); vertColor.r = (byte)(r * slot.r * regionAttachment.r * graphicColor.r * vertColor.a); vertColor.g = (byte)(g * slot.g * regionAttachment.g * graphicColor.g * vertColor.a); vertColor.b = (byte)(b * slot.b * regionAttachment.b * graphicColor.b * vertColor.a); if (slot.data.blendMode == BlendMode.additive) { vertColor.a = 0; } colors[vertexIndex] = vertColor; colors[vertexIndex + 1] = vertColor; colors[vertexIndex + 2] = vertColor; colors[vertexIndex + 3] = vertColor; 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 Bounds 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 Bounds 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; } var 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); vertColor.a = (byte)(a * slot.a * meshAttachment.a * graphicColor.a); vertColor.r = (byte)(r * slot.r * meshAttachment.r * graphicColor.r * vertColor.a); vertColor.g = (byte)(g * slot.g * meshAttachment.g * graphicColor.g * vertColor.a); vertColor.b = (byte)(b * slot.b * meshAttachment.b * graphicColor.b * vertColor.a); if (slot.data.blendMode == BlendMode.additive) { vertColor.a = 0; } float[] meshUVs = meshAttachment.uvs; float z = i * zSpacing; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { vertices[vertexIndex].x = tempVertices[ii] * scale; vertices[vertexIndex].y = tempVertices[ii + 1] * scale; vertices[vertexIndex].z = z; colors[vertexIndex] = vertColor; uvs[vertexIndex].x = meshUVs[ii]; uvs[vertexIndex].y = meshUVs[ii + 1]; // Calculate Bounds 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 { var 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); vertColor.a = (byte)(a * slot.a * skinnedMeshAttachment.a * graphicColor.a); vertColor.r = (byte)(r * slot.r * skinnedMeshAttachment.r * graphicColor.r * vertColor.a); vertColor.g = (byte)(g * slot.g * skinnedMeshAttachment.g * graphicColor.g * vertColor.a); vertColor.b = (byte)(b * slot.b * skinnedMeshAttachment.b * graphicColor.b * vertColor.a); if (slot.data.blendMode == BlendMode.additive) { vertColor.a = 0; } float[] meshUVs = skinnedMeshAttachment.uvs; float z = i * zSpacing; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { vertices[vertexIndex].x = tempVertices[ii] * scale; vertices[vertexIndex].y = tempVertices[ii + 1] * scale; vertices[vertexIndex].z = z; colors[vertexIndex] = vertColor; uvs[vertexIndex].x = meshUVs[ii]; uvs[vertexIndex].y = meshUVs[ii + 1]; // Calculate Bounds 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; // Push data from buffers. mesh.vertices = vertices; mesh.colors32 = colors; mesh.uv = uvs; // Set Mesh bounds. Vector3 meshBoundsExtents = (meshBoundsMax - meshBoundsMin) * scale; // scaled Vector3 meshBoundsCenter = meshBoundsMin + meshBoundsExtents * 0.5f; mesh.bounds = new Bounds(meshBoundsCenter, meshBoundsExtents); //mesh.RecalculateBounds(); canvasRenderer.SetMesh(mesh); //this.SetVerticesDirty(); if (mustUpdateMeshStructure) { int submeshCount = submeshMaterials.Count; mesh.subMeshCount = submeshCount; for (int i = 0; i < submeshCount; ++i) { mesh.SetTriangles(submeshes.Items[i].triangles, i); } /* * TODO: Check fix with a known repro case. * if (useMesh1) * lastState.forceUpdateMesh1 = false; * else * lastState.forceUpdateMesh2 = false; */ } if (newTriangles && calculateNormals) { var normals = new Vector3[vertexCount]; var 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) { var tangents = new Vector4[vertexCount]; var 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); useMesh1 = !useMesh1; }