/// <summary> /// Triangulate this csg and pack the triangulated data into buffers /// appropriate for use with gltf. /// </summary> internal static GraphicsBuffers Tessellate(this Csg.Solid csg) { var buffers = new GraphicsBuffers(); ushort iCursor = 0; (Vector3 U, Vector3 V)basis; const float SEARCH_RADIUS = 0.001f; // Setup the octree to fit around the csg. // This requires one expensive initialization. var verts = csg.Polygons.SelectMany(p => p.Vertices).Select(v => v.Pos.ToElementsVector()).ToArray(); var bounds = new BBox3(verts); var center = bounds.Center(); var origin = new Point((float)center.X, (float)center.Y, (float)center.Z); var size = (float)bounds.Max.DistanceTo(bounds.Min); var octree = new PointOctree <(Vector3 position, Vector3 normal, ushort index)>(size, origin, SEARCH_RADIUS); foreach (var p in csg.Polygons) { var vertexIndices = new ushort[p.Vertices.Count]; var a = p.Vertices[0].Pos.ToElementsVector(); var b = p.Vertices[1].Pos.ToElementsVector(); var c = p.Vertices[2].Pos.ToElementsVector(); basis = ComputeBasisAndNormalForTriangle(a, b, c, out Vector3 normal); // Anything with 3 vertices is a triangle. Manually // tesselate triangles. For everything else, use // the tessellator. if (p.Vertices.Count > 2 && p.Vertices.Count <= 3) { for (var i = 0; i < p.Vertices.Count; i++) { var v = p.Vertices[i]; var op = new Point((float)v.Pos.X, (float)v.Pos.Y, (float)v.Pos.Z); var ep = v.Pos.ToElementsVector(); if (TryGetExistingVertex(op, ep, octree, normal, SEARCH_RADIUS, out ushort vertexIndex)) { vertexIndices[i] = vertexIndex; continue; } vertexIndices[i] = iCursor; iCursor++; var uu = basis.U.Dot(ep); var vv = basis.V.Dot(ep); buffers.AddVertex(ep, normal, new UV(uu, vv)); octree.Add((ep, normal, vertexIndices[i]), op);
internal static GraphicsBuffers ToGraphicsBuffers(this IList <Vector3> vertices, bool lineLoop) { var gb = new GraphicsBuffers(); for (var i = 0; i < vertices.Count; i++) { var v = vertices[i]; gb.AddVertex(v, default(Vector3), default(UV), null); var write = lineLoop ? (i < vertices.Count - 1) : (i % 2 == 0 && i < vertices.Count - 1); if (write) { gb.AddIndex((ushort)i); gb.AddIndex((ushort)(i + 1)); } } return(gb); }
/// <summary> /// Get all buffers required for rendering. /// </summary> public GraphicsBuffers GetBuffers() { var buffers = new GraphicsBuffers(); for (var i = 0; i < this.Vertices.Count; i++) { var v = this.Vertices[i]; buffers.AddVertex(v.Position, v.Normal, v.UV, v.Color); } for (var i = 0; i < this.Triangles.Count; i++) { var t = this.Triangles[i]; buffers.AddIndex((ushort)t.Vertices[0].Index); buffers.AddIndex((ushort)t.Vertices[1].Index); buffers.AddIndex((ushort)t.Vertices[2].Index); } return(buffers); }