static bool TryAttachEdgeToList(IndexVector segment, LinkedLoop <int> toList) { var first = toList.first.value; if (first == segment.From) { toList.AddFirst(segment.To); return(true); } if (first == segment.To) { toList.AddFirst(segment.From); return(true); } var last = toList.last.value; if (last == segment.From) { toList.AddLast(segment.To); return(true); } if (last == segment.To) { toList.AddLast(segment.From); return(true); } return(false); }
public LinkedList <LinkedLoop <int> > GetEdgeLoopsByIndex() { var lists = new LinkedList <LinkedLoop <int> >(); // join by common indexes var capEdgesLoop = new LinkedLoop <IndexVector>(CapEdges); while (capEdgesLoop.size != 0) { var newList = new LinkedLoop <int>(); lists.AddLast(newList); IndexVector edge = capEdgesLoop.first.value; capEdgesLoop.first.Remove(); newList.AddLast(edge.From); newList.AddLast(edge.To); var current = capEdgesLoop.first; int counter = capEdgesLoop.size; while (counter != 0) { --counter; var next = current.next; if (TryAttachEdgeToList(current.value, newList)) { current.Remove(); counter = capEdgesLoop.size; } current = next; } } return(lists); }
/// <summary> /// Optimize mesh: deleting all vertices that present in mesh but not present in mesh's triangle list /// </summary> public void DeleteUnusedVertices() { DeleteEmptySubmeshes(); bool[] used = new bool[_meshData.Vertices.Count]; int newVertexCount = 0; for (var i = 0; i < _meshData.SubMeshes.Length; ++i) { var subMesh = _meshData.SubMeshes[i]; for (var j = 0; j < subMesh.Length; ++j) { int vIndex = subMesh[j]; if (!used[vIndex]) { ++newVertexCount; } used[vIndex] = true; } } var oldToNewShift = new int[_meshData.Vertices.Count]; newVertexCount = 0; for (int i = 0; i < used.Length; ++i) { if (!used[i]) { continue; } _meshData.Vertices[newVertexCount] = _meshData.Vertices[i]; oldToNewShift[i] = newVertexCount; ++newVertexCount; } if (_meshData.NormalsExists) { DeleteUnusedItem(used, _meshData.Normals); } if (_meshData.ColorsExists) { DeleteUnusedItem(used, _meshData.Colors); } if (_meshData.Colors32Exists) { DeleteUnusedItem(used, _meshData.Colors32); } if (_meshData.UVExists) { DeleteUnusedItem(used, _meshData.UV); } if (_meshData.UV2Exists) { DeleteUnusedItem(used, _meshData.UV2); } if (_meshData.UV3Exists) { DeleteUnusedItem(used, _meshData.UV3); } if (_meshData.UV4Exists) { DeleteUnusedItem(used, _meshData.UV4); } if (_meshData.TangentsExists) { DeleteUnusedItem(used, _meshData.Tangents); } if (_meshData.BoneWeightsExists) { DeleteUnusedItem(used, _meshData.BoneWeights); } // shift sub meshes for (int smi = 0; smi < _meshData.SubMeshes.Length; ++smi) { var subMesh = _meshData.SubMeshes[smi]; for (int vertIndex = 0; vertIndex < subMesh.Length; ++vertIndex) { subMesh[vertIndex] = oldToNewShift[subMesh[vertIndex]]; } } // shift crossSegments for (int i = 0; i < CapEdges.Count; i++) { var segment = CapEdges[i]; CapEdges[i] = new IndexVector(oldToNewShift[segment.From], oldToNewShift[segment.To]); } // truncate _meshData.Vertices.RemoveRange(newVertexCount, _meshData.Vertices.Count - newVertexCount); if (_meshData.NormalsExists) { _meshData.Normals.RemoveRange(newVertexCount, _meshData.Normals.Count - newVertexCount); } if (_meshData.ColorsExists) { _meshData.Colors.RemoveRange(newVertexCount, _meshData.Colors.Count - newVertexCount); } if (_meshData.Colors32Exists) { _meshData.Colors32.RemoveRange(newVertexCount, _meshData.Colors32.Count - newVertexCount); } if (_meshData.UVExists) { _meshData.UV.RemoveRange(newVertexCount, _meshData.UV.Count - newVertexCount); } if (_meshData.UV2Exists) { _meshData.UV2.RemoveRange(newVertexCount, _meshData.UV2.Count - newVertexCount); } if (_meshData.UV3Exists) { _meshData.UV3.RemoveRange(newVertexCount, _meshData.UV3.Count - newVertexCount); } if (_meshData.UV4Exists) { _meshData.UV4.RemoveRange(newVertexCount, _meshData.UV4.Count - newVertexCount); } if (_meshData.TangentsExists) { _meshData.Tangents.RemoveRange(newVertexCount, _meshData.Tangents.Count - newVertexCount); } if (_meshData.BoneWeightsExists) { _meshData.BoneWeights.RemoveRange(newVertexCount, _meshData.BoneWeights.Count - newVertexCount); } }
/// <summary> /// Generate new index in triangle list that resides in plane /// </summary> public int GetIndexFor(int from, int to) { var oldDir = new IndexVector(from, to); int result; if (_chashedOuterLines.TryGetValue(oldDir, out result)) { return(result); } result = _meshData.Vertices.Count; _chashedOuterLines.Add(oldDir, result); float ratioIn = CalcGetRatio(from, to); { // Vertex Vector3 vFrom = _meshData.Vertices[from]; Vector3 vTo = _meshData.Vertices[to]; Vector3 vNew = Vector3.Lerp(vFrom, vTo, ratioIn); _meshData.Vertices.Add(vNew); } if (_meshData.NormalsExists) { Vector3 nFrom = _meshData.Normals[from]; Vector3 nTo = _meshData.Normals[to]; Vector3 nNew = Vector3.Slerp(nFrom, nTo, ratioIn); _meshData.Normals.Add(nNew); } if (_meshData.ColorsExists) { Color colorFrom = _meshData.Colors[from]; Color colorTo = _meshData.Colors[to]; Color colorNew = Color.Lerp(colorFrom, colorTo, ratioIn); _meshData.Colors.Add(colorNew); } if (_meshData.Colors32Exists) { Color32 colorFrom = _meshData.Colors32[from]; Color32 colorTo = _meshData.Colors32[to]; Color32 colorNew = Color32.Lerp(colorFrom, colorTo, ratioIn); _meshData.Colors32.Add(colorNew); } if (_meshData.UVExists) { AddValue(_meshData.UV, from, to, ratioIn); } if (_meshData.UV2Exists) { AddValue(_meshData.UV2, from, to, ratioIn); } if (_meshData.UV3Exists) { AddValue(_meshData.UV3, from, to, ratioIn); } if (_meshData.UV4Exists) { AddValue(_meshData.UV4, from, to, ratioIn); } if (_meshData.TangentsExists) { Vector4 vFrom = _meshData.Tangents[from]; Vector4 vTo = _meshData.Tangents[to]; Vector4 vNew = Vector4.Lerp(vFrom, vTo, ratioIn); _meshData.Tangents.Add(vNew); } if (_meshData.BoneWeightsExists) { var w1 = _meshData.BoneWeights[from]; var w2 = _meshData.BoneWeights[to]; var ws = new Dictionary <int, float>(); float ratioOut = 1 - ratioIn; if (w1.weight0 != 0) { ws.Add(w1.boneIndex0, w1.weight0 * ratioIn); } if (w1.weight1 != 0) { ws.Add(w1.boneIndex1, w1.weight1 * ratioIn); } if (w1.weight2 != 0) { ws.Add(w1.boneIndex2, w1.weight2 * ratioIn); } if (w1.weight3 != 0) { ws.Add(w1.boneIndex3, w1.weight3 * ratioIn); } if (w2.weight0 != 0) { float fA; ws.TryGetValue(w2.boneIndex0, out fA); ws[w2.boneIndex0] = fA + w2.weight0 * ratioOut; } if (w2.weight1 != 0) { float fA; ws.TryGetValue(w2.boneIndex1, out fA); ws[w2.boneIndex1] = fA + w2.weight1 * ratioOut; } if (w2.weight2 != 0) { float fA; ws.TryGetValue(w2.boneIndex2, out fA); ws[w2.boneIndex2] = fA + w2.weight2 * ratioOut; } if (w2.weight3 != 0) { float fA; ws.TryGetValue(w2.boneIndex3, out fA); ws[w2.boneIndex3] = fA + w2.weight3 * ratioOut; } var newBoneWeight = new BoneWeight(); var wsArr = ws .Where(v => v.Value != 0) .Take(4) .OrderByDescending(v => v.Value) .ToArray(); KeyValuePair <int, float>[] wsArr4 = new KeyValuePair <int, float> [4]; Array.Copy(wsArr, wsArr4, wsArr.Length); float weightSum = 0; weightSum += wsArr4[0].Value; weightSum += wsArr4[1].Value; weightSum += wsArr4[2].Value; weightSum += wsArr4[3].Value; float weightRatio = 1 / weightSum; if (wsArr.Length > 0) { newBoneWeight.boneIndex0 = wsArr[0].Key; newBoneWeight.weight0 = wsArr[0].Value * weightRatio; } if (wsArr.Length > 1) { newBoneWeight.boneIndex1 = wsArr[1].Key; newBoneWeight.weight1 = wsArr[1].Value * weightRatio; } if (wsArr.Length > 2) { newBoneWeight.boneIndex2 = wsArr[2].Key; newBoneWeight.weight2 = wsArr[2].Value * weightRatio; } if (wsArr.Length > 3) { newBoneWeight.boneIndex3 = wsArr[3].Key; newBoneWeight.weight3 = wsArr[3].Value * weightRatio; } _meshData.BoneWeights.Add(newBoneWeight); } return(result); }
/// <summary> /// Generate new index in triangle list that resides in plane /// </summary> public int GetIndexFor(int from, int to) { var oldDir = new IndexVector(from, to); int result; if (_chashedOuterLines.TryGetValue(oldDir, out result)) { return(result); } Vector3 v1 = _adapter.GetWorldPos(from); Vector3 v2 = _adapter.GetWorldPos(to); Vector3 enter; float ratioIn = CalcGetRatio(v1, v2, out enter); if (Mathf.Abs((enter - v1).sqrMagnitude) <= float.Epsilon) { return(from); } if (Mathf.Abs((enter - v2).sqrMagnitude) <= float.Epsilon) { return(to); } result = _meshData.Vertices.Count; _chashedOuterLines.Add(oldDir, result); { // Vertex Vector3 vFrom = _meshData.Vertices[from]; Vector3 vTo = _meshData.Vertices[to]; Vector3 vNew = Vector3.Lerp(vFrom, vTo, ratioIn); _meshData.Vertices.Add(vNew); } if (_meshData.NormalsExists) { Vector3 nFrom = _meshData.Normals[from]; Vector3 nTo = _meshData.Normals[to]; Vector3 nNew = Vector3.Slerp(nFrom, nTo, ratioIn); _meshData.Normals.Add(nNew); } if (_meshData.ColorsExists) { Color colorFrom = _meshData.Colors[from]; Color colorTo = _meshData.Colors[to]; Color colorNew = Color.Lerp(colorFrom, colorTo, ratioIn); _meshData.Colors.Add(colorNew); } if (_meshData.Colors32Exists) { Color32 colorFrom = _meshData.Colors32[from]; Color32 colorTo = _meshData.Colors32[to]; Color32 colorNew = Color32.Lerp(colorFrom, colorTo, ratioIn); _meshData.Colors32.Add(colorNew); } if (_meshData.UVExists) { AddValue(_meshData.UV, from, to, ratioIn); } if (_meshData.UV2Exists) { AddValue(_meshData.UV2, from, to, ratioIn); } if (_meshData.UV3Exists) { AddValue(_meshData.UV3, from, to, ratioIn); } if (_meshData.UV4Exists) { AddValue(_meshData.UV4, from, to, ratioIn); } if (_meshData.TangentsExists) { Vector4 vFrom = _meshData.Tangents[from]; Vector4 vTo = _meshData.Tangents[to]; Vector4 vNew = Vector4.Lerp(vFrom, vTo, ratioIn); _meshData.Tangents.Add(vNew); } if (_meshData.BoneWeightsExists) { var w1 = _meshData.BoneWeights[from]; var w2 = _meshData.BoneWeights[to]; var ws = new Dictionary <int, float>(8); float ratioOut = 1 - ratioIn; float tmp; ws.TryGetValue(w1.boneIndex0, out tmp); ws[w1.boneIndex0] = tmp + w1.weight0 * ratioIn; ws.TryGetValue(w1.boneIndex1, out tmp); ws[w1.boneIndex1] = tmp + w1.weight1 * ratioIn; ws.TryGetValue(w1.boneIndex2, out tmp); ws[w1.boneIndex2] = tmp + w1.weight2 * ratioIn; ws.TryGetValue(w1.boneIndex3, out tmp); ws[w1.boneIndex3] = tmp + w1.weight3 * ratioIn; ws.TryGetValue(w2.boneIndex0, out tmp); ws[w2.boneIndex0] = tmp + w2.weight0 * ratioOut; ws.TryGetValue(w2.boneIndex1, out tmp); ws[w2.boneIndex1] = tmp + w2.weight1 * ratioOut; ws.TryGetValue(w2.boneIndex2, out tmp); ws[w2.boneIndex2] = tmp + w2.weight2 * ratioOut; ws.TryGetValue(w2.boneIndex3, out tmp); ws[w2.boneIndex3] = tmp + w2.weight3 * ratioOut; var wsArr = ws .OrderByDescending(v => v.Value) .Take(4) .ToArray(); KeyValuePair <int, float>[] wsArr4 = new KeyValuePair <int, float> [4]; Array.Copy(wsArr, wsArr4, wsArr.Length); float weightSum = 0; weightSum += wsArr4[0].Value; weightSum += wsArr4[1].Value; weightSum += wsArr4[2].Value; weightSum += wsArr4[3].Value; var newBoneWeight = new BoneWeight(); float weightRatio = 1 / weightSum; if (wsArr.Length > 0) { newBoneWeight.boneIndex0 = wsArr[0].Key; newBoneWeight.weight0 = wsArr[0].Value * weightRatio; } if (wsArr.Length > 1) { newBoneWeight.boneIndex1 = wsArr[1].Key; newBoneWeight.weight1 = wsArr[1].Value * weightRatio; } if (wsArr.Length > 2) { newBoneWeight.boneIndex2 = wsArr[2].Key; newBoneWeight.weight2 = wsArr[2].Value * weightRatio; } if (wsArr.Length > 3) { newBoneWeight.boneIndex3 = wsArr[3].Key; newBoneWeight.weight3 = wsArr[3].Value * weightRatio; } _meshData.BoneWeights.Add(newBoneWeight); } return(result); }