/// <summary> /// Remove all component data /// </summary> public void ClearComponents() { TransformComponents.Clear(); PhysicsComponents.Clear(); CollisionComponents.Clear(); MeshComponents.Clear(); }
Mesh[] SplitMeshes(MeshComponents mesh, int size) { //vertsPerMesh > 2*(size+1) //vertsPerMesh < 64512 (65534 exatctly) //vertsPerMesh must be multiple of 2 int aux = 0; int powerBase = 2; while (aux * size + 1 < 30000) { powerBase++; aux = (int)Mathf.Pow(2, powerBase); } int vertsPerMesh = (size + 1) * (int)Mathf.Pow(2.0f, powerBase); Debug.Log(vertsPerMesh); int numMeshes = mesh.vertices.Length / vertsPerMesh + 1; Mesh[] returnMeshes = new Mesh[numMeshes]; for (int m = 0; m < numMeshes; m++) { returnMeshes[m] = new Mesh(); List <Vector3> mVertices = new List <Vector3>(); List <int> mTriangles = new List <int>(); int index = 0; Debug.LogWarning(mesh.vertices.Length); for (int v = 0; v < vertsPerMesh; v++) { index = (m * (vertsPerMesh - (size + 1)) + v); if (index < mesh.vertices.Length) { mVertices.Add(mesh.vertices[index]); } //Debug.Log("M: " + m + " vertsPerMesh: " + vertsPerMesh + " size+1: " + (size+1) + " v: " + v + " index: " + index); } for (int v = 0, x = 0; x < (mVertices.Count / (size + 1)) - 1; x++) { for (int z = 0; z < size; z++, v++) { mTriangles.Add(v); mTriangles.Add(v + 1); mTriangles.Add(v + size + 1); mTriangles.Add(v + size + 1); mTriangles.Add(v + 1); mTriangles.Add(v + size + 2); } v++; } returnMeshes[m].SetVertices(mVertices); returnMeshes[m].SetTriangles(mTriangles, 0); } return(returnMeshes); }
Dictionary <int, int> ModifiedV; // could use flat buffer for this? public VertexChangeBuilder(DMesh3 mesh, MeshComponents components = MeshComponents.All) { Mesh = mesh; Components = components; ModifiedV = new Dictionary <int, int>(); ActiveChange = new ModifyVerticesMeshChange(mesh, components); }
/// <summary> /// This method can be used to extend a mesh by some vertices. /// </summary> /// <param name="mesh">The mesh which shall be extended</param> /// <param name="extensionComponent">the information of the extension</param> /// <param name="transform">the transformobject of the extension component.</param> /// <returns>an extended mesh represented by an mesh-component object.</returns> public static MeshComponents ExtendMesh(this Mesh mesh, MeshComponents extensionComponent, Transform transform) { MeshComponents extendedMeshComponents = new MeshComponents(); extendedMeshComponents.SetInitialTriangles(mesh.vertices, mesh.triangles); extensionComponent.ConvertWorldToLocalVertices(transform); extendedMeshComponents.AddTriangles(extensionComponent.GetVertices()); return extendedMeshComponents; }
private void Awake() { _lookupMesh = new Dictionary <float3, ChunkTable>(); textureAtlas = material; tileMesh = tileMeshComp; _drawDistance = drawDistance; instance = this; }
public static void Restore(DMesh3 mesh, BinaryReader reader) { int version = reader.ReadInt32(); if (version != DMesh3Version) { throw new Exception("gSerialization.Restore: Incorrect DMesh3Version!"); } MeshComponents components = (MeshComponents)reader.ReadInt32(); Restore(mesh.VerticesBuffer, reader); Restore(mesh.TrianglesBuffer, reader); Restore(mesh.EdgesBuffer, reader); Restore(mesh.EdgesRefCounts.RawRefCounts, reader); if ((components & MeshComponents.VertexNormals) != 0) { mesh.EnableVertexNormals(Vector3f.AxisY); Restore(mesh.NormalsBuffer, reader); } else { mesh.DiscardVertexNormals(); } if ((components & MeshComponents.VertexColors) != 0) { mesh.EnableVertexColors(Vector3f.One); Restore(mesh.ColorsBuffer, reader); } else { mesh.DiscardVertexColors(); } if ((components & MeshComponents.VertexUVs) != 0) { mesh.EnableVertexUVs(Vector2f.Zero); Restore(mesh.UVBuffer, reader); } else { mesh.DiscardVertexUVs(); } if ((components & MeshComponents.FaceGroups) != 0) { mesh.EnableTriangleGroups(0); Restore(mesh.GroupsBuffer, reader); } else { mesh.DiscardTriangleGroups(); } mesh.RebuildFromEdgeRefcounts(); }
public bool HasSolidNeighbour(int x, int y, int z, ConcurrentDictionary <int3, Chunk> chunkMap) { //If this is ever is Jobified, this will be a memory sink Block[,,] chunks; if (x < 0 || x >= MeshComponents.chunkSize || y < 0 || y >= MeshComponents.chunkSize || z < 0 || z >= MeshComponents.chunkSize) { //Block in another chunk float3 neighbourChunkPos = owner.position + new float3((x - (int)position.x) * MeshComponents.chunkSize, (y - (int)position.y) * MeshComponents.chunkSize, (z - (int)position.z) * MeshComponents.chunkSize); string nName = MeshComponents.BuildChunkName(neighbourChunkPos); x = ConvertBlockIndexToLocal(x); y = ConvertBlockIndexToLocal(y); z = ConvertBlockIndexToLocal(z); if (chunkMap.TryGetValue(new int3(neighbourChunkPos), out Chunk nChunk)) { chunks = nChunk.chunkData; } else { //Edge of the known world return(false); } } else { //Block in this chunk chunks = owner.chunkData; } if (chunks.Length != 0) { try { return(chunks[x, y, z].isSolid); } catch (System.IndexOutOfRangeException ex) { } return(false); } else { return(false); } }
MeshComponents CalculateMesh(int size) { MeshComponents mesh = new MeshComponents(); mesh.vertices = new Vector3[(size + 1) * (size + 1)]; mesh.triangles = new int[size * size * 6]; for (int i = 0, x = 0; x <= size; x++) { for (int z = 0; z <= size; z++, i++) { float y = Noise.PerlinNoise2D(x * 0.05f, z * 0.05f) * 8; mesh.vertices[i] = (new Vector3(x, y, z)); } } return(mesh); }
// Use this for initialization public void GenerateMesh() { var meshData = new MeshComponents(this.scaleCoeff); this.Tiles = new CityMeshTiles(this.Origin, new Vector2I(MeshWidth, MeshHeight), TileSize, Material); var materials = new List <Material>(); foreach (var tile in this.Tiles.TileArray) { meshData.GenerateSquareAt(tile.FromX, tile.FromY, tile.SizeX); materials.Add(tile.Material); } var mesh = this.GetComponent <MeshFilter>().mesh; meshData.BuildMesh(mesh); this.GetComponent <Renderer>().materials = materials.ToArray(); }
/// <summary> /// Resizes all component arrays to contain at least maxSize amount of objects /// </summary> public void SetComponentArraySize(int maxSize) { int oldSize = TransformComponents.Length; if (maxSize > oldSize) { TransformComponents.SetSize(maxSize); PhysicsComponents.SetSize(maxSize); CollisionComponents.SetSize(maxSize); MeshComponents.SetSize(maxSize); for (int i = oldSize; i < maxSize; i++) { // Initialize defaults TransformComponents[i].SetDefaults(); CollisionComponents[i].SetDefaults(); MeshComponents[i].SetDefaults(); } } }
void initialize_buffers(DMesh3 mesh, MeshComponents components) { ModifiedV = new DVector <int>(); NewPositions = new DVector <Vector3d>(); OldPositions = new DVector <Vector3d>(); if (mesh.HasVertexNormals && (components & MeshComponents.VertexNormals) != 0) { NewNormals = new DVector <Vector3f>(); OldNormals = new DVector <Vector3f>(); } if (mesh.HasVertexColors && (components & MeshComponents.VertexColors) != 0) { NewColors = new DVector <Vector3f>(); OldColors = new DVector <Vector3f>(); } if (mesh.HasVertexUVs && (components & MeshComponents.VertexUVs) != 0) { NewUVs = new DVector <Vector2f>(); OldUVs = new DVector <Vector2f>(); } }
/// <summary> /// Combines a set of meshes into the target mesh. /// </summary> /// <param name="target">Target.</param> /// <param name="sources">Sources.</param> public static void CombineMeshes(UMAMeshData target, CombineInstance[] sources, bool ignoreBlendShapes = false) { int vertexCount = 0; int bindPoseCount = 0; int transformHierarchyCount = 0; int blendShapeCount = 0; MeshComponents meshComponents = MeshComponents.none; int subMeshCount = FindTargetSubMeshCount(sources); var subMeshTriangleLength = new int[subMeshCount]; AnalyzeSources(sources, subMeshTriangleLength, ref vertexCount, ref bindPoseCount, ref transformHierarchyCount, ref meshComponents, ref blendShapeCount); int[][] submeshTriangles = new int[subMeshCount][]; for (int i = 0; i < subMeshTriangleLength.Length; i++) { submeshTriangles[i] = new int[subMeshTriangleLength[i]]; subMeshTriangleLength[i] = 0; } bool has_normals = (meshComponents & MeshComponents.has_normals) != MeshComponents.none; bool has_tangents = (meshComponents & MeshComponents.has_tangents) != MeshComponents.none; bool has_uv = (meshComponents & MeshComponents.has_uv) != MeshComponents.none; bool has_uv2 = (meshComponents & MeshComponents.has_uv2) != MeshComponents.none; bool has_uv3 = (meshComponents & MeshComponents.has_uv3) != MeshComponents.none; bool has_uv4 = (meshComponents & MeshComponents.has_uv4) != MeshComponents.none; bool has_colors32 = (meshComponents & MeshComponents.has_colors32) != MeshComponents.none; bool has_blendShapes = (meshComponents & MeshComponents.has_blendShapes) != MeshComponents.none; if (ignoreBlendShapes) { has_blendShapes = false; } Vector3[] vertices = EnsureArrayLength(target.vertices, vertexCount); BoneWeight[] boneWeights = EnsureArrayLength(target.unityBoneWeights, vertexCount); Vector3[] normals = has_normals ? EnsureArrayLength(target.normals, vertexCount) : null; Vector4[] tangents = has_tangents ? EnsureArrayLength(target.tangents, vertexCount) : null; Vector2[] uv = has_uv ? EnsureArrayLength(target.uv, vertexCount) : null; Vector2[] uv2 = has_uv2 ? EnsureArrayLength(target.uv2, vertexCount) : null; Vector2[] uv3 = has_uv3 ? EnsureArrayLength(target.uv3, vertexCount) : null; Vector2[] uv4 = has_uv4 ? EnsureArrayLength(target.uv4, vertexCount) : null; Color32[] colors32 = has_colors32 ? EnsureArrayLength(target.colors32, vertexCount) : null; UMABlendShape[] blendShapes = has_blendShapes ? new UMABlendShape[blendShapeCount] : null; UMATransform[] umaTransforms = EnsureArrayLength(target.umaBones, transformHierarchyCount); int boneCount = 0; foreach (var source in sources) { MergeSortedTransforms(umaTransforms, ref boneCount, source.meshData.umaBones); } int vertexIndex = 0; if (bonesCollection == null) { bonesCollection = new Dictionary <int, BoneIndexEntry>(boneCount); } else { bonesCollection.Clear(); } if (bindPoses == null) { bindPoses = new List <Matrix4x4>(bindPoseCount); } else { bindPoses.Clear(); } if (bonesList == null) { bonesList = new List <int>(boneCount); } else { bonesList.Clear(); } int blendShapeIndex = 0; foreach (var source in sources) { vertexCount = source.meshData.vertices.Length; BuildBoneWeights(source.meshData.boneWeights, 0, boneWeights, vertexIndex, vertexCount, source.meshData.boneNameHashes, source.meshData.bindPoses, bonesCollection, bindPoses, bonesList); Array.Copy(source.meshData.vertices, 0, vertices, vertexIndex, vertexCount); if (has_normals) { if (source.meshData.normals != null && source.meshData.normals.Length > 0) { Array.Copy(source.meshData.normals, 0, normals, vertexIndex, vertexCount); } else { FillArray(tangents, vertexIndex, vertexCount, Vector3.zero); } } if (has_tangents) { if (source.meshData.tangents != null && source.meshData.tangents.Length > 0) { Array.Copy(source.meshData.tangents, 0, tangents, vertexIndex, vertexCount); } else { FillArray(tangents, vertexIndex, vertexCount, Vector4.zero); } } if (has_uv) { if (source.meshData.uv != null && source.meshData.uv.Length >= vertexCount) { Array.Copy(source.meshData.uv, 0, uv, vertexIndex, vertexCount); } else { FillArray(uv, vertexIndex, vertexCount, Vector4.zero); } } if (has_uv2) { if (source.meshData.uv2 != null && source.meshData.uv2.Length >= vertexCount) { Array.Copy(source.meshData.uv2, 0, uv2, vertexIndex, vertexCount); } else { FillArray(uv2, vertexIndex, vertexCount, Vector4.zero); } } if (has_uv3) { if (source.meshData.uv3 != null && source.meshData.uv3.Length >= vertexCount) { Array.Copy(source.meshData.uv3, 0, uv3, vertexIndex, vertexCount); } else { FillArray(uv3, vertexIndex, vertexCount, Vector4.zero); } } if (has_uv4) { if (source.meshData.uv4 != null && source.meshData.uv4.Length >= vertexCount) { Array.Copy(source.meshData.uv4, 0, uv4, vertexIndex, vertexCount); } else { FillArray(uv4, vertexIndex, vertexCount, Vector4.zero); } } if (has_colors32) { if (source.meshData.colors32 != null && source.meshData.colors32.Length > 0) { Array.Copy(source.meshData.colors32, 0, colors32, vertexIndex, vertexCount); } else { Color32 white32 = Color.white; FillArray(colors32, vertexIndex, vertexCount, white32); } } if (has_blendShapes) { if (source.meshData.blendShapes != null && source.meshData.blendShapes.Length > 0) { for (int shapeIndex = 0; shapeIndex < source.meshData.blendShapes.Length; shapeIndex++) { bool nameAlreadyExists = false; int i = 0; //Probably this would be better with a dictionary for (i = 0; i < blendShapeIndex; i++) { if (blendShapes [i].shapeName == source.meshData.blendShapes [shapeIndex].shapeName) { nameAlreadyExists = true; break; } } if (nameAlreadyExists) //Lets add the vertices data to the existing blendShape { if (blendShapes [i].frames.Length != source.meshData.blendShapes [shapeIndex].frames.Length) { Debug.LogError("SkinnedMeshCombiner: mesh blendShape frame counts don't match!"); break; } for (int frameIndex = 0; frameIndex < source.meshData.blendShapes [shapeIndex].frames.Length; frameIndex++) { Array.Copy(source.meshData.blendShapes [shapeIndex].frames [frameIndex].deltaVertices, 0, blendShapes [i].frames [frameIndex].deltaVertices, vertexIndex, vertexCount); Array.Copy(source.meshData.blendShapes [shapeIndex].frames [frameIndex].deltaNormals, 0, blendShapes [i].frames [frameIndex].deltaNormals, vertexIndex, vertexCount); Array.Copy(source.meshData.blendShapes [shapeIndex].frames [frameIndex].deltaTangents, 0, blendShapes [i].frames [frameIndex].deltaTangents, vertexIndex, vertexCount); } } else { blendShapes [blendShapeIndex] = new UMABlendShape(); blendShapes [blendShapeIndex].shapeName = source.meshData.blendShapes [shapeIndex].shapeName; blendShapes [blendShapeIndex].frames = new UMABlendFrame[source.meshData.blendShapes [shapeIndex].frames.Length]; for (int frameIndex = 0; frameIndex < source.meshData.blendShapes [shapeIndex].frames.Length; frameIndex++) { blendShapes [blendShapeIndex].frames [frameIndex] = new UMABlendFrame(vertices.Length); blendShapes [blendShapeIndex].frames [frameIndex].frameWeight = source.meshData.blendShapes [shapeIndex].frames [frameIndex].frameWeight; Array.Copy(source.meshData.blendShapes [shapeIndex].frames [frameIndex].deltaVertices, 0, blendShapes [blendShapeIndex].frames [frameIndex].deltaVertices, vertexIndex, vertexCount); Array.Copy(source.meshData.blendShapes [shapeIndex].frames [frameIndex].deltaNormals, 0, blendShapes [blendShapeIndex].frames [frameIndex].deltaNormals, vertexIndex, vertexCount); Array.Copy(source.meshData.blendShapes [shapeIndex].frames [frameIndex].deltaTangents, 0, blendShapes [blendShapeIndex].frames [frameIndex].deltaTangents, vertexIndex, vertexCount); } blendShapeIndex++; } } } } for (int i = 0; i < source.meshData.subMeshCount; i++) { if (source.targetSubmeshIndices[i] >= 0) { int[] subTriangles = source.meshData.submeshes[i].triangles; int triangleLength = subTriangles.Length; int destMesh = source.targetSubmeshIndices[i]; CopyIntArrayAdd(subTriangles, 0, submeshTriangles[destMesh], subMeshTriangleLength[destMesh], triangleLength, vertexIndex); subMeshTriangleLength[destMesh] += triangleLength; } } vertexIndex += vertexCount; } vertexCount = vertexIndex; // fill in new values. target.vertexCount = vertexCount; target.vertices = vertices; target.unityBoneWeights = boneWeights; target.bindPoses = bindPoses.ToArray(); target.normals = normals; target.tangents = tangents; target.uv = uv; target.uv2 = uv2; target.uv3 = uv3; target.uv4 = uv4; target.colors32 = colors32; if (has_blendShapes) { target.blendShapes = blendShapes; } target.subMeshCount = subMeshCount; target.submeshes = new SubMeshTriangles[subMeshCount]; target.umaBones = umaTransforms; target.umaBoneCount = boneCount; for (int i = 0; i < subMeshCount; i++) { target.submeshes[i].triangles = submeshTriangles[i]; } target.boneNameHashes = bonesList.ToArray(); }
private static void AnalyzeSources(CombineInstance[] sources, int[] subMeshTriangleLength, ref int vertexCount, ref int bindPoseCount, ref int transformHierarchyCount, ref MeshComponents meshComponents, ref int blendShapeCount) { HashSet <string> blendShapeNames = new HashSet <string> (); //Hash to find all the unique blendshape names for (int i = 0; i < subMeshTriangleLength.Length; i++) { subMeshTriangleLength[i] = 0; } foreach (var source in sources) { vertexCount += source.meshData.vertices.Length; bindPoseCount += source.meshData.bindPoses.Length; transformHierarchyCount += source.meshData.umaBones.Length; if (source.meshData.normals != null && source.meshData.normals.Length != 0) { meshComponents |= MeshComponents.has_normals; } if (source.meshData.tangents != null && source.meshData.tangents.Length != 0) { meshComponents |= MeshComponents.has_tangents; } if (source.meshData.uv != null && source.meshData.uv.Length != 0) { meshComponents |= MeshComponents.has_uv; } if (source.meshData.uv2 != null && source.meshData.uv2.Length != 0) { meshComponents |= MeshComponents.has_uv2; } if (source.meshData.uv3 != null && source.meshData.uv3.Length != 0) { meshComponents |= MeshComponents.has_uv3; } if (source.meshData.uv4 != null && source.meshData.uv4.Length != 0) { meshComponents |= MeshComponents.has_uv4; } if (source.meshData.colors32 != null && source.meshData.colors32.Length != 0) { meshComponents |= MeshComponents.has_colors32; } //If we find a blendshape on this mesh then lets add it to the blendShapeNames hash to get all the unique names if (source.meshData.blendShapes != null && source.meshData.blendShapes.Length != 0) { for (int shapeIndex = 0; shapeIndex < source.meshData.blendShapes.Length; shapeIndex++) { blendShapeNames.Add(source.meshData.blendShapes [shapeIndex].shapeName); } } for (int i = 0; i < source.meshData.subMeshCount; i++) { if (source.targetSubmeshIndices[i] >= 0) { int triangleLength = source.meshData.submeshes[i].triangles.Length; subMeshTriangleLength[source.targetSubmeshIndices[i]] += triangleLength; } } } //If our blendshape hash has at least 1 name, then we have a blendshape! if (blendShapeNames.Count > 0) { blendShapeCount = blendShapeNames.Count; meshComponents |= MeshComponents.has_blendShapes; } }
private static void AnalyzeSources(CombineInstance[] sources, int[] subMeshTriangleLength, ref int vertexCount, ref int bindPoseCount, ref int transformHierarchyCount, ref MeshComponents meshComponents) { for (int i = 0; i < subMeshTriangleLength.Length; i++) { subMeshTriangleLength[i] = 0; } foreach (var source in sources) { vertexCount += source.meshData.vertices.Length; bindPoseCount += source.meshData.bindPoses.Length; transformHierarchyCount += source.meshData.umaBones.Length; if (source.meshData.normals != null && source.meshData.normals.Length != 0) { meshComponents |= MeshComponents.has_normals; } if (source.meshData.tangents != null && source.meshData.tangents.Length != 0) { meshComponents |= MeshComponents.has_tangents; } if (source.meshData.uv != null && source.meshData.uv.Length != 0) { meshComponents |= MeshComponents.has_uv; } if (source.meshData.uv2 != null && source.meshData.uv2.Length != 0) { meshComponents |= MeshComponents.has_uv2; } if (source.meshData.uv3 != null && source.meshData.uv3.Length != 0) { meshComponents |= MeshComponents.has_uv3; } if (source.meshData.uv4 != null && source.meshData.uv4.Length != 0) { meshComponents |= MeshComponents.has_uv4; } if (source.meshData.colors32 != null && source.meshData.colors32.Length != 0) { meshComponents |= MeshComponents.has_colors32; } if (source.meshData.clothSkinningSerialized != null && source.meshData.clothSkinningSerialized.Length != 0) { meshComponents |= MeshComponents.has_clothSkinning; } for (int i = 0; i < source.meshData.subMeshCount; i++) { if (source.targetSubmeshIndices[i] >= 0) { int triangleLength = (source.triangleMask == null) ? source.meshData.submeshes[i].triangles.Length : (source.meshData.submeshes[i].triangles.Length - (UMAUtils.GetCardinality(source.triangleMask[i]) * 3)); subMeshTriangleLength[source.targetSubmeshIndices[i]] += triangleLength; } } } }
/// <summary> /// Combines a set of meshes into the target mesh. /// </summary> /// <param name="target">Target.</param> /// <param name="sources">Sources.</param> /// <param name="blendShapeSettings">BlendShape Settings.</param> public static void CombineMeshes(UMAMeshData target, CombineInstance[] sources, UMAData.BlendShapeSettings blendShapeSettings = null) { if (blendShapeSettings == null) { blendShapeSettings = new UMAData.BlendShapeSettings(); } int vertexCount = 0; int bindPoseCount = 0; int transformHierarchyCount = 0; int blendShapeCount = 0; MeshComponents meshComponents = MeshComponents.none; int subMeshCount = FindTargetSubMeshCount(sources); var subMeshTriangleLength = new int[subMeshCount]; AnalyzeSources(sources, subMeshTriangleLength, ref vertexCount, ref bindPoseCount, ref transformHierarchyCount, ref meshComponents, ref blendShapeCount); int[][] submeshTriangles = new int[subMeshCount][]; for (int i = 0; i < subMeshTriangleLength.Length; i++) { submeshTriangles[i] = target.GetSubmeshBuffer(subMeshTriangleLength[i], i); subMeshTriangleLength[i] = 0; } bool has_normals = (meshComponents & MeshComponents.has_normals) != MeshComponents.none; bool has_tangents = (meshComponents & MeshComponents.has_tangents) != MeshComponents.none; bool has_uv = (meshComponents & MeshComponents.has_uv) != MeshComponents.none; bool has_uv2 = (meshComponents & MeshComponents.has_uv2) != MeshComponents.none; bool has_uv3 = (meshComponents & MeshComponents.has_uv3) != MeshComponents.none; bool has_uv4 = (meshComponents & MeshComponents.has_uv4) != MeshComponents.none; bool has_colors32 = (meshComponents & MeshComponents.has_colors32) != MeshComponents.none; bool has_blendShapes = (meshComponents & MeshComponents.has_blendShapes) != MeshComponents.none; if (blendShapeSettings.ignoreBlendShapes) { has_blendShapes = false; } bool has_clothSkinning = (meshComponents & MeshComponents.has_clothSkinning) != MeshComponents.none; Vector3[] vertices = EnsureArrayLength(target.vertices, vertexCount); BoneWeight[] boneWeights = EnsureArrayLength(target.unityBoneWeights, vertexCount); Vector3[] normals = has_normals ? EnsureArrayLength(target.normals, vertexCount) : null; Vector4[] tangents = has_tangents ? EnsureArrayLength(target.tangents, vertexCount) : null; Vector2[] uv = has_uv ? EnsureArrayLength(target.uv, vertexCount) : null; Vector2[] uv2 = has_uv2 ? EnsureArrayLength(target.uv2, vertexCount) : null; Vector2[] uv3 = has_uv3 ? EnsureArrayLength(target.uv3, vertexCount) : null; Vector2[] uv4 = has_uv4 ? EnsureArrayLength(target.uv4, vertexCount) : null; Color32[] colors32 = has_colors32 ? EnsureArrayLength(target.colors32, vertexCount) : null; UMABlendShape[] blendShapes = has_blendShapes ? new UMABlendShape[blendShapeCount] : null; UMATransform[] umaTransforms = EnsureArrayLength(target.umaBones, transformHierarchyCount); ClothSkinningCoefficient[] clothSkinning = has_clothSkinning ? EnsureArrayLength(target.clothSkinning, vertexCount) : null; Dictionary <Vector3, int> clothVertices = has_clothSkinning ? new Dictionary <Vector3, int>(vertexCount) : null; Dictionary <Vector3, int> localClothVertices = has_clothSkinning ? new Dictionary <Vector3, int>(vertexCount) : null; int boneCount = 0; foreach (var source in sources) { MergeSortedTransforms(umaTransforms, ref boneCount, source.meshData.umaBones); } int vertexIndex = 0; if (bonesCollection == null) { bonesCollection = new Dictionary <int, BoneIndexEntry>(boneCount); } else { bonesCollection.Clear(); } if (bindPoses == null) { bindPoses = new List <Matrix4x4>(bindPoseCount); } else { bindPoses.Clear(); } if (bonesList == null) { bonesList = new List <int>(boneCount); } else { bonesList.Clear(); } int blendShapeIndex = 0; foreach (var source in sources) { int sourceVertexCount = source.meshData.vertices.Length; BuildBoneWeights(source.meshData.boneWeights, 0, boneWeights, vertexIndex, sourceVertexCount, source.meshData.boneNameHashes, source.meshData.bindPoses, bonesCollection, bindPoses, bonesList); Array.Copy(source.meshData.vertices, 0, vertices, vertexIndex, sourceVertexCount); if (has_normals) { if (source.meshData.normals != null && source.meshData.normals.Length > 0) { Array.Copy(source.meshData.normals, 0, normals, vertexIndex, sourceVertexCount); } else { FillArray(tangents, vertexIndex, sourceVertexCount, Vector3.zero); } } if (has_tangents) { if (source.meshData.tangents != null && source.meshData.tangents.Length > 0) { Array.Copy(source.meshData.tangents, 0, tangents, vertexIndex, sourceVertexCount); } else { FillArray(tangents, vertexIndex, sourceVertexCount, Vector4.zero); } } if (has_uv) { if (source.meshData.uv != null && source.meshData.uv.Length >= sourceVertexCount) { Array.Copy(source.meshData.uv, 0, uv, vertexIndex, sourceVertexCount); } else { FillArray(uv, vertexIndex, sourceVertexCount, Vector4.zero); } } if (has_uv2) { if (source.meshData.uv2 != null && source.meshData.uv2.Length >= sourceVertexCount) { Array.Copy(source.meshData.uv2, 0, uv2, vertexIndex, sourceVertexCount); } else { FillArray(uv2, vertexIndex, sourceVertexCount, Vector4.zero); } } if (has_uv3) { if (source.meshData.uv3 != null && source.meshData.uv3.Length >= sourceVertexCount) { Array.Copy(source.meshData.uv3, 0, uv3, vertexIndex, sourceVertexCount); } else { FillArray(uv3, vertexIndex, sourceVertexCount, Vector4.zero); } } if (has_uv4) { if (source.meshData.uv4 != null && source.meshData.uv4.Length >= sourceVertexCount) { Array.Copy(source.meshData.uv4, 0, uv4, vertexIndex, sourceVertexCount); } else { FillArray(uv4, vertexIndex, sourceVertexCount, Vector4.zero); } } if (has_colors32) { if (source.meshData.colors32 != null && source.meshData.colors32.Length > 0) { Array.Copy(source.meshData.colors32, 0, colors32, vertexIndex, sourceVertexCount); } else { Color32 white32 = Color.white; FillArray(colors32, vertexIndex, sourceVertexCount, white32); } } if (has_blendShapes) { if (source.meshData.blendShapes != null && source.meshData.blendShapes.Length > 0) { for (int shapeIndex = 0; shapeIndex < source.meshData.blendShapes.Length; shapeIndex++) { #region BlendShape Baking if (blendShapeSettings.bakeBlendShapes != null && blendShapeSettings.bakeBlendShapes.Count > 0) { // If there are names in the bakeBlendShape dictionary and we find them in the meshData blendshape list, then lets bake them instead of adding them. UMABlendShape currentShape = source.meshData.blendShapes[shapeIndex]; if (blendShapeSettings.bakeBlendShapes.ContainsKey(currentShape.shapeName)) { float weight = blendShapeSettings.bakeBlendShapes[currentShape.shapeName] * 100.0f; if (weight <= 0f) { continue; // Baking in nothing, so skip it entirely } // Let's find the frame this weight is in int frameIndex; int prevIndex; for (frameIndex = 0; frameIndex < currentShape.frames.Length; frameIndex++) { if (currentShape.frames[frameIndex].frameWeight >= weight) { break; } } // Let's calculate the weight for the frame we're in float frameWeight = 1f; float prevWeight = 0f; bool doLerp = false; // Weight is higher than the last frame, shape is over 100% if (frameIndex >= currentShape.frames.Length) { frameIndex = currentShape.frames.Length - 1; frameWeight = (weight / currentShape.frames[frameIndex].frameWeight); } else if (frameIndex > 0) { doLerp = true; prevWeight = currentShape.frames[frameIndex - 1].frameWeight; frameWeight = ((weight - prevWeight) / (currentShape.frames[frameIndex].frameWeight - prevWeight)); prevWeight = 1f - frameWeight; } else { frameWeight = (weight / currentShape.frames[frameIndex].frameWeight); } prevIndex = frameIndex - 1; // The blend shape frames lerp between the deltas of two adjacent frames. int vertIndex = vertexIndex; for (int bakeIndex = 0; bakeIndex < currentShape.frames[frameIndex].deltaVertices.Length; bakeIndex++, vertIndex++) { // Add the current frame's deltas vertices[vertIndex] += currentShape.frames[frameIndex].deltaVertices[bakeIndex] * frameWeight; // Add in the previous frame's deltas if (doLerp) { vertices[vertIndex] += currentShape.frames[prevIndex].deltaVertices[bakeIndex] * prevWeight; } } if (has_normals) { vertIndex = vertexIndex; for (int bakeIndex = 0; bakeIndex < currentShape.frames[frameIndex].deltaNormals.Length; bakeIndex++, vertIndex++) { normals[vertIndex] += currentShape.frames[frameIndex].deltaNormals[bakeIndex] * frameWeight; if (doLerp) { normals[vertIndex] += currentShape.frames[prevIndex].deltaNormals[bakeIndex] * prevWeight; } } } if (has_tangents) { vertIndex = vertexIndex; for (int bakeIndex = 0; bakeIndex < currentShape.frames[frameIndex].deltaTangents.Length; bakeIndex++, vertIndex++) { tangents[vertIndex] += (Vector4)currentShape.frames[frameIndex].deltaTangents[bakeIndex] * frameWeight; if (doLerp) { tangents[vertIndex] += (Vector4)currentShape.frames[prevIndex].deltaTangents[bakeIndex] * prevWeight; } } } continue; // If we bake then don't perform the rest of this interation of the loop. } } #endregion bool nameAlreadyExists = false; int i = 0; //Probably this would be better with a dictionary for (i = 0; i < blendShapeIndex; i++) { if (blendShapes[i].shapeName == source.meshData.blendShapes[shapeIndex].shapeName) { nameAlreadyExists = true; break; } } if (nameAlreadyExists) //Lets add the vertices data to the existing blendShape { if (blendShapes[i].frames.Length != source.meshData.blendShapes[shapeIndex].frames.Length) { Debug.LogError("SkinnedMeshCombiner: mesh blendShape frame counts don't match!"); break; } for (int frameIndex = 0; frameIndex < source.meshData.blendShapes[shapeIndex].frames.Length; frameIndex++) { Array.Copy(source.meshData.blendShapes[shapeIndex].frames[frameIndex].deltaVertices, 0, blendShapes[i].frames[frameIndex].deltaVertices, vertexIndex, sourceVertexCount); Array.Copy(source.meshData.blendShapes[shapeIndex].frames[frameIndex].deltaNormals, 0, blendShapes[i].frames[frameIndex].deltaNormals, vertexIndex, sourceVertexCount); Array.Copy(source.meshData.blendShapes[shapeIndex].frames[frameIndex].deltaTangents, 0, blendShapes[i].frames[frameIndex].deltaTangents, vertexIndex, sourceVertexCount); } } else { blendShapes[blendShapeIndex] = new UMABlendShape(); blendShapes[blendShapeIndex].shapeName = source.meshData.blendShapes[shapeIndex].shapeName; blendShapes[blendShapeIndex].frames = new UMABlendFrame[source.meshData.blendShapes[shapeIndex].frames.Length]; for (int frameIndex = 0; frameIndex < source.meshData.blendShapes[shapeIndex].frames.Length; frameIndex++) { blendShapes[blendShapeIndex].frames[frameIndex] = new UMABlendFrame(vertexCount); blendShapes[blendShapeIndex].frames[frameIndex].frameWeight = source.meshData.blendShapes[shapeIndex].frames[frameIndex].frameWeight; Array.Copy(source.meshData.blendShapes[shapeIndex].frames[frameIndex].deltaVertices, 0, blendShapes[blendShapeIndex].frames[frameIndex].deltaVertices, vertexIndex, sourceVertexCount); Array.Copy(source.meshData.blendShapes[shapeIndex].frames[frameIndex].deltaNormals, 0, blendShapes[blendShapeIndex].frames[frameIndex].deltaNormals, vertexIndex, sourceVertexCount); Array.Copy(source.meshData.blendShapes[shapeIndex].frames[frameIndex].deltaTangents, 0, blendShapes[blendShapeIndex].frames[frameIndex].deltaTangents, vertexIndex, sourceVertexCount); } blendShapeIndex++; } } } } if (has_clothSkinning) { localClothVertices.Clear(); if (source.meshData.clothSkinningSerialized != null && source.meshData.clothSkinningSerialized.Length > 0) { for (int i = 0; i < source.meshData.vertexCount; i++) { var vertice = source.meshData.vertices[i]; if (!localClothVertices.ContainsKey(vertice)) { int localCount = localClothVertices.Count; localClothVertices.Add(vertice, localCount); if (!clothVertices.ContainsKey(vertice)) { ConvertData(ref source.meshData.clothSkinningSerialized[localCount], ref clothSkinning[clothVertices.Count]); clothVertices.Add(vertice, clothVertices.Count); } else { ConvertData(ref source.meshData.clothSkinningSerialized[localCount], ref clothSkinning[clothVertices[vertice]]); } } } } else { for (int i = 0; i < source.meshData.vertexCount; i++) { var vertice = source.meshData.vertices[i]; if (!clothVertices.ContainsKey(vertice)) { clothSkinning[clothVertices.Count].maxDistance = 0; clothSkinning[clothVertices.Count].collisionSphereDistance = float.MaxValue; clothVertices.Add(vertice, clothVertices.Count); localClothVertices.Add(vertice, clothVertices.Count); } } } } for (int i = 0; i < source.meshData.subMeshCount; i++) { if (source.targetSubmeshIndices[i] >= 0) { int[] subTriangles = source.meshData.submeshes[i].triangles; int triangleLength = subTriangles.Length; int destMesh = source.targetSubmeshIndices[i]; if (source.triangleMask == null) { CopyIntArrayAdd(subTriangles, 0, submeshTriangles[destMesh], subMeshTriangleLength[destMesh], triangleLength, vertexIndex); subMeshTriangleLength[destMesh] += triangleLength; } else { MaskedCopyIntArrayAdd(subTriangles, 0, submeshTriangles[destMesh], subMeshTriangleLength[destMesh], triangleLength, vertexIndex, source.triangleMask[i]); subMeshTriangleLength[destMesh] += (triangleLength - (UMAUtils.GetCardinality(source.triangleMask[i]) * 3)); } } } vertexIndex += sourceVertexCount; } if (vertexCount != vertexIndex) { Debug.LogError("Combined vertices size didn't match precomputed value!"); } // fill in new values. target.vertexCount = vertexCount; target.vertices = vertices; target.unityBoneWeights = boneWeights; target.bindPoses = bindPoses.ToArray(); target.normals = normals; target.tangents = tangents; target.uv = uv; target.uv2 = uv2; target.uv3 = uv3; target.uv4 = uv4; target.colors32 = colors32; if (has_blendShapes) { target.blendShapes = blendShapes; } if (has_clothSkinning) { Array.Resize(ref clothSkinning, clothVertices.Count); } target.clothSkinning = clothSkinning; target.subMeshCount = subMeshCount; target.submeshes = new SubMeshTriangles[subMeshCount]; target.umaBones = umaTransforms; target.umaBoneCount = boneCount; for (int i = 0; i < subMeshCount; i++) { target.submeshes[i].triangles = submeshTriangles[i]; } target.boneNameHashes = bonesList.ToArray(); }
/// <summary> /// Combines a set of meshes into the target mesh. /// </summary> /// <param name="target">Target.</param> /// <param name="sources">Sources.</param> /// <param name="blendShapeSettings">BlendShape Settings.</param> public static void CombineMeshes(UMAMeshData target, CombineInstance[] sources, BlendShapeSettings blendShapeSettings = null) { if (blendShapeSettings == null) { blendShapeSettings = new BlendShapeSettings(); } int vertexCount = 0; int bindPoseCount = 0; int transformHierarchyCount = 0; Dictionary <string, BlendShapeVertexData> blendShapeNames = new Dictionary <string, BlendShapeVertexData>(); MeshComponents meshComponents = MeshComponents.none; int subMeshCount = FindTargetSubMeshCount(sources); var subMeshTriangleLength = new int[subMeshCount]; AnalyzeSources(sources, subMeshTriangleLength, ref vertexCount, ref bindPoseCount, ref transformHierarchyCount, ref meshComponents); if (!blendShapeSettings.ignoreBlendShapes) { AnalyzeBlendShapeSources(sources, blendShapeSettings, ref meshComponents, out blendShapeNames); } int[][] submeshTriangles = new int[subMeshCount][]; for (int i = 0; i < subMeshTriangleLength.Length; i++) { submeshTriangles[i] = target.GetSubmeshBuffer(subMeshTriangleLength[i], i); subMeshTriangleLength[i] = 0; } bool has_normals = (meshComponents & MeshComponents.has_normals) != MeshComponents.none; bool has_tangents = (meshComponents & MeshComponents.has_tangents) != MeshComponents.none; bool has_uv = (meshComponents & MeshComponents.has_uv) != MeshComponents.none; bool has_uv2 = (meshComponents & MeshComponents.has_uv2) != MeshComponents.none; bool has_uv3 = (meshComponents & MeshComponents.has_uv3) != MeshComponents.none; bool has_uv4 = (meshComponents & MeshComponents.has_uv4) != MeshComponents.none; bool has_colors32 = (meshComponents & MeshComponents.has_colors32) != MeshComponents.none; bool has_blendShapes = (meshComponents & MeshComponents.has_blendShapes) != MeshComponents.none; if (blendShapeSettings.ignoreBlendShapes) { has_blendShapes = false; } bool has_clothSkinning = (meshComponents & MeshComponents.has_clothSkinning) != MeshComponents.none; #if UNITY_2019_3_OR_NEWER if (nativeBoneWeights.Length < vertexCount) { if (nativeBoneWeights.IsCreated) { nativeBoneWeights.Dispose(); } nativeBoneWeights = new NativeArray <BoneWeight>(vertexCount, Allocator.Persistent); } #else BoneWeight[] boneWeights = EnsureArrayLength(target.unityBoneWeights, vertexCount); #endif Vector3[] vertices = EnsureArrayLength(target.vertices, vertexCount); Vector3[] normals = has_normals ? EnsureArrayLength(target.normals, vertexCount) : null; Vector4[] tangents = has_tangents ? EnsureArrayLength(target.tangents, vertexCount) : null; Vector2[] uv = has_uv ? EnsureArrayLength(target.uv, vertexCount) : null; Vector2[] uv2 = has_uv2 ? EnsureArrayLength(target.uv2, vertexCount) : null; Vector2[] uv3 = has_uv3 ? EnsureArrayLength(target.uv3, vertexCount) : null; Vector2[] uv4 = has_uv4 ? EnsureArrayLength(target.uv4, vertexCount) : null; Color32[] colors32 = has_colors32 ? EnsureArrayLength(target.colors32, vertexCount) : null; UMABlendShape[] blendShapes = has_blendShapes ? new UMABlendShape[blendShapeNames.Keys.Count] : null; UMATransform[] umaTransforms = EnsureArrayLength(target.umaBones, transformHierarchyCount); ClothSkinningCoefficient[] clothSkinning = has_clothSkinning ? EnsureArrayLength(target.clothSkinning, vertexCount) : null; Dictionary <Vector3, int> clothVertices = has_clothSkinning ? new Dictionary <Vector3, int>(vertexCount) : null; Dictionary <Vector3, int> localClothVertices = has_clothSkinning ? new Dictionary <Vector3, int>(vertexCount) : null; InitializeBlendShapeData(ref vertexCount, blendShapeNames, blendShapes); int boneCount = 0; foreach (var source in sources) { MergeSortedTransforms(umaTransforms, ref boneCount, source.meshData.umaBones); } int vertexIndex = 0; if (bonesCollection == null) { bonesCollection = new Dictionary <int, BoneIndexEntry>(boneCount); } else { bonesCollection.Clear(); } if (bindPoses == null) { bindPoses = new List <Matrix4x4>(bindPoseCount); } else { bindPoses.Clear(); } if (bonesList == null) { bonesList = new List <int>(boneCount); } else { bonesList.Clear(); } foreach (var source in sources) { int sourceVertexCount = source.meshData.vertices.Length; #if UNITY_2019_3_OR_NEWER BuildBoneWeights(source.meshData.boneWeights, 0, nativeBoneWeights, vertexIndex, sourceVertexCount, source.meshData.boneNameHashes, source.meshData.bindPoses, bonesCollection, bindPoses, bonesList); #else BuildBoneWeights(source.meshData.boneWeights, 0, boneWeights, vertexIndex, sourceVertexCount, source.meshData.boneNameHashes, source.meshData.bindPoses, bonesCollection, bindPoses, bonesList); #endif Array.Copy(source.meshData.vertices, 0, vertices, vertexIndex, sourceVertexCount); if (has_normals) { if (source.meshData.normals != null && source.meshData.normals.Length > 0) { Array.Copy(source.meshData.normals, 0, normals, vertexIndex, sourceVertexCount); } else { FillArray(tangents, vertexIndex, sourceVertexCount, Vector3.zero); } } if (has_tangents) { if (source.meshData.tangents != null && source.meshData.tangents.Length > 0) { Array.Copy(source.meshData.tangents, 0, tangents, vertexIndex, sourceVertexCount); } else { FillArray(tangents, vertexIndex, sourceVertexCount, Vector4.zero); } } if (has_uv) { if (source.meshData.uv != null && source.meshData.uv.Length >= sourceVertexCount) { Array.Copy(source.meshData.uv, 0, uv, vertexIndex, sourceVertexCount); } else { FillArray(uv, vertexIndex, sourceVertexCount, Vector4.zero); } } if (has_uv2) { if (source.meshData.uv2 != null && source.meshData.uv2.Length >= sourceVertexCount) { Array.Copy(source.meshData.uv2, 0, uv2, vertexIndex, sourceVertexCount); } else { FillArray(uv2, vertexIndex, sourceVertexCount, Vector4.zero); } } if (has_uv3) { if (source.meshData.uv3 != null && source.meshData.uv3.Length >= sourceVertexCount) { Array.Copy(source.meshData.uv3, 0, uv3, vertexIndex, sourceVertexCount); } else { FillArray(uv3, vertexIndex, sourceVertexCount, Vector4.zero); } } if (has_uv4) { if (source.meshData.uv4 != null && source.meshData.uv4.Length >= sourceVertexCount) { Array.Copy(source.meshData.uv4, 0, uv4, vertexIndex, sourceVertexCount); } else { FillArray(uv4, vertexIndex, sourceVertexCount, Vector4.zero); } } if (has_colors32) { if (source.meshData.colors32 != null && source.meshData.colors32.Length > 0) { Array.Copy(source.meshData.colors32, 0, colors32, vertexIndex, sourceVertexCount); } else { Color32 white32 = Color.white; FillArray(colors32, vertexIndex, sourceVertexCount, white32); } } if (has_blendShapes) { if (source.meshData.blendShapes != null && source.meshData.blendShapes.Length > 0) { int sourceBlendShapeLength = source.meshData.blendShapes.Length; for (int shapeIndex = 0; shapeIndex < sourceBlendShapeLength; shapeIndex++) { string shapeName = source.meshData.blendShapes[shapeIndex].shapeName; //If we aren't loading all blendshapes and we don't find the blendshape name in the list of explicit blendshapes to combine, then skip to the next one. if (!blendShapeSettings.loadAllBlendShapes && !blendShapeSettings.blendShapes.ContainsKey(shapeName)) { continue; } #region BlendShape Baking if (BakeBlendShape(blendShapeSettings.blendShapes, source.meshData.blendShapes[shapeIndex], ref vertexIndex, vertices, normals, tangents, has_normals, has_tangents)) { continue; //If we baked this blendshape, then continue to the next one and skip adding the regular blendshape. } #endregion //If our dictionary contains the shape name, which it should if (blendShapeNames.ContainsKey(shapeName)) { UMABlendShape[] sourceBlendShapes = source.meshData.blendShapes; int i = blendShapeNames[shapeName].index; if (blendShapes[i].frames.Length != sourceBlendShapes[shapeIndex].frames.Length) { if (Debug.isDebugBuild) { Debug.LogError("SkinnedMeshCombiner: mesh blendShape frame counts don't match!"); } break; } for (int frameIndex = 0; frameIndex < sourceBlendShapes[shapeIndex].frames.Length; frameIndex++) { Array.Copy(sourceBlendShapes[shapeIndex].frames[frameIndex].deltaVertices, 0, blendShapes[i].frames[frameIndex].deltaVertices, vertexIndex, sourceVertexCount); Vector3[] sourceDeltaNormals = sourceBlendShapes[shapeIndex].frames[frameIndex].deltaNormals; Vector3[] sourceDeltaTangents = sourceBlendShapes[shapeIndex].frames[frameIndex].deltaTangents; //if out dictionary says at least one source has normals or tangents and the current source has normals or tangents then copy them. if (blendShapeNames[shapeName].hasNormals && sourceDeltaNormals.Length > 0) { Array.Copy(sourceDeltaNormals, 0, blendShapes[i].frames[frameIndex].deltaNormals, vertexIndex, sourceVertexCount); } if (blendShapeNames[shapeName].hasTangents && sourceDeltaTangents.Length > 0) { Array.Copy(sourceDeltaTangents, 0, blendShapes[i].frames[frameIndex].deltaTangents, vertexIndex, sourceVertexCount); } } } else { if (Debug.isDebugBuild) { Debug.LogError("BlendShape " + shapeName + " not found in dictionary!"); } } } } } if (has_clothSkinning) { localClothVertices.Clear(); if (source.meshData.clothSkinningSerialized != null && source.meshData.clothSkinningSerialized.Length > 0) { for (int i = 0; i < source.meshData.vertexCount; i++) { var vertice = source.meshData.vertices[i]; if (!localClothVertices.ContainsKey(vertice)) { int localCount = localClothVertices.Count; localClothVertices.Add(vertice, localCount); if (!clothVertices.ContainsKey(vertice)) { ConvertData(ref source.meshData.clothSkinningSerialized[localCount], ref clothSkinning[clothVertices.Count]); clothVertices.Add(vertice, clothVertices.Count); } else { ConvertData(ref source.meshData.clothSkinningSerialized[localCount], ref clothSkinning[clothVertices[vertice]]); } } } } else { for (int i = 0; i < source.meshData.vertexCount; i++) { var vertice = source.meshData.vertices[i]; if (!clothVertices.ContainsKey(vertice)) { clothSkinning[clothVertices.Count].maxDistance = 0; clothSkinning[clothVertices.Count].collisionSphereDistance = float.MaxValue; clothVertices.Add(vertice, clothVertices.Count); localClothVertices.Add(vertice, clothVertices.Count); } } } } for (int i = 0; i < source.meshData.subMeshCount; i++) { if (source.targetSubmeshIndices[i] >= 0) { int[] subTriangles = source.meshData.submeshes[i].triangles; int triangleLength = subTriangles.Length; int destMesh = source.targetSubmeshIndices[i]; if (source.triangleMask == null) { CopyIntArrayAdd(subTriangles, 0, submeshTriangles[destMesh], subMeshTriangleLength[destMesh], triangleLength, vertexIndex); subMeshTriangleLength[destMesh] += triangleLength; } else { MaskedCopyIntArrayAdd(subTriangles, 0, submeshTriangles[destMesh], subMeshTriangleLength[destMesh], triangleLength, vertexIndex, source.triangleMask[i]); subMeshTriangleLength[destMesh] += (triangleLength - (UMAUtils.GetCardinality(source.triangleMask[i]) * 3)); } } } vertexIndex += sourceVertexCount; } if (vertexCount != vertexIndex) { if (Debug.isDebugBuild) { Debug.LogError("Combined vertices size didn't match precomputed value!"); } } // fill in new values. target.vertexCount = vertexCount; target.vertices = vertices; #if UNITY_2019_3_OR_NEWER target.unityBoneWeights = nativeBoneWeights.GetSubArray(0, vertexCount).ToArray(); #else target.unityBoneWeights = boneWeights; #endif target.bindPoses = bindPoses.ToArray(); target.normals = normals; target.tangents = tangents; target.uv = uv; target.uv2 = uv2; target.uv3 = uv3; target.uv4 = uv4; target.colors32 = colors32; if (has_blendShapes) { target.blendShapes = blendShapes; } if (has_clothSkinning) { Array.Resize(ref clothSkinning, clothVertices.Count); } target.clothSkinning = clothSkinning; target.subMeshCount = subMeshCount; target.submeshes = new SubMeshTriangles[subMeshCount]; target.umaBones = umaTransforms; target.umaBoneCount = boneCount; for (int i = 0; i < subMeshCount; i++) { target.submeshes[i].triangles = submeshTriangles[i]; } target.boneNameHashes = bonesList.ToArray(); }
private static void AnalyzeBlendShapeSources(CombineInstance[] sources, BlendShapeSettings blendShapeSettings, ref MeshComponents meshComponents, out Dictionary <string, BlendShapeVertexData> blendShapeNames) { blendShapeNames = new Dictionary <string, BlendShapeVertexData>(); if (blendShapeSettings.ignoreBlendShapes) { return; } int bakedCount = 0; foreach (var source in sources) { //If we find a blendshape on this mesh then lets add it to the blendShapeNames hash to get all the unique names if (source.meshData.blendShapes == null) { continue; } if (source.meshData.blendShapes.Length == 0) { continue; } for (int shapeIndex = 0; shapeIndex < source.meshData.blendShapes.Length; shapeIndex++) { string shapeName = source.meshData.blendShapes[shapeIndex].shapeName; //if we are baking this blendshape then skip and don't add to the blendshape names. BlendShapeData data; if (blendShapeSettings.blendShapes.TryGetValue(shapeName, out data)) { if (data.isBaked) { bakedCount++; continue; } } if (!blendShapeNames.ContainsKey(shapeName)) { BlendShapeVertexData newData = new BlendShapeVertexData(); blendShapeNames.Add(shapeName, newData); } blendShapeNames[shapeName].hasNormals |= source.meshData.blendShapes[shapeIndex].frames[0].HasNormals(); blendShapeNames[shapeName].hasTangents |= source.meshData.blendShapes[shapeIndex].frames[0].HasTangents(); if (source.meshData.blendShapes[shapeIndex].frames.Length > blendShapeNames[shapeName].frameCount) { blendShapeNames[shapeName].frameCount = source.meshData.blendShapes[shapeIndex].frames.Length; blendShapeNames[shapeName].frameWeights = new float[blendShapeNames[shapeName].frameCount]; for (int i = 0; i < blendShapeNames[shapeName].frameCount; i++) { //technically two sources could have different frame weights for the same blendshape, but then thats a problem with the source. blendShapeNames[shapeName].frameWeights[i] = source.meshData.blendShapes[shapeIndex].frames[i].frameWeight; } } } } //If our blendshape hash has at least 1 name, then we have a blendshape! if (blendShapeNames.Count > 0 || bakedCount > 0) { meshComponents |= MeshComponents.has_blendShapes; } }
public ModifyVerticesMeshChange(DMesh3 mesh, MeshComponents wantComponents = MeshComponents.All) { initialize_buffers(mesh, wantComponents); }
private static void AnalyzeSources(CombineInstance[] sources, int[] subMeshTriangleLength, ref int vertexCount, ref int bindPoseCount, ref int transformHierarchyCount, ref MeshComponents meshComponents) { for (int i = 0; i < subMeshTriangleLength.Length; i++) { subMeshTriangleLength[i] = 0; } foreach (var source in sources) { vertexCount += source.meshData.vertices.Length; bindPoseCount += source.meshData.bindPoses.Length; transformHierarchyCount += source.meshData.umaBones.Length; if (source.meshData.normals != null && source.meshData.normals.Length != 0) { meshComponents |= MeshComponents.has_normals; } if (source.meshData.tangents != null && source.meshData.tangents.Length != 0) { meshComponents |= MeshComponents.has_tangents; } if (source.meshData.uv != null && source.meshData.uv.Length != 0) { meshComponents |= MeshComponents.has_uv; } if (source.meshData.uv2 != null && source.meshData.uv2.Length != 0) { meshComponents |= MeshComponents.has_uv2; } #if !UNITY_4_6 if (source.meshData.uv3 != null && source.meshData.uv3.Length != 0) { meshComponents |= MeshComponents.has_uv3; } if (source.meshData.uv4 != null && source.meshData.uv4.Length != 0) { meshComponents |= MeshComponents.has_uv4; } #endif if (source.meshData.colors32 != null && source.meshData.colors32.Length != 0) { meshComponents |= MeshComponents.has_colors32; } for (int i = 0; i < source.meshData.subMeshCount; i++) { if (source.targetSubmeshIndices[i] >= 0) { int triangleLength = source.meshData.submeshes[i].triangles.Length; subMeshTriangleLength[source.targetSubmeshIndices[i]] += triangleLength; } } } }
/// <summary> /// Combines a set of meshes into the target mesh. /// </summary> /// <param name="target">Target.</param> /// <param name="sources">Sources.</param> public static void CombineMeshes(UMAMeshData target, CombineInstance[] sources) { int vertexCount = 0; int bindPoseCount = 0; int transformHierarchyCount = 0; MeshComponents meshComponents = MeshComponents.none; int subMeshCount = FindTargetSubMeshCount(sources); var subMeshTriangleLength = new int[subMeshCount]; AnalyzeSources(sources, subMeshTriangleLength, ref vertexCount, ref bindPoseCount, ref transformHierarchyCount, ref meshComponents); int[][] submeshTriangles = new int[subMeshCount][]; for (int i = 0; i < subMeshTriangleLength.Length; i++) { submeshTriangles[i] = new int[subMeshTriangleLength[i]]; subMeshTriangleLength[i] = 0; } bool has_normals = (meshComponents & MeshComponents.has_normals) != MeshComponents.none; bool has_tangents = (meshComponents & MeshComponents.has_tangents) != MeshComponents.none; bool has_uv = (meshComponents & MeshComponents.has_uv) != MeshComponents.none; bool has_uv2 = (meshComponents & MeshComponents.has_uv2) != MeshComponents.none; #if !UNITY_4_6 bool has_uv3 = (meshComponents & MeshComponents.has_uv3) != MeshComponents.none; bool has_uv4 = (meshComponents & MeshComponents.has_uv4) != MeshComponents.none; #endif bool has_colors32 = (meshComponents & MeshComponents.has_colors32) != MeshComponents.none; Vector3[] vertices = EnsureArrayLength(target.vertices, vertexCount); BoneWeight[] boneWeights = EnsureArrayLength(target.unityBoneWeights, vertexCount); Vector3[] normals = has_normals ? EnsureArrayLength(target.normals, vertexCount) : null; Vector4[] tangents = has_tangents ? EnsureArrayLength(target.tangents, vertexCount) : null; Vector2[] uv = has_uv ? EnsureArrayLength(target.uv, vertexCount) : null; Vector2[] uv2 = has_uv2 ? EnsureArrayLength(target.uv2, vertexCount) : null; #if !UNITY_4_6 Vector2[] uv3 = has_uv3 ? EnsureArrayLength(target.uv3, vertexCount) : null; Vector2[] uv4 = has_uv4 ? EnsureArrayLength(target.uv4, vertexCount) : null; #endif Color32[] colors32 = has_colors32 ? EnsureArrayLength(target.colors32, vertexCount) : null; UMATransform[] umaTransforms = EnsureArrayLength(target.umaBones, transformHierarchyCount); int boneCount = 0; foreach (var source in sources) { MergeSortedTransforms(umaTransforms, ref boneCount, source.meshData.umaBones); } int vertexIndex = 0; if (bonesCollection == null) { bonesCollection = new Dictionary <int, BoneIndexEntry>(boneCount); } else { bonesCollection.Clear(); } if (bindPoses == null) { bindPoses = new List <Matrix4x4>(bindPoseCount); } else { bindPoses.Clear(); } if (bonesList == null) { bonesList = new List <int>(boneCount); } else { bonesList.Clear(); } foreach (var source in sources) { vertexCount = source.meshData.vertices.Length; BuildBoneWeights(source.meshData.boneWeights, 0, boneWeights, vertexIndex, vertexCount, source.meshData.boneNameHashes, source.meshData.bindPoses, bonesCollection, bindPoses, bonesList); Array.Copy(source.meshData.vertices, 0, vertices, vertexIndex, vertexCount); if (has_normals) { if (source.meshData.normals != null && source.meshData.normals.Length > 0) { Array.Copy(source.meshData.normals, 0, normals, vertexIndex, vertexCount); } else { FillArray(tangents, vertexIndex, vertexCount, Vector3.zero); } } if (has_tangents) { if (source.meshData.tangents != null && source.meshData.tangents.Length > 0) { Array.Copy(source.meshData.tangents, 0, tangents, vertexIndex, vertexCount); } else { FillArray(tangents, vertexIndex, vertexCount, Vector4.zero); } } if (has_uv) { if (source.meshData.uv != null && source.meshData.uv.Length >= vertexCount) { Array.Copy(source.meshData.uv, 0, uv, vertexIndex, vertexCount); } else { FillArray(uv, vertexIndex, vertexCount, Vector4.zero); } } if (has_uv2) { if (source.meshData.uv2 != null && source.meshData.uv2.Length >= vertexCount) { Array.Copy(source.meshData.uv2, 0, uv2, vertexIndex, vertexCount); } else { FillArray(uv2, vertexIndex, vertexCount, Vector4.zero); } } #if !UNITY_4_6 if (has_uv3) { if (source.meshData.uv3 != null && source.meshData.uv3.Length >= vertexCount) { Array.Copy(source.meshData.uv3, 0, uv3, vertexIndex, vertexCount); } else { FillArray(uv3, vertexIndex, vertexCount, Vector4.zero); } } if (has_uv4) { if (source.meshData.uv4 != null && source.meshData.uv4.Length >= vertexCount) { Array.Copy(source.meshData.uv4, 0, uv4, vertexIndex, vertexCount); } else { FillArray(uv4, vertexIndex, vertexCount, Vector4.zero); } } #endif if (has_colors32) { if (source.meshData.colors32 != null && source.meshData.colors32.Length > 0) { Array.Copy(source.meshData.colors32, 0, colors32, vertexIndex, vertexCount); } else { Color32 white32 = Color.white; FillArray(colors32, vertexIndex, vertexCount, white32); } } for (int i = 0; i < source.meshData.subMeshCount; i++) { if (source.targetSubmeshIndices[i] >= 0) { int[] subTriangles = source.meshData.submeshes[i].triangles; int triangleLength = subTriangles.Length; int destMesh = source.targetSubmeshIndices[i]; CopyIntArrayAdd(subTriangles, 0, submeshTriangles[destMesh], subMeshTriangleLength[destMesh], triangleLength, vertexIndex); subMeshTriangleLength[destMesh] += triangleLength; } } vertexIndex += vertexCount; } vertexCount = vertexIndex; // fill in new values. target.vertexCount = vertexCount; target.vertices = vertices; target.unityBoneWeights = boneWeights; target.bindPoses = bindPoses.ToArray(); target.normals = normals; target.tangents = tangents; target.uv = uv; target.uv2 = uv2; #if !UNITY_4_6 target.uv3 = uv3; target.uv4 = uv4; #endif target.colors32 = colors32; target.subMeshCount = subMeshCount; target.submeshes = new SubMeshTriangles[subMeshCount]; target.umaBones = umaTransforms; target.umaBoneCount = boneCount; for (int i = 0; i < subMeshCount; i++) { target.submeshes[i].triangles = submeshTriangles[i]; } target.boneNameHashes = bonesList.ToArray(); }