//通过采样坐标u获取对应的网格 private void GetSmartMeshByU(int u, ref int relativeU, out SmartMesh mesh) { mesh = null; int uCursor = 0; relativeU = u; for (int i = 0; i < smartMeshList.Count; i++) { int vertexCount = smartMeshList[i].vertexCount; uCursor += vertexCount; //找到了u停留的Mesh,计算相对u if (u < uCursor) { mesh = smartMeshList[i]; return; } else { relativeU -= vertexCount; } } Debug.LogErrorFormat("根据坐标{0}获取模型数据失败!!!", u); }
//在场景中准备一个节点 private void PrepareGameObjectInScene() { instanceGameObject = GameObject.Instantiate <GameObject>(modelGameObject); instanceGameObject.name = "TEMP"; Animation ac = instanceGameObject.GetComponent <Animation>(); //移除旧的 if (ac != null) { DestroyImmediate(ac); } //添加新的 instanceAnimation = instanceGameObject.AddComponent <Animation>(); //添加.. foreach (var item in animationClips) { string animName = string.IsNullOrEmpty(item.newName) ? item.clip.name : item.newName; instanceAnimation.AddClip(item.clip, animName); } skinnedMeshRenderers.Clear(); meshFilters.Clear(); smartMeshList.Clear(); instanceGameObject.GetComponentsInChildren <SkinnedMeshRenderer>(true, skinnedMeshRenderers); instanceGameObject.GetComponentsInChildren <MeshFilter>(true, meshFilters); usedTextures = new List <Texture>(); foreach (var smr in skinnedMeshRenderers) { SmartMesh smartMesh = new SmartMesh(smr, null); var meshUseTexture = smartMesh.mainTexture; int idx = usedTextures.IndexOf(meshUseTexture); if (idx < 0) { //用的是第几套uv呢 smartMesh.uvIdx = usedTextures.Count; usedTextures.Add(meshUseTexture); } else { smartMesh.uvIdx = idx; } smartMeshList.Add(smartMesh); Debug.Log(smartMesh.Desc()); } foreach (var mf in meshFilters) { SmartMesh smartMesh = new SmartMesh(null, mf); var meshUseTexture = smartMesh.mainTexture; int idx = usedTextures.IndexOf(meshUseTexture); if (idx < 0) { //用的是第几套uv呢 smartMesh.uvIdx = usedTextures.Count; usedTextures.Add(meshUseTexture); } else { smartMesh.uvIdx = idx; } smartMeshList.Add(smartMesh); Debug.Log(smartMesh.Desc()); } multipleTexturesMode = usedTextures.Count > 1; Debug.LogFormat("使用的蒙皮纹理数为:{0}", usedTextures.Count); if (multipleTexturesMode) { EditorUtility.DisplayDialog("注意", "注意,当前存在多套蒙皮纹理!", "好的"); } }
//针对每一个动作单独生成纹理 private void GenerateAnimationTexture(Animation animation, AnimationState state) { //生成动画纹理的名称 string assetName = string.Format("{0}_{1}", modelGameObject.name, state.name); Debug.LogFormat("正在处理 {0}...", assetName); //播放并记录 Debug.Log("播放动画" + state.name); animation.Play(state.name); AnimationClip clip = state.clip; //连接到材质球 string keyLen = string.Format("_{0}Len", state.name); mainMaterial.SetFloat(keyLen, state.length); //原始需要帧数 int originFrames = (int)(state.clip.frameRate * state.length); int generateFrames = Mathf.ClosestPowerOfTwo(originFrames); float frameGap = state.length / generateFrames; Debug.LogFormat("{0}的原始帧数为{1},处理后为{2},动画长度为{3:0.00},帧间隔为{4:0.00}", state.name, originFrames, generateFrames, state.length, frameGap); //纹理宽度为顶点数量,高度为动作帧数 int textureWidth = Mathf.NextPowerOfTwo(combinedMesh.vertexCount); int textureHeight = generateFrames; Texture2D animationTexture = new Texture2D(textureWidth, textureHeight, TextureFormat.RGBAHalf, false); for (int v = 0; v < textureHeight; v++) { //摆pose state.time = v * frameGap; //采样!!! animation.Sample(); for (int u = 0; u < combinedMesh.vertexCount; u++) { //这里必须按照之前合并网格的顺序来搞... int relativeU = 0; SmartMesh sm = null; GetSmartMeshByU(u, ref relativeU, out sm); if (sm == null) { EditorUtility.DisplayDialog("错误", "根据UV坐标获取网格信息失败!", "呃..."); return; } Mesh mesh = sm.GetAnimationMesh(modelCenter.worldToLocalMatrix); Vector3 vertexPos = mesh.vertices[relativeU]; Color color = new Color(vertexPos.x, vertexPos.y, vertexPos.z); //将位置保存为颜色 animationTexture.SetPixel(u, v, color); } } animationTexture.Apply(); //保存 AssetDatabase.CreateAsset(animationTexture, GetAnimationTextureAssetPath(assetName)); Debug.Log("生成了动画纹理:" + assetName, animationTexture); //连接到材质球 string keyTex = string.Format("_{0}Tex", state.name); mainMaterial.SetTexture(keyTex, animationTexture); if (state.name.ToLower().Contains("attack")) { animationAsset.attackAnimLength = clip.length; } else if (state.name.ToLower().Contains("death")) { //别问为什么,经验! animationAsset.deathAnimLength = clip.length * 0.95f; } }
public virtual void LateUpdate() { if (!valid || (!meshRenderer.enabled && this.generateMeshOverride == null)) { return; } ExposedList <Slot> drawOrder = skeleton.drawOrder; Slot[] items = drawOrder.Items; int count = drawOrder.Count; bool flag = renderMeshes; SmartMesh.Instruction instruction = currentInstructions; ExposedList <Attachment> attachments = instruction.attachments; attachments.Clear(clearArray: false); attachments.GrowIfNeeded(count); attachments.Count = count; Attachment[] items2 = instruction.attachments.Items; ExposedList <SubmeshInstruction> submeshInstructions = instruction.submeshInstructions; submeshInstructions.Clear(clearArray: false); bool flag2 = customSlotMaterials.Count > 0; int num = 0; int num2 = 0; int num3 = 0; int firstVertexIndex = 0; int startSlot = 0; Material material = null; for (int i = 0; i < count; i++) { Slot slot = items[i]; Attachment attachment = items2[i] = slot.attachment; RegionAttachment regionAttachment = attachment as RegionAttachment; object rendererObject; int num4; int num5; if (regionAttachment != null) { rendererObject = regionAttachment.RendererObject; num4 = 4; num5 = 6; } else { if (!flag) { continue; } MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment == null) { continue; } rendererObject = meshAttachment.RendererObject; num4 = meshAttachment.worldVerticesLength >> 1; num5 = meshAttachment.triangles.Length; } Material value; if (flag2) { if (!customSlotMaterials.TryGetValue(slot, out value)) { value = (Material)((AtlasRegion)rendererObject).page.rendererObject; } } else { value = (Material)((AtlasRegion)rendererObject).page.rendererObject; } bool flag3 = separatorSlots.Count > 0 && separatorSlots.Contains(slot); if (num > 0 && (material.GetInstanceID() != value.GetInstanceID() || flag3)) { submeshInstructions.Add(new SubmeshInstruction { skeleton = skeleton, material = material, startSlot = startSlot, endSlot = i, triangleCount = num3, firstVertexIndex = firstVertexIndex, vertexCount = num2, forceSeparate = flag3 }); num3 = 0; num2 = 0; firstVertexIndex = num; startSlot = i; } material = value; num3 += num5; num += num4; num2 += num4; } if (num2 != 0) { submeshInstructions.Add(new SubmeshInstruction { skeleton = skeleton, material = material, startSlot = startSlot, endSlot = count, triangleCount = num3, firstVertexIndex = firstVertexIndex, vertexCount = num2, forceSeparate = false }); } instruction.vertexCount = num; instruction.immutableTriangles = immutableTriangles; if (customMaterialOverride.Count > 0) { SubmeshInstruction[] items3 = submeshInstructions.Items; for (int j = 0; j < submeshInstructions.Count; j++) { Material material2 = items3[j].material; Material value2; if (customMaterialOverride.TryGetValue(material2, out value2)) { items3[j].material = value2; } } } if (this.generateMeshOverride != null) { this.generateMeshOverride(instruction); if (disableRenderingOnOverride) { return; } } if (ArraysMeshGenerator.EnsureSize(num, ref vertices, ref uvs, ref colors) && calculateNormals) { Vector3[] array = normals = new Vector3[num]; Vector3 vector = new Vector3(0f, 0f, -1f); for (int k = 0; k < num; k++) { array[k] = vector; } } Vector3 boundsMin = default(Vector3); Vector3 boundsMax = default(Vector3); 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; if (zSpacing > 0f) { boundsMin.z = 0f; boundsMax.z = zSpacing * (float)(count - 1); } else { boundsMin.z = zSpacing * (float)(count - 1); boundsMax.z = 0f; } } int vertexIndex = 0; ArraysMeshGenerator.FillVerts(skeleton, 0, count, zSpacing, pmaVertexColors, vertices, uvs, colors, ref vertexIndex, ref tempVertices, ref boundsMin, ref boundsMax, flag); SmartMesh next = doubleBufferedMesh.GetNext(); Mesh mesh = next.mesh; mesh.vertices = vertices; mesh.colors32 = colors; mesh.uv = uvs; mesh.bounds = ArraysMeshGenerator.ToBounds(boundsMin, boundsMax); SmartMesh.Instruction instructionUsed = next.instructionUsed; if (calculateNormals && instructionUsed.vertexCount < num) { mesh.normals = normals; } bool flag4 = CheckIfMustUpdateMeshStructure(instruction, instructionUsed); int count2 = submeshInstructions.Count; if (flag4) { ExposedList <Material> exposedList = submeshMaterials; exposedList.Clear(clearArray: false); int count3 = submeshes.Count; if (submeshes.Capacity < count2) { submeshes.Capacity = count2; } for (int l = count3; l < count2; l++) { submeshes.Items[l] = new ArraysMeshGenerator.SubmeshTriangleBuffer(submeshInstructions.Items[l].triangleCount); } submeshes.Count = count2; bool flag5 = !instruction.immutableTriangles; int m = 0; int num6 = count2 - 1; for (; m < count2; m++) { SubmeshInstruction submeshInstruction = submeshInstructions.Items[m]; if (flag5 || m >= count3) { ArraysMeshGenerator.SubmeshTriangleBuffer submeshTriangleBuffer = submeshes.Items[m]; int triangleCount = submeshInstruction.triangleCount; if (flag) { ArraysMeshGenerator.FillTriangles(ref submeshTriangleBuffer.triangles, skeleton, triangleCount, submeshInstruction.firstVertexIndex, submeshInstruction.startSlot, submeshInstruction.endSlot, m == num6); submeshTriangleBuffer.triangleCount = triangleCount; } else { ArraysMeshGenerator.FillTrianglesQuads(ref submeshTriangleBuffer.triangles, ref submeshTriangleBuffer.triangleCount, ref submeshTriangleBuffer.firstVertex, submeshInstruction.firstVertexIndex, triangleCount, m == num6); } } exposedList.Add(submeshInstruction.material); } mesh.subMeshCount = count2; for (int n = 0; n < count2; n++) { mesh.SetTriangles(submeshes.Items[n].triangles, n); } } if (calculateTangents) { ArraysMeshGenerator.SolveTangents2DEnsureSize(ref tangents, ref tempTanBuffer, vertices.Length); for (int num7 = 0; num7 < count2; num7++) { ArraysMeshGenerator.SubmeshTriangleBuffer submeshTriangleBuffer2 = submeshes.Items[num7]; ArraysMeshGenerator.SolveTangents2DTriangles(tempTanBuffer, submeshTriangleBuffer2.triangles, submeshTriangleBuffer2.triangleCount, vertices, uvs, num); } ArraysMeshGenerator.SolveTangents2DBuffer(tangents, tempTanBuffer, num); mesh.tangents = tangents; } Material[] array2 = sharedMaterials; bool flag6 = flag4 || array2.Length != count2; if (!flag6) { SubmeshInstruction[] items4 = submeshInstructions.Items; int num8 = 0; for (int num9 = array2.Length; num8 < num9; num8++) { if (array2[num8].GetInstanceID() != items4[num8].material.GetInstanceID()) { flag6 = true; break; } } } if (flag6) { if (submeshMaterials.Count == sharedMaterials.Length) { submeshMaterials.CopyTo(sharedMaterials); } else { sharedMaterials = submeshMaterials.ToArray(); } meshRenderer.sharedMaterials = sharedMaterials; } meshFilter.sharedMesh = mesh; next.instructionUsed.Set(instruction); }
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)); }