/// <summary> /// Runs a greedy meshing algorithm over a single axis. /// </summary> /// <param name="offset">The offset along the plane axis.</param> /// <param name="side">The side of the block being targeted.</param> /// <param name="mesh">The proc mesh to add the vertices to.</param> public void Mesh(int offset, int side, ProcMesh mesh) { m_QuadBuilder.Mesh = mesh; foreach (var q in PlaneIterator()) { if (!q.Quad.Active) { continue; } FindNextQuad(q, out int w, out int h); var quadMesh = new QuadBuilder.QuadMesh { X = q.X, Y = q.Y, W = w - q.X + 1, H = h - q.Y + 1, Side = side, Offset = offset, TextureIndex = q.Quad.TextureIndex, TextureRotation = q.Quad.Rotation, }; m_QuadBuilder.WriteQuad(quadMesh); ClearQuad(q, w, h); } m_QuadBuilder.Mesh = null; }
public void WieldVertices_NoUVs() { var mesh = new ProcMesh(); mesh.Vertices.Add(new Vec3(0, 0, 0)); mesh.Vertices.Add(new Vec3(0, 0, 0)); mesh.Vertices.Add(new Vec3(1, 0, 0)); mesh.Vertices.Add(new Vec3(0, 0, 0)); mesh.Normals.Add(new Vec3(0, 1, 0)); mesh.Normals.Add(new Vec3(0, 1, 0)); mesh.Normals.Add(new Vec3(1, 0, 0)); mesh.Normals.Add(new Vec3(0, 1, 0)); mesh.Triangles.Add(0); mesh.Triangles.Add(1); mesh.Triangles.Add(2); mesh.Triangles.Add(3); mesh.WieldVertices(); Assert.AreEqual(2, mesh.Vertices.Count); Assert.AreEqual(new Vec3(0, 0, 0), mesh.Vertices[0]); Assert.AreEqual(new Vec3(1, 0, 0), mesh.Vertices[1]); Assert.AreEqual(2, mesh.Normals.Count); Assert.AreEqual(new Vec3(0, 1, 0), mesh.Normals[0]); Assert.AreEqual(new Vec3(1, 0, 0), mesh.Normals[1]); Assert.AreEqual(0, mesh.UVs.Count); Assert.AreEqual(4, mesh.Triangles.Count); Assert.AreEqual(0, mesh.Triangles[0]); Assert.AreEqual(0, mesh.Triangles[1]); Assert.AreEqual(1, mesh.Triangles[2]); Assert.AreEqual(0, mesh.Triangles[3]); }
//adds a node to the mesh and to the node list protected void addNode <T>(MeshBuilder mb, Vector3 pos, Quaternion rot) where T : Node { //move the mesh out just a bit to prevent z fighting //maybe add the node to the list first then change this pos += rot * Vector3.up * .01f; //set colors of nodes //TODO: change this Sub sub = Sub.Foyaite; if (typeof(T) == typeof(PowerInNode)) { sub = Sub.Vegitation1; } else if (typeof(T) == typeof(PowerOutNode)) { sub = Sub.Foyaite; } else if (typeof(T) == typeof(NeutralNode)) { sub = Sub.IronDioxide; } // ProcMesh.addCube(mb, pos, .4f, .4f, .1f, Sub.Foyaite, rot); ProcMesh.addQuad(mb, pos, rot * Vector3.right * .4f, rot * Vector3.forward * .4f, sub); //create the node Node node; if (typeof(T) == typeof(PowerInNode)) { node = new PowerInNode(pos, rot) { go = this.gameObject } } ; else if (typeof(T) == typeof(PowerOutNode)) { node = new PowerOutNode(pos, rot) { go = this.gameObject } } ; else { node = new NeutralNode(pos, rot) { go = this.gameObject } }; nodes.Add(node); Node.curNodes.Add(node); } }
public override void Render() { MeshBuilder mb = new MeshBuilder(); ProcMesh.addCube(mb, Vector3.zero, .5f, .5f, .5f, Sub.Vegitation2); setMeshCol(mb.getMesh()); addNode <PowerInNode>(mb, new Vector3(.25f, 0, 0), Quaternion.Euler(0, 0, -90)); setMesh(mb.getMesh()); }
/// <summary> /// Creates a new voxel chunk mesher. /// </summary> /// <param name="chunkProperties">The chunk properties to handle.</param> /// <param name="wield">Whether or not to wield vertices after remeshing.</param> /// <param name="enableUVs">Whether or not to generate UVs in the mesh.</param> public VoxelChunkMesher(ChunkProperties chunkProperties, bool wieldVertices, bool enableUVs) { m_ChunkProperties = chunkProperties; m_GreedyMesher = new GreedyMesher(chunkProperties.ChunkSize, enableUVs); m_WieldVertices = wieldVertices; m_Mesh = new ProcMesh(); m_Task = Task.Run(Remesh); }
public override void Render() { MeshBuilder mb = new MeshBuilder(); ProcMesh.addCube(mb, Vector3.zero, 1f, 1f, .1f, Sub.TEST); setMeshCol(mb.getMesh()); addNode <NeutralNode>(mb, new Vector3(0, -.05f, 0), Quaternion.Euler(180, 0, 0)); setMesh(mb.getMesh()); }
public override void Render() { MeshBuilder mb = new MeshBuilder(); ProcMesh.addCube(mb, Vector3.zero, .5f, .5f, 1, Sub.Hawaiite); setMeshCol(mb.getMesh()); addNode <PowerInNode>(mb, new Vector3(0, -.5f, 0), Quaternion.Euler(180, 0, 0)); setMesh(mb.getMesh()); }
public override void Render() { MeshBuilder mb = new MeshBuilder(); ProcMesh.addCube(mb, Vector3.zero, 4, 5, .5f, Sub.Gold); meshCollider.sharedMesh = mb.getMesh(); ProcMesh.addCube(mb, new Vector3(1.75f, 2, 2.25f), .5f, .5f, 4, Sub.Gold); ProcMesh.addCube(mb, new Vector3(-1.75f, 2, 2.25f), .5f, .5f, 4, Sub.Gold); ProcMesh.addCube(mb, new Vector3(0, 4, 2.25f), 4f, .5f, .5f, Sub.Gold); filter.mesh = mb.getMesh(); //setMesh(mb.getMesh()); }
// Use this for initialization void Start() { //setReferences(); MeshBuilder mb = new MeshBuilder(); //ProceduralPrimitives.Quad(mb, Vector3.zero, new Vector3(4,0,0), new Vector3(0,0,4), Sub.Limestone); //ProceduralPrimitives.addCube(mb, Vector3.zero, Vector3.right, Vector3.forward, Vector3.up, Sub.Foyaite); ProcMesh.addCuboid(mb, Vector3.zero, new Vector3(5, 5, 5), new Vector3(0, -10, 4), Vector3.up, Sub.Foyaite); filter.mesh = mb.getMesh(); //filter.mesh.RecalculateBounds(); // filter.mesh.RecalculateNormals(); }
//don't ask why I capitalized this method but don't follow convention for anything else //okay fine I'll tell you, you might want to get some popcorn because it's story time //Many believe the Render method to be a fluke, an accident, the result of an experiment gone horribly wrong. //None of these are in fact the truth at all. The mysterious Render method is simply a remnant of a class long lost in the git archive //from many projects ago... //It started many years in the past when a young boy was on a quest to unlock the secrets of cyberspace and the world of game development //He had an idea, a starting point to a game he would enjoy: an infinite world //this would give him a map to let his imagination run free with creation //There was just one problem: He did not know how to do it. //The boy decided to consult an online tutorial explaining how to create a voxel based world represented by cubes //This mighty tutorial offered the boy something that few souls have encountered and many believe to be a myth //They call it the Chunk class //lengend has it that the Chunk class contained infinite knowledge of world generation in game development //It's countless methods were more beautiful, more elegant, and more efficient than the greatest minds in computer science could ever imagine //It is believed that one of these methods was simply named Render //The great class was there for the boy's taking, but he knew he would have much work ahead of him in understanding its holy contents //He spent days and weeks exploring the unknown, learning more than he thought possible //But one day, something changed. //to be continued i need to get back to work public override void Render() { MeshBuilder mb = new MeshBuilder(); ProcMesh.addCube(mb, Vector3.zero, 3, 5, .5f, Sub.Gold); setMeshCol(mb.getMesh()); addNode <PowerOutNode>(mb, new Vector3(0, 0, -2.5f), Quaternion.Euler(-90, 0, 0)); addNode <PowerOutNode>(mb, new Vector3(0, 0, 2.5f), Quaternion.Euler(90, 0, 0)); addNode <NeutralNode>(mb, new Vector3(0, .25f, 0), Quaternion.identity); setMesh(mb.getMesh()); }
public override Mesh buildObject(int seed) { System.Random rand = new System.Random(seed); MeshBuilder mb = new MeshBuilder(); float size = (float)sizeprob.getValue(rand.NextDouble()); ProcMesh.addCube(mb, Vector3.zero, size, size, size, substance); ModMesh.displace(mb, size * (float)dispProb.getValue(rand.NextDouble())); return(mb.getMesh()); }
public void UnequalMeshCounts() { var mesh = new ProcMesh(); mesh.Vertices.Add(new Vec3(0, 0, 0)); mesh.Vertices.Add(new Vec3(0, 0, 0)); mesh.Vertices.Add(new Vec3(1, 0, 0)); mesh.Vertices.Add(new Vec3(0, 0, 0)); mesh.Normals.Add(new Vec3(0, 1, 0)); mesh.Normals.Add(new Vec3(0, 1, 0)); mesh.UVs.Add(new Vec3(0, 0, 0)); mesh.Triangles.Add(0); mesh.Triangles.Add(1); mesh.Triangles.Add(2); mesh.Triangles.Add(3); Assert.Throws <InvalidOperationException>(() => mesh.WieldVertices()); }
/// <summary> /// Applies the given proc mesh to the Unity mesh. /// </summary> /// <param name="procMesh">The proc mesh to retrieve the data from.</param> /// <param name="mesh">The Unity mesh to write to.</param> public void UpdateMesh(LayeredProcMesh procMesh, Mesh mesh) { mesh.Clear(); ProcMesh root = new ProcMesh(); for (int i = 0; i < procMesh.TotalLayers; i++) { var layer = procMesh.GetLayer(i); root.Vertices.AddRange(layer.Vertices); root.Normals.AddRange(layer.Normals); root.UVs.AddRange(layer.UVs); } mesh.subMeshCount = procMesh.TotalLayers; mesh.SetVertices(root.Vertices.Select(v => new Vector3(v.X, v.Y, v.Z)).ToList()); if (root.Normals.Count > 0) { mesh.SetNormals(root.Normals.Select(v => new Vector3(v.X, v.Y, v.Z)).ToList()); } if (root.UVs.Count > 0) { mesh.SetUVs(0, root.UVs.Select(v => new Vector3(v.X, v.Y, v.Z)).ToList()); } int baseVertex = 0; int k = 0; for (int i = 0; i < procMesh.TotalLayers; i++) { var layer = procMesh.GetLayer(i); mesh.SetTriangles(layer.Triangles, k++, true, baseVertex); baseVertex += layer.Vertices.Count; } mesh.RecalculateBounds(); mesh.Optimize(); }
//build the mesh of the square made up of these four voxels private static void marchSquare(MeshBuilder mb, SVox v1, SVox v2, SVox v3, SVox v4, Sub sub) { //calculate the cell type int cellType = 0; if (v1.state) { cellType |= 1; } if (v2.state) { cellType |= 2; } if (v3.state) { cellType |= 4; } if (v4.state) { cellType |= 8; } //Sub sub = Sub.Foyaite; //now build the mesh based on the cell type switch (cellType) { case 0: return; case 1: ProcMesh.addTri(mb, v1.pos, v1.yEdge, v1.xEdge, sub); return; case 2: ProcMesh.addTri(mb, v2.pos, v1.xEdge, v2.yEdge, sub); return; case 3: ProcMesh.addQuad(mb, v1.pos, v1.yEdge, v2.yEdge, v2.pos, sub); return; case 4: ProcMesh.addTri(mb, v3.pos, v3.xEdge, v1.yEdge, sub); return; case 5: ProcMesh.addQuad(mb, v1.pos, v3.pos, v3.xEdge, v1.xEdge, sub); return; case 6: ProcMesh.addTri(mb, v3.pos, v3.xEdge, v1.yEdge, sub); ProcMesh.addTri(mb, v2.pos, v1.xEdge, v2.yEdge, sub); //ProcMesh.addQuad(mb, v1.yEdge, v3.xEdge, v2.yEdge, v1.xEdge, Sub.Limestone); return; case 7: ProcMesh.addTri(mb, v1.pos, v3.pos, v2.pos, sub); ProcMesh.addQuad(mb, v3.pos, v3.xEdge, v2.yEdge, v2.pos, sub); return; case 8: ProcMesh.addTri(mb, v4.pos, v2.yEdge, v3.xEdge, sub); return; case 9: ProcMesh.addTri(mb, v1.pos, v1.yEdge, v1.xEdge, sub); ProcMesh.addTri(mb, v4.pos, v2.yEdge, v3.xEdge, sub); //ProcMesh.addQuad(mb, v1.yEdge, v3.xEdge, v2.yEdge, v1.xEdge, Sub.Limestone); return; case 10: ProcMesh.addQuad(mb, v2.pos, v1.xEdge, v3.xEdge, v4.pos, sub); return; case 11: ProcMesh.addTri(mb, v1.pos, v4.pos, v2.pos, sub); ProcMesh.addQuad(mb, v1.pos, v1.yEdge, v3.xEdge, v4.pos, sub); return; case 12: ProcMesh.addQuad(mb, v3.pos, v4.pos, v2.yEdge, v1.yEdge, sub); return; case 13: ProcMesh.addTri(mb, v1.pos, v3.pos, v4.pos, sub); ProcMesh.addQuad(mb, v1.pos, v4.pos, v2.yEdge, v1.xEdge, sub); return; case 14: ProcMesh.addTri(mb, v3.pos, v4.pos, v2.pos, sub); ProcMesh.addQuad(mb, v3.pos, v2.pos, v1.xEdge, v1.yEdge, sub); return; case 15: //ProcMesh.addQuad(mb, v1.pos, v3.pos, v4.pos, v2.pos, sub);//Sub.TEST); return; default: return; } }
public static void WieldVertices(this ProcMesh mesh) { bool hasNormals = mesh.Normals.Count > 0; bool hasUVs = mesh.UVs.Count > 0; if ((hasNormals && mesh.Normals.Count != mesh.Vertices.Count) || (hasUVs && mesh.UVs.Count != mesh.Vertices.Count)) { throw new System.InvalidOperationException("Mesh does not contain equal vertex sizes!"); } for (int v = 0; v < mesh.Vertices.Count; v++) { var vertex = mesh.Vertices[v]; var normal = hasNormals ? mesh.Normals[v] : default; var uv = hasUVs ? mesh.UVs[v] : default; for (int r = v + 1; r < mesh.Vertices.Count; r++) { if (mesh.Vertices[r] != vertex) { continue; } if (hasNormals && mesh.Normals[r] != normal) { continue; } if (hasUVs && mesh.UVs[r] != uv) { continue; } mesh.Vertices.RemoveAt(r); if (hasNormals) { mesh.Normals.RemoveAt(r); } if (hasUVs) { mesh.UVs.RemoveAt(r); } for (int t = 0; t < mesh.Triangles.Count; t++) { if (mesh.Triangles[t] < r) { continue; } if (mesh.Triangles[t] == r) { mesh.Triangles[t] = v; continue; } mesh.Triangles[t] -= 1; } } } }