public static void BuildGrid(this IMeshBuilder meshBuilder, float cellWidth, float cellLength, int segmentCount) { //Loop through the rows: for (int i = 0; i <= segmentCount; i++) { //incremented values for the Z position and V coordinate: float z = cellLength * i; float v = (1.0f / segmentCount) * i; //Loop through the collumns: for (int j = 0; j <= segmentCount; j++) { //incremented values for the X position and U coordinate: float x = cellWidth * j; float u = (1.0f / segmentCount) * j; //The position offset for this quad: Vector3 offset = new Vector3(x, 0f, z); //build quads that share vertices: Vector2 uv = new Vector2(u, v); bool buildTriangles = i > 0 && j > 0; BuildQuadForGrid(meshBuilder, offset, uv, buildTriangles, segmentCount + 1); } } }
public static (int[], int[]) FillPolygon(IMeshBuilder meshBuilder, IList <Vector3d> newPolygon, Vector3f normal) { if (meshBuilder == null || newPolygon == null) { return(null, null); } var triangulation = Geometry.Triangulate(newPolygon, normal); if (triangulation == null) { return(null, null); } //add vertices and triangles of basement to mesh var vertexToIndex = new Dictionary <Vector3d, int>(); var addedTriangles = new int[triangulation.Count]; int addedTriangleIdx = 0; foreach (var triangle in triangulation) { int a0 = AddDistinctVertex3d(meshBuilder, vertexToIndex, triangle[0], normal); int b0 = AddDistinctVertex3d(meshBuilder, vertexToIndex, triangle[1], normal); int c0 = AddDistinctVertex3d(meshBuilder, vertexToIndex, triangle[2], normal); addedTriangles[addedTriangleIdx] = meshBuilder.AppendTriangle(a0, b0, c0); addedTriangleIdx++; } int[] newVertices = vertexToIndex.Values.ToArray(); return(newVertices, addedTriangles); }
public static void ExtrudeToCenter(this IMeshBuilder meshBuilder, IMeshSelection meshSelection) { var p = Vector3.zero; for (int i = 0; i < meshSelection.Count; i++) { p += meshBuilder.Vertices[meshSelection[i]]; } p = p / meshSelection.Count; meshBuilder.Vertices.Add(p); meshBuilder.UVs.Add(Vector2.zero); // meshBuilder.Colors.Add(new Color(1f, 1f, 1f, 1f)); for (int i = 0; i < meshSelection.Count - 1; i++) { var i1 = meshSelection[i]; var i2 = meshBuilder.Vertices.Count - 1; var i3 = meshSelection[i + 1]; meshBuilder.AddTriangle(i1, i2, i3); } // Add the final face. meshBuilder.AddTriangle(meshBuilder.Vertices.Count - 2, meshBuilder.Vertices.Count - 1, meshSelection[0]); }
public static void BuildFacade(this IMeshBuilder meshBuilder, float width, float height, float length, Vector3 anchor) { //build the walls: //calculate directional vectors for the walls: Vector3 upDir = Vector3.up * height; Vector3 rightDir = Vector3.right * width; Vector3 forwardDir = Vector3.forward * length; Vector3 farCorner = upDir + rightDir + forwardDir; Vector3 nearCorner = Vector3.zero; //shift the pivot by the anchor. Vector3 pivotOffset = Vector3.Scale((rightDir + forwardDir + upDir), anchor); farCorner -= pivotOffset; nearCorner -= pivotOffset; //build the quads for the walls: BuildQuad(meshBuilder, nearCorner, rightDir, upDir); BuildQuad(meshBuilder, nearCorner, upDir, forwardDir); BuildQuad(meshBuilder, farCorner, -upDir, -rightDir); BuildQuad(meshBuilder, farCorner, -forwardDir, -upDir); }
public static GameObject CreateGameObject( this IMeshBuilder meshBuilder, string name, Material material, bool meshCollider = false, bool calculateNormals = true, bool calculateBounds = true) { var go = new GameObject(); if (!string.IsNullOrEmpty(name)) { go.name = name; } var meshFilter = go.AddComponent <MeshFilter>(); var meshRenderer = go.AddComponent <MeshRenderer>(); meshFilter.mesh = meshBuilder.BuildMesh(calculateNormals, calculateBounds); meshRenderer.material = material; if (meshCollider) { go.AddComponent <MeshCollider>().sharedMesh = meshFilter.sharedMesh; } return(go); }
public static void BuildCube(this IMeshBuilder meshBuilder, float width, float height, float length, Vector3 anchor) { //calculate directional vectors for all 3 dimensions of the cube: Vector3 upDir = Vector3.up * height; Vector3 rightDir = Vector3.right * width; Vector3 forwardDir = Vector3.forward * length; //calculate the positions of two corners opposite each other on the cube: //positions that will place the pivot at the corner of the cube: Vector3 nearCorner = Vector3.zero; Vector3 farCorner = upDir + rightDir + forwardDir; //shift the pivot by the anchor Vector3 pivotOffset = Vector3.Scale((rightDir + forwardDir + upDir), anchor); farCorner -= pivotOffset; nearCorner -= pivotOffset; //build the 3 quads that originate from nearCorner: BuildQuad(meshBuilder, nearCorner, forwardDir, rightDir); BuildQuad(meshBuilder, nearCorner, rightDir, upDir); BuildQuad(meshBuilder, nearCorner, upDir, forwardDir); //build the 3 quads that originate from farCorner: BuildQuad(meshBuilder, farCorner, -rightDir, -forwardDir); BuildQuad(meshBuilder, farCorner, -upDir, -rightDir); BuildQuad(meshBuilder, farCorner, -forwardDir, -upDir); }
private int append_vertex(IMeshBuilder builder, Vector3d vtx, Vector3f norm, Vector3f cols, Vector2f uvs, bool bHaveNormals, bool bHaveColors, bool bHaveUVs) { if (bHaveNormals == false && bHaveColors == false && bHaveUVs == false) { return(builder.AppendVertex(vtx.x, vtx.y, vtx.z)); } NewVertexInfo vinfo = new NewVertexInfo(); vinfo.bHaveC = vinfo.bHaveN = vinfo.bHaveUV = false; vinfo.v = vtx; if (bHaveNormals) { vinfo.bHaveN = true; vinfo.n = norm; } if (bHaveColors) { vinfo.bHaveC = true; vinfo.c = cols; } if (bHaveUVs) { vinfo.bHaveUV = true; vinfo.uv = uvs; } return(builder.AppendVertex(vinfo)); }
public IOReadResult Read(TextReader reader, ReadOptions options, IMeshBuilder builder) { XmlSerializer serializer = new XmlSerializer(typeof(AMF)); AMF amf; try { amf = (AMF)serializer.Deserialize(reader); } catch (Exception e) { return(new IOReadResult(IOCode.FileParsingError, $"XML parsing error: {e}")); } foreach (var @object in amf.objects) { foreach (var mesh in @object.meshes) { int meshId = builder.AppendNewMesh(false, false, false, true); var mapV = new int[mesh.vertices.vertices.Length]; for (int k = 0; k < mesh.vertices.vertices.Length; ++k) { var coordinates = mesh.vertices.vertices[k].coordinates; mapV[k] = builder.AppendVertex(coordinates.x, coordinates.y, coordinates.z); } for (int i = 0; i < mesh.volumes.Length; ++i) { for (int j = 0; j < mesh.volumes[i].triangles.Length; ++j) { var triangle = mesh.volumes[i].triangles[j]; builder.AppendTriangle(mapV[triangle.v1], mapV[triangle.v2], mapV[triangle.v3], i); } } } } return(IOReadResult.Ok); }
public static void AssignColors(this IMeshBuilder meshBuilder, int startIndex, int endIndex, Color color) { for (int i = 0; i < meshBuilder.Vertices.Count; i++) { meshBuilder.Colors[i] = color; } }
protected virtual void BuildMesh(STLSolid solid, IMeshBuilder builder) { if (RebuildStrategy == Strategy.AutoBestResult) { DMesh3 result = BuildMesh_Auto(solid); builder.AppendNewMesh(result); } else if (RebuildStrategy == Strategy.IdenticalVertexWeld) { DMesh3 result = BuildMesh_IdenticalWeld(solid); builder.AppendNewMesh(result); } else if (RebuildStrategy == Strategy.TolerantVertexWeld) { DMesh3 result = BuildMesh_TolerantWeld(solid, WeldTolerance); builder.AppendNewMesh(result); } else { BuildMesh_NoMerge(solid, builder); } if (WantPerTriAttribs && solid.TriAttribs != null && builder.SupportsMetaData) { builder.AppendMetaData(PerTriAttribMetadataName, solid.TriAttribs); } }
/// <summary> /// Read mesh file using options and builder. You must provide our own Builder /// here because the reader is not returned /// </summary> static public IOReadResult ReadFile(string sFilename, ReadOptions options, IMeshBuilder builder) { var reader = new StandardMeshReader(); reader.MeshBuilder = builder; return(reader.Read(sFilename, options)); }
public IOReadResult ReadFile(Stream stream, IMeshBuilder builder, ReadOptions options, ParsingMessagesHandler messages) { // detect binary STL BinaryReader binReader = new BinaryReader(stream); byte[] header = binReader.ReadBytes(80); bool bIsBinary = false; // if first 80 bytes contain non-text chars, probably a binary file if (Util.IsTextString(header) == false) { bIsBinary = true; } // if we don't see "solid" string in first 80 chars, probably binary if (bIsBinary == false) { string sText = System.Text.Encoding.ASCII.GetString(header); if (sText.Contains("solid") == false) { bIsBinary = true; } } stream.Seek(0, SeekOrigin.Begin); // reset stream STLReader reader = new STLReader(); reader.warningEvent += messages; IOReadResult result = (bIsBinary) ? reader.Read(new BinaryReader(stream), options, builder) : reader.Read(new StreamReader(stream), options, builder); return(result); }
public async Task <MeshData> BuildMeshData(Terrain terrain, IReadOnlyCollection <Texture2D> alphaMaps, MassiveGrassGrid.CellIndex index, Rect rect, MassiveGrassProfile profile) { var elements = await GenerateElements(terrain, rect, profile, index.hash % 50000); builder = builder ?? profile.CreateBuilder(); return(await builder.BuildMeshData(terrain, alphaMaps, profile, elements)); }
/// <summary> /// Builds a single quad based on a position offset and width and length vectors. /// </summary> /// <param name="meshBuilder">The mesh builder currently being added to.</param> /// <param name="offset">A position offset for the quad.</param> /// <param name="widthDir">The width vector of the quad.</param> /// <param name="lengthDir">The length vector of the quad.</param> public static void BuildQuad(this IMeshBuilder meshBuilder, Vector3 offset, Vector3 widthDir, Vector3 lengthDir) { Vector3 normal = Vector3.Cross(lengthDir, widthDir).normalized; meshBuilder.Vertices.Add(offset); meshBuilder.UVs.Add(new Vector2(0.0f, 0.0f)); meshBuilder.Normals.Add(normal); meshBuilder.Vertices.Add(offset + lengthDir); meshBuilder.UVs.Add(new Vector2(0.0f, 1.0f)); meshBuilder.Normals.Add(normal); meshBuilder.Vertices.Add(offset + lengthDir + widthDir); meshBuilder.UVs.Add(new Vector2(1.0f, 1.0f)); meshBuilder.Normals.Add(normal); meshBuilder.Vertices.Add(offset + widthDir); meshBuilder.UVs.Add(new Vector2(1.0f, 0.0f)); meshBuilder.Normals.Add(normal); //we don't know how many verts the meshBuilder is up to, but we only care about the four we just added: int baseIndex = meshBuilder.Vertices.Count - 4; meshBuilder.AddTriangle(baseIndex, baseIndex + 1, baseIndex + 2); meshBuilder.AddTriangle(baseIndex, baseIndex + 2, baseIndex + 3); }
public IOReadResult ReadFile(Stream stream, IMeshBuilder builder, ReadOptions options, ParsingMessagesHandler messages) { // detect binary STL //BinaryReader binReader = new BinaryReader(stream); //byte[] header = binReader.ReadBytes(80); bool bIsBinary = Util.IsBinaryStream(stream, 500); // [RMS] Thingi10k includes some files w/ unicode string in ascii header... // How can we detect this? can we check that each character is a character? //string sUTF8 = System.Text.Encoding.UTF8.GetString(header); //string sAscii = System.Text.Encoding.ASCII.GetString(header); //if (sUTF8.Contains("solid") == false && sAscii.Contains("solid") == false) // bIsBinary = true; // if first 80 bytes contain non-text chars, probably a binary file //if (Util.IsTextString(header) == false) // bIsBinary = true; //// if we don't see "solid" string in first 80 chars, probably binary //if (bIsBinary == false) { // string sText = System.Text.Encoding.ASCII.GetString(header); // if (sText.Contains("solid") == false) // bIsBinary = true; //} stream.Seek(0, SeekOrigin.Begin); // reset stream var reader = new STLReader(); reader.warningEvent += messages; IOReadResult result = (bIsBinary) ? reader.Read(new BinaryReader(stream), options, builder) : reader.Read(new StreamReader(stream), options, builder); return(result); }
/// <summary> /// Builds a smooth surfaced grid with the origin in the bottom-left corner. /// </summary> /// <remarks> /// The grid is comprised of quads with no shared vertices, allowing flat shading. /// </remarks> /// <param name="meshBuilder">Mesh builder.</param> /// <param name="cellWidth">Cell width.</param> /// <param name="cellLength">Cell length.</param> /// <param name="segmentCount">Segment count.</param> /// <param name="heightFunc">Height func.</param> public static void BuildSmoothGrid(this IMeshBuilder meshBuilder, float cellWidth, float cellLength, int segmentCount, Func <int, int, float> heightFunc) { int baseIndex = 0; for (int i = 0; i < segmentCount; i++) { for (int j = 0; j < segmentCount; j++) { var x = cellWidth * j; var z = cellLength * i; meshBuilder.Vertices.Add(new Vector3(x, heightFunc(j, i), z)); meshBuilder.Vertices.Add(new Vector3(x, heightFunc(j, i + 1), z + cellLength)); meshBuilder.Vertices.Add(new Vector3(x + cellWidth, heightFunc(j + 1, i + 1), z + cellLength)); meshBuilder.Vertices.Add(new Vector3(x + cellWidth, heightFunc(j + 1, i), z)); meshBuilder.Normals.Add(Vector3.up); meshBuilder.Normals.Add(Vector3.up); meshBuilder.Normals.Add(Vector3.up); meshBuilder.Normals.Add(Vector3.up); meshBuilder.AddTriangle(baseIndex, baseIndex + 1, baseIndex + 2); meshBuilder.AddTriangle(baseIndex, baseIndex + 2, baseIndex + 3); baseIndex += 4; } } }
public IOReadResult Read(TextReader reader, ReadOptions options, IMeshBuilder builder) { XmlSerializer serializer = new XmlSerializer(typeof(Model)); Model model; try { model = (Model)serializer.Deserialize(reader); } catch (Exception e) { return(new IOReadResult(IOCode.FileParsingError, $"XML parsing error: {e}")); } foreach (var @object in model.resources.objects) { var mesh = @object.mesh; int meshId = builder.AppendNewMesh(false, false, false, true); var mapV = new int[mesh.vertices.vertices.Length]; for (int k = 0; k < mesh.vertices.vertices.Length; ++k) { var vertex = mesh.vertices.vertices[k]; mapV[k] = builder.AppendVertex(vertex.x, vertex.y, vertex.z); } for (int j = 0; j < mesh.triangles.triangles.Length; ++j) { var triangle = mesh.triangles.triangles[j]; builder.AppendTriangle(mapV[triangle.v1], mapV[triangle.v2], mapV[triangle.v3]); } } return(IOReadResult.Ok); }
public IOReadResult Read(BinaryReader reader, ReadOptions options, IMeshBuilder builder) { if (options.CustomFlags != null) { ParseArguments(options.CustomFlags); } /*byte[] header = */ reader.ReadBytes(80); int totalTris = reader.ReadInt32(); Objects = new List <STLSolid>(); Objects.Add(new STLSolid()); int tri_size = 50; // bytes IntPtr bufptr = Marshal.AllocHGlobal(tri_size); var tmp = new stl_triangle(); Type tri_type = tmp.GetType(); var tri_attribs = new DVector <short>(); try { for (int i = 0; i < totalTris; ++i) { byte[] tri_bytes = reader.ReadBytes(50); if (tri_bytes.Length < 50) { break; } Marshal.Copy(tri_bytes, 0, bufptr, tri_size); var tri = (stl_triangle)Marshal.PtrToStructure(bufptr, tri_type); append_vertex(tri.ax, tri.ay, tri.az); append_vertex(tri.bx, tri.by, tri.bz); append_vertex(tri.cx, tri.cy, tri.cz); tri_attribs.Add(tri.attrib); } } catch (Exception e) { return(new IOReadResult(IOCode.GenericReaderError, "exception: " + e.Message)); } Marshal.FreeHGlobal(bufptr); if (Objects.Count == 1) { Objects[0].TriAttribs = tri_attribs; } foreach (STLSolid solid in Objects) { BuildMesh(solid, builder); } return(new IOReadResult(IOCode.Ok, "")); }
public IOReadResult ReadFile(Stream stream, IMeshBuilder builder, ReadOptions options, ParsingMessagesHandler messages) { var reader = new BinaryG3Reader(); //reader.warningEvent += messages; IOReadResult result = reader.Read(new BinaryReader(stream), options, builder); return(result); }
public static void AssignRandomColorToVertices(this IMeshBuilder meshBuilder) { meshBuilder.AddMissingColors(Color.white); for (int i = 0; i < meshBuilder.Colors.Count; i++) { meshBuilder.Colors[i] = ColorHelper.RandomRGB(); } }
public static void AssignColors(this IMeshBuilder meshBuilder, MeshBuilderAssignColorsDelegate colorFunc) { meshBuilder.Colors.Clear(); for (int i = 0; i < meshBuilder.Vertices.Count; i++) { meshBuilder.AddColor(colorFunc(i, meshBuilder.Vertices[i])); } }
public static void AddMissingColors(this IMeshBuilder meshBuilder, Color color) { var numMissing = meshBuilder.Vertices.Count - meshBuilder.Colors.Count; for (int i = 0; i < numMissing; i++) { meshBuilder.Colors.Add(color); } }
unsafe int append_triangle(IMeshBuilder builder, Triangle t) { if (t.vIndices[0] < 0 || t.vIndices[1] < 0 || t.vIndices[2] < 0) { emit_warning(string.Format("[OBJReader] invalid triangle: {0} {1} {2}", t.vIndices[0], t.vIndices[1], t.vIndices[2])); return(-1); } return(builder.AppendTriangle(t.vIndices[0], t.vIndices[1], t.vIndices[2])); }
public IOReadResult ReadFile(string sFilename, IMeshBuilder builder, ReadOptions options, ParsingMessagesHandler messages) { try { using (FileStream stream = File.Open(sFilename, FileMode.Open, FileAccess.Read)) { return(ReadFile(stream, builder, options, messages)); } } catch (Exception e) { return(new IOReadResult(IOCode.FileAccessError, "Could not open file " + sFilename + " for reading : " + e.Message)); } }
int append_triangle(IMeshBuilder builder, Index3i tri) { if (tri.a < 0 || tri.b < 0 || tri.c < 0) { emit_warning(string.Format("[PLYReader] invalid triangle: {0} {1} {2}", tri.a, tri.b, tri.c)); return(-1); } return(builder.AppendTriangle(tri.a, tri.b, tri.c)); }
public static IMeshSelection SelectAll(this IMeshBuilder meshBuilder) { var selection = new MeshSelection(); for (int i = 0; i < meshBuilder.Vertices.Count; i++) { selection.Add(i); } return(selection); }
public static GameObject CreateGameObject(this IMeshBuilder meshBuilder, Material material) { var go = new GameObject(); var meshFilter = go.AddComponent <MeshFilter>(); var meshRenderer = go.AddComponent <MeshRenderer>(); meshFilter.mesh = meshBuilder.BuildMesh(); meshRenderer.material = material; return(go); }
protected virtual void BuildMesh(STLSolid solid, IMeshBuilder builder) { if (RebuildStrategy == Strategy.IdenticalVertexWeld) { BuildMesh_IdenticalWeld(solid, builder); } else { BuildMesh_NoMerge(solid, builder); } }
/// <summary> /// Construct a MeshReader, optionally with default format handlers /// Initializes MeshBuilder to a DMesh3Builder /// </summary> public StandardMeshReader(bool bIncludeDefaultReaders = true) { Readers = new List <MeshFormatReader>(); MeshBuilder = new DMesh3Builder(); if (bIncludeDefaultReaders) { Readers.Add(new OBJFormatReader()); Readers.Add(new STLFormatReader()); Readers.Add(new OFFFormatReader()); } }
public static bool IsEmpty <TMaterial>(this IMeshBuilder <TMaterial> mesh) { if (mesh == null) { return(true); } if (mesh.Primitives.Count == 0) { return(true); } return(mesh.Primitives.All(prim => prim.IsEmpty())); }