using System; using System.Collections.Generic; using UnityEngine; namespace Obi { public struct Triangle : IBounded { public int i1; public int i2; public int i3; Aabb b; public Triangle(int i1, int i2, int i3, Vector3 v1, Vector3 v2, Vector3 v3) { this.i1 = i1; this.i2 = i2; this.i3 = i3; b = new Aabb(v1); b.Encapsulate(v2); b.Encapsulate(v3); } public Aabb GetBounds() { return b; } } public class ObiTriangleMeshHandle : ObiResourceHandle { public ObiTriangleMeshHandle(Mesh mesh, int index = -1) : base(index) { owner = mesh; } } public struct TriangleMeshHeader //we need to use the header in the backend, so it must be a struct. { public int firstNode; public int nodeCount; public int firstTriangle; public int triangleCount; public int firstVertex; public int vertexCount; public TriangleMeshHeader(int firstNode, int nodeCount, int firstTriangle, int triangleCount, int firstVertex, int vertexCount) { this.firstNode = firstNode; this.nodeCount = nodeCount; this.firstTriangle = firstTriangle; this.triangleCount = triangleCount; this.firstVertex = firstVertex; this.vertexCount = vertexCount; } } public class ObiTriangleMeshContainer { public Dictionary handles; /**< dictionary indexed by mesh, so that we don't generate data for the same mesh multiple times.*/ public ObiNativeTriangleMeshHeaderList headers; /**< One header per mesh.*/ public ObiNativeBIHNodeList bihNodes; public ObiNativeTriangleList triangles; public ObiNativeVector3List vertices; public ObiTriangleMeshContainer() { handles = new Dictionary(); headers = new ObiNativeTriangleMeshHeaderList(); bihNodes = new ObiNativeBIHNodeList(); triangles = new ObiNativeTriangleList(); vertices = new ObiNativeVector3List(); } public ObiTriangleMeshHandle GetOrCreateTriangleMesh(Mesh source) { ObiTriangleMeshHandle handle = new ObiTriangleMeshHandle(null); if (source != null && !handles.TryGetValue(source, out handle)) { if (source.isReadable) { var sourceTris = source.triangles; var sourceVertices = source.vertices; // Build a bounding interval hierarchy from the triangles: IBounded[] t = new IBounded[sourceTris.Length / 3]; for (int i = 0; i < t.Length; ++i) { int t1 = sourceTris[i * 3]; int t2 = sourceTris[i * 3 + 1]; int t3 = sourceTris[i * 3 + 2]; t[i] = new Triangle(t1, t2, t3, sourceVertices[t1], sourceVertices[t2], sourceVertices[t3]); } var sourceBih = BIH.Build(ref t); Triangle[] tris = Array.ConvertAll(t, x => (Triangle)x); handle = new ObiTriangleMeshHandle(source, headers.count); handles.Add(source, handle); headers.Add(new TriangleMeshHeader(bihNodes.count, sourceBih.Length, triangles.count, tris.Length, vertices.count, sourceVertices.Length)); bihNodes.AddRange(sourceBih); triangles.AddRange(tris); vertices.AddRange(sourceVertices); } else { handle = new ObiTriangleMeshHandle(source); handles.Add(source, handle); } } return handle; } public void DestroyTriangleMesh(ObiTriangleMeshHandle handle) { if (handle != null && handle.isValid && handle.index < handles.Count) { var header = headers[handle.index]; // Update headers: for (int i = 0; i < headers.count; ++i) { var h = headers[i]; if (h.firstTriangle > header.firstTriangle) { h.firstNode -= header.nodeCount; h.firstTriangle -= header.triangleCount; h.firstVertex -= header.vertexCount; headers[i] = h; } } // update handles: foreach (var pair in handles) { if (pair.Value.index > handle.index) pair.Value.index --; } // Remove nodes, triangles and vertices bihNodes.RemoveRange(header.firstNode, header.nodeCount); triangles.RemoveRange(header.firstTriangle, header.triangleCount); vertices.RemoveRange(header.firstVertex, header.vertexCount); // remove header: headers.RemoveAt(handle.index); // remove the mesh from the dictionary: handles.Remove(handle.owner); // Invalidate our handle: handle.Invalidate(); } } public void Dispose() { if (headers != null) headers.Dispose(); if (triangles != null) triangles.Dispose(); if (vertices != null) vertices.Dispose(); if (bihNodes != null) bihNodes.Dispose(); } } }