void AttachToNeigbor(VoxPiece vp) { foreach (Voxel v in vp.Voxels) { // Try find piece in each direction if (AttachToNeigbor(vp, v.X - 1, v.Y, v.Z)) { return; } if (AttachToNeigbor(vp, v.X + 1, v.Y, v.Z)) { return; } if (AttachToNeigbor(vp, v.X, v.Y - 1, v.Z)) { return; } if (AttachToNeigbor(vp, v.X, v.Y + 1, v.Z)) { return; } if (AttachToNeigbor(vp, v.X, v.Y, v.Z - 1)) { return; } if (AttachToNeigbor(vp, v.X, v.Y, v.Z + 1)) { return; } } }
void Attach(VoxPiece piece, VoxPiece neigbor) { foreach (Voxel v in piece.Voxels) { v.Piece = neigbor; neigbor.Voxels.Add(v); } }
void RandomlyAttach(VoxPiece vp, int x, int y, int z, float chance) { if (Random.value <= chance) { Voxel child = TryGetVoxel(x, y, z); if (child != null && child.Piece == null) { RecursiveAttach(vp, child, chance * 0.9f); } } }
bool AttachToNeigbor(VoxPiece piece, int x, int y, int z) { Voxel neighbor = TryGetVoxel(x, y, z); if (neighbor != null && neighbor.Piece != piece) { Attach(piece, neighbor.Piece); return(true); } return(false); }
void RecursiveAttach(VoxPiece vp, Voxel v, float chance) { v.Piece = vp; vp.Voxels.Add(v); // Try find piece in each direction RandomlyAttach(vp, v.X - 1, v.Y, v.Z, chance); RandomlyAttach(vp, v.X + 1, v.Y, v.Z, chance); RandomlyAttach(vp, v.X, v.Y - 1, v.Z, chance); RandomlyAttach(vp, v.X, v.Y + 1, v.Z, chance); RandomlyAttach(vp, v.X, v.Y, v.Z - 1, chance); RandomlyAttach(vp, v.X, v.Y, v.Z + 1, chance); }
// Split into pieces // For each unattached voxel // Create a piece // Recursively: // Randomly choose if neighbors are attached // Reduce chance of attaching // Recurse attached pieces void SplitIntoPieces() { foreach (Voxel v in Voxels.Values) { // If piece is not attached yet if (v.Piece == null && v.Y < 60f) { // Start a new piece by recursively attaching VoxPiece vp = new VoxPiece(); //int key = Key(v.X, v.Y, v.Z); vp.Key = Key(v); RecursiveAttach(vp, v, 1f); VoxPieces[vp.Key] = vp; } } // Find small pieces int minSize = App.Inst.MinPieceVoxels; List <VoxPiece> smallPieces = new List <VoxPiece>(); foreach (var pair in VoxPieces) { VoxPiece piece = pair.Value; if (piece.Voxels.Count < minSize) { smallPieces.Add(piece); } } // Remove small pieces from the list foreach (VoxPiece piece in smallPieces) { VoxPieces.Remove(piece.Key); } // Combine small piece with existing large piece foreach (VoxPiece piece in smallPieces) { AttachToNeigbor(piece); } Debug.LogWarning(">> Split into " + VoxPieces.Count + " pieces"); }
void AddFace(VoxPiece vp, Voxel v, Vector3 pos, float scale, Vector3 n) { // If no neighbor on that face is part of the same piece Voxel neighbor = TryGetVoxel(v.X + (int)n.x, v.Y + (int)n.y, v.Z + (int)n.z); if (neighbor == null || neighbor.Piece != vp) { // Get the voxel color int mat = v.C; // If there is a neighbor on another piece then this is an interior piece if (neighbor != null) { mat = 1; } // Add quad for that face with color UV AddVoxelFace(v, pos, scale, n, mat); } }
Piece BuildPiece(VoxPiece vp, Material mat) { GameObject go = Instantiate(App.Inst.VoxPrefab.gameObject); go.SetActive(true); Piece piece = go.GetComponent <Piece>(); Voxel firstVoxel = vp.Voxels[0]; float scale = App.Inst.CubieScale; Vector3 pos = new Vector3(firstVoxel.X, firstVoxel.Y, firstVoxel.Z); go.transform.position = pos * scale; piece.SnapPos = go.transform.localPosition; MeshFilter filter = go.GetComponent <MeshFilter>(); Mesh mesh = filter.mesh; // Set the texture Renderer rend = go.GetComponent <Renderer>(); rend.material = mat; Verts.Clear(); Norms.Clear(); Tangs.Clear(); Colors.Clear(); UVs.Clear(); Indices.Clear(); Vert = 0; // For each voxel in the pieces foreach (Voxel v in vp.Voxels) { // For each face on the voxel AddFace(vp, v, pos, scale, Vector3.left); AddFace(vp, v, pos, scale, -Vector3.left); AddFace(vp, v, pos, scale, Vector3.up); AddFace(vp, v, pos, scale, -Vector3.up); AddFace(vp, v, pos, scale, Vector3.forward); AddFace(vp, v, pos, scale, -Vector3.forward); } mesh.Clear(); mesh.SetVertices(Verts); mesh.SetNormals(Norms); mesh.SetTangents(Tangs); mesh.SetColors(Colors); mesh.SetUVs(0, UVs); mesh.SetIndices(Indices.ToArray(), MeshTopology.Triangles, 0); // Rebuild the physics mesh MeshCollider col = go.GetComponent <MeshCollider>(); col.sharedMesh = mesh; Rigidbody body = piece.GetComponent <Rigidbody>(); body.isKinematic = true; BakeAppertureLighting(piece); return(piece); }