public static VoxelFace ToOppositeFace(this VoxelFace face) { switch (face) { case (VoxelFace.Top): return(VoxelFace.Bottom); case (VoxelFace.Bottom): return(VoxelFace.Top); case (VoxelFace.Left): return(VoxelFace.Right); case (VoxelFace.Right): return(VoxelFace.Left); case (VoxelFace.Front): return(VoxelFace.Back); case (VoxelFace.Back): return(VoxelFace.Front); default: Assert.FailMessage("Invalid face"); return(VoxelFace.Top); } }
public static VoxelFaces ToFaces(this VoxelFace face) { switch (face) { case (VoxelFace.Top): return(VoxelFaces.Top); case (VoxelFace.Bottom): return(VoxelFaces.Bottom); case (VoxelFace.Left): return(VoxelFaces.Left); case (VoxelFace.Right): return(VoxelFaces.Right); case (VoxelFace.Front): return(VoxelFaces.Front); case (VoxelFace.Back): return(VoxelFaces.Back); default: return(VoxelFaces.None); } }
private static MessagePackObject WriteFace(VoxelFace face, int faceI, List <string> materials, List <string> overlays) { var faceList = new List <MessagePackObject>(); faceList.Add(faceI); if (face.material != null) { faceList.Add(materials.IndexOf(face.material.name)); } else { faceList.Add(-1); } if (face.overlay != null) { faceList.Add(overlays.IndexOf(face.overlay.name)); } else { faceList.Add(-1); } faceList.Add(face.orientation); StripDataList(faceList, new bool[] { false, face.material == null, face.overlay == null, face.orientation == 0 }); return(new MessagePackObject(faceList)); }
private JSONObject WriteVoxel(Voxel voxel, List <string> materials, List <Substance> substances) { JSONObject voxelObject = new JSONObject(); voxelObject["at"] = WriteIntVector3(voxel.transform.position); JSONArray faces = new JSONArray(); for (int faceI = 0; faceI < voxel.faces.Length; faceI++) { VoxelFace face = voxel.faces[faceI]; if (face.IsEmpty()) { continue; } faces[-1] = WriteFace(face, faceI, materials); } voxelObject["f"] = faces; if (voxel.substance != null) { voxelObject["s"].AsInt = substances.IndexOf(voxel.substance); } return(voxelObject); }
public void RemoveVoxel(IntVector3 voxel) { // Ignore if there is no voxel at that position if (VoxelMap[voxel] == 0) { return; } // First remove it from the map (capture the material first) Material material = GetMaterial(VoxelMap[voxel]); VoxelMap[voxel] = 0; // Remove faces for the voxel from the mesh foreach (FaceDirection dir in directions) { VoxelFace face = new VoxelFace(voxel, dir); VoxelMesh.Remove(face, material); } // Add faces for any adjacent voxels IntVector3 adjacentVoxel; foreach (FaceDirection dir in directions) { int adjacentVoxelId = GetAdjacentVoxel(VoxelMap, voxel, dir, out adjacentVoxel); if (adjacentVoxelId != 0) { VoxelFace face = new VoxelFace(adjacentVoxel, dir.GetOppositeFace(), halfScale); VoxelMesh.Add(face, GetMaterial(adjacentVoxelId)); } } VoxelMesh.Update(); }
} // end Adjust() private Voxel CreateSubstanceBlock(Vector3 position, Substance substance, VoxelFace faceTemplate) { if (!substance.defaultPaint.IsEmpty()) { faceTemplate = substance.defaultPaint; } Voxel voxel = VoxelAt(position, true); if (!voxel.IsEmpty()) { if (voxel.substance == substance) { return(voxel); } return(null); // doesn't work } voxel.substance = substance; for (int faceI = 0; faceI < 6; faceI++) { Voxel adjacentVoxel = VoxelAt(position + Voxel.DirectionForFaceI(faceI), false); if (adjacentVoxel == null || adjacentVoxel.substance != substance) { // create boundary voxel.faces[faceI] = faceTemplate; } else { // remove boundary adjacentVoxel.faces[Voxel.OppositeFaceI(faceI)].Clear(); voxel.faces[faceI].Clear(); } } return(voxel); }
private IEnumerator BuildMesh() { Stopwatch timer = new Stopwatch(); timer.Start(); Stopwatch yieldTimer = new Stopwatch(); yieldTimer.Start(); Debug.Log("Building Mesh..."); // Work our which faces we need. We do this by checking to see if a two voxels share and adjacent // side. ProgressMonitor.Begin("Building Mesh", VoxelMap.Size); VoxelMesh voxelMesh = new VoxelMesh(); voxelMaterials = new Dictionary <int, Material>(); foreach (var voxel in VoxelMap) { ProgressMonitor.Worked(1); if (NeedsYield(yieldTimer)) { yield return(null); } if (voxel.Value == 0) { continue; } Material material = GetMaterial(voxel.Value); foreach (FaceDirection dir in directions) { if (GetAdjacentVoxel(VoxelMap, voxel.Key, dir) == 0) { // Add the face VoxelFace face = new VoxelFace(voxel.Key, dir, halfScale); voxelMesh.Add(face, material); } // else don't need a face here } } // Update and parent the meshes voxelMesh.Update(); foreach (var meshGO in voxelMesh.GetGameObjects()) { meshGO.transform.parent = gameObject.transform; meshGO.transform.localPosition = VoxelMap.Offset; // Not sure this is right...should it be scaled? meshGO.transform.localRotation = Quaternion.identity; } // We're done! ProgressMonitor.Finished(); VoxelMesh = voxelMesh; Debug.Log($"Completed in {timer.ElapsedMilliseconds / 1000.0f:F2}s"); }
public static VoxelFace getBlockVoxelFace(Vector3 offset, int faceId, int textureIndex) { VoxelFace face = new VoxelFace(); face.vertices[0] = _vertices[_faceVertices[faceId, 0]] + offset; face.vertices[1] = _vertices[_faceVertices[faceId, 1]] + offset; face.vertices[2] = _vertices[_faceVertices[faceId, 2]] + offset; face.vertices[3] = _vertices[_faceVertices[faceId, 3]] + offset; // TODO Make a texture manager Component to get textures, for now Hard code to a single texture face.uvs[0] = _uvs[0]; face.uvs[1] = _uvs[1]; face.uvs[2] = _uvs[2]; face.uvs[3] = _uvs[3]; Vector3 normal = new Vector3(0, 0, -1); face.normals[0] = _normals[faceId]; face.normals[1] = _normals[faceId]; face.normals[2] = _normals[faceId]; face.normals[3] = _normals[faceId]; face.triangles[0] = _triangleVertices[faceId, 0]; face.triangles[1] = _triangleVertices[faceId, 1]; face.triangles[2] = _triangleVertices[faceId, 2]; face.triangles[3] = _triangleVertices[faceId, 3]; face.triangles[4] = _triangleVertices[faceId, 4]; face.triangles[5] = _triangleVertices[faceId, 5]; return(face); }
private VoxelFace ReadFace(MessagePackObject faceObj, out int faceI, List <Material> materials, List <Material> overlays) { VoxelFace face = new VoxelFace(); var faceList = faceObj.AsList(); if (faceList.Count >= 1) { faceI = faceList[0].AsInt32(); } else { faceI = -1; } if (faceList.Count >= 2 && faceList[1].AsInt32() != -1) { face.material = materials[faceList[1].AsInt32()]; } if (faceList.Count >= 3 && faceList[2].AsInt32() != -1) { face.overlay = overlays[faceList[2].AsInt32()]; } if (faceList.Count >= 4) { face.orientation = faceList[3].AsByte(); } return(face); }
private static List <Pixel> GetPixels( List <VoxelFace> faces, out int minPixelX, out int minPixelY, out int maxPixelX, out int maxPixelY ) { minPixelX = int.MaxValue; minPixelY = int.MaxValue; maxPixelX = 0; maxPixelY = 0; List <Pixel> pixels = new List <Pixel>(); int count = faces.Count; for (int index = 0; index < count; index++) { VoxelFace face = faces[index]; float pixelSize = 1f; Vector2 pos = new Vector2( (face.Position.x * pixelSize), (face.Position.y * pixelSize) ); pos.x = Mathf.Floor((pos.x / pixelSize) * pixelSize); pos.y = Mathf.Floor((pos.y / pixelSize) * pixelSize); minPixelX = Mathf.Min(minPixelX, (int)pos.x); minPixelY = Mathf.Min(minPixelY, (int)pos.y); maxPixelX = Mathf.Max((int)pos.x, maxPixelX); maxPixelY = Mathf.Max((int)pos.y, maxPixelY); pixels.Add(new Pixel() { Color = face.Color, X = (int)pos.x, Y = (int)pos.y }); } return(pixels); }
private static MessagePackObject WriteFace(VoxelFace face, int faceI, Dictionary <Material, int> materials, Dictionary <Material, int> overlays) { var faceList = new List <MessagePackObject>(); faceList.Add(faceI); if (face.material != null) { faceList.Add(materials[face.material]); } else { faceList.Add(-1); } if (face.overlay != null) { faceList.Add(overlays[face.overlay]); } else { faceList.Add(-1); } faceList.Add(face.orientation); StripDataList(faceList, new bool[] { false, face.material == null, face.overlay == null, face.orientation == 0 }); return(new MessagePackObject(faceList)); }
private static List <VoxelFace> GetFaces( Voxel[,,] voxels, Color[] palette, Vector3 voxelSize, Vector3 mainPivot, Quaternion cameraRot, Vector3 pivotOffset, int cameraAngleIndex, float lightIntensity, out Vector3 minPos, out Vector3 maxPos ) { lightIntensity = Mathf.Lerp(0f, 0.7f, lightIntensity * 0.2f); minPos = Vector3.one * float.MaxValue; maxPos = Vector3.one * float.MinValue; List <VoxelFace> faces = new List <VoxelFace>(); for (int x = 0; x < voxelSize.x; x++) { for (int y = 0; y < voxelSize.y; y++) { for (int z = 0; z < voxelSize.z; z++) { Voxel vox = voxels[x, y, z]; Color color = palette[vox.ColorIndex <= 0 ? 0 : vox.ColorIndex - 1]; for (int i = 0; i < 6; i++) { if (!vox.IsEmpty && vox.Visible[i]) { Vector3 pos = cameraRot * (new Vector3( x - voxelSize.x * mainPivot.x, z - voxelSize.z * mainPivot.y, y - voxelSize.y * mainPivot.z ) + VOX_CENTER_OFFSET[i] * 0.5f) + pivotOffset; minPos = Vector3.Min(minPos, pos); maxPos = Vector3.Max(maxPos, pos); Vector3 worldNormal = cameraRot * VOX_CENTER_OFFSET[i]; // Normal Check if (Vector3.Angle(worldNormal, Vector3.back) >= 90f) { continue; } VoxelFace face = new VoxelFace() { Position = pos, Normal = worldNormal, Type = VoxelFace.GetFaceType(cameraAngleIndex, (Direction)i, worldNormal.x), }; face.Color = Color.Lerp( color, (int)face.Type > 3 ? Color.black : color, (int)face.Type > 3 ? (int)face.Type > 7 ? lightIntensity * 0.5f : lightIntensity : 1f ); faces.Add(face); } } } } } faces.Sort(new FaceSorter()); return(faces); }
public override bool Equals(object obj) { if (!(obj is VoxelFace)) { return(false); } VoxelFace otherFace = (VoxelFace)obj; return(otherFace.Origin.Equals(Origin) && otherFace.Direction.Equals(Direction)); }
public VoxelFace GetSelectedPaint() { // because of the order of IterateSelected, add selected faces will be preferred foreach (VoxelFaceReference faceRef in IterateSelectedFaces()) { VoxelFace face = faceRef.face; face.addSelected = false; face.storedSelected = false; return(face); } return(new VoxelFace()); }
public override VoxelMaterial GetMaterialForInput(Vector3Int fromCoord, VoxelCell fromCell, Vector3Int toCoord, VoxelCell toCell) { VoxelFace face = VoxelFaceHelpers.NormalToFace(toCoord - fromCoord); var surface = m_Table.CellToResource(fromCell); if (surface != null) { return(surface.GetMaterialForFace(face)); } return(null); }
public void PaintSelectedFaces(VoxelFace paint) { foreach (VoxelFaceReference faceRef in IterateSelectedFaces()) { if (paint.material != null || faceRef.voxel.substance != null) { faceRef.voxel.faces[faceRef.faceI].material = paint.material; } faceRef.voxel.faces[faceRef.faceI].overlay = paint.overlay; faceRef.voxel.faces[faceRef.faceI].orientation = paint.orientation; VoxelModified(faceRef.voxel); } }
public void Remove(VoxelFace face, Material material) { foreach (var meshDetails in meshDetailsList) { if (meshDetails.material == material && meshDetails.faces.Contains(face)) { meshDetails.faces.Remove(face); meshDetails.dirty = true; return; } } }
public void SelectAllWithPaint(VoxelFace paint) { foreach (Voxel voxel in IterateVoxels()) { for (int faceI = 0; faceI < 6; faceI++) { if (voxel.faces[faceI].Equals(paint)) { SelectFace(voxel, faceI); } } } AutoSetMoveAxesEnabled(); }
private static MessagePackObject WriteVoxel(Voxel voxel, Dictionary <Material, int> materials, Dictionary <Material, int> overlays, Dictionary <Substance, int> substances) { var voxelList = new List <MessagePackObject>(); voxelList.Add(WriteVector3Int(voxel.position)); var facesList = new List <MessagePackObject>(); for (int faceI = 0; faceI < voxel.faces.Length; faceI++) { VoxelFace face = voxel.faces[faceI]; if (face.IsEmpty()) { continue; } facesList.Add(WriteFace(face, faceI, materials, overlays)); } voxelList.Add(new MessagePackObject(facesList)); if (voxel.substance != null) { voxelList.Add(substances[voxel.substance]); } else { voxelList.Add(-1); } var edgesList = new List <MessagePackObject>(); for (int edgeI = 0; edgeI < voxel.edges.Length; edgeI++) { VoxelEdge edge = voxel.edges[edgeI]; if (!edge.hasBevel) { continue; } edgesList.Add(WriteEdge(edge, edgeI)); } voxelList.Add(new MessagePackObject(edgesList)); StripDataList(voxelList, new bool[] { false, facesList.Count == 0, voxel.substance == null, edgesList.Count == 0 }); return(new MessagePackObject(voxelList)); }
private void DrawPaint(VoxelFace paint, Rect rect) { float rotation = VoxelFace.GetOrientationRotation(paint.orientation) * 90; Vector2 scaleFactor = Vector2.one; if (VoxelFace.GetOrientationMirror(paint.orientation)) { scaleFactor = new Vector2(-1, 1); rotation += 90; } Matrix4x4 baseMatrix = GUI.matrix; RotateAboutPoint(rect.center, rotation, scaleFactor); MaterialSelectorGUI.DrawMaterialTexture(paint.material, rect, false); MaterialSelectorGUI.DrawMaterialTexture(paint.overlay, rect, true); GUI.matrix = baseMatrix; }
public void SurfaceSelectFloodFill(Voxel voxel, int faceI, Substance substance) { if (voxel == null) { return; } if (voxel.substance != substance) { return; } VoxelFace face = voxel.faces[faceI]; if (face.IsEmpty()) { return; } if (face.addSelected || face.storedSelected) // stop at boundaries of stored selection { return; } SelectFace(voxel, faceI); Vector3 position = voxel.transform.position; for (int sideNum = 0; sideNum < 4; sideNum++) { int sideFaceI = Voxel.SideFaceI(faceI, sideNum); SurfaceSelectFloodFill(voxel, sideFaceI, substance); Vector3 newPos = position + Voxel.DirectionForFaceI(sideFaceI); SurfaceSelectFloodFill(VoxelAt(newPos, false), faceI, substance); newPos += Voxel.DirectionForFaceI(faceI); SurfaceSelectFloodFill(VoxelAt(newPos, false), Voxel.OppositeFaceI(sideFaceI), substance); } if (selectMode != SelectMode.SURFACE) { selectionBounds = voxel.GetFaceBounds(faceI); } else { selectionBounds.Encapsulate(voxel.GetFaceBounds(faceI)); } selectMode = SelectMode.SURFACE; SetMoveAxes(position + new Vector3(0.5f, 0.5f, 0.5f) - Voxel.OppositeDirectionForFaceI(faceI) / 2); }
private void SelectByPaintInterface() { FacePickerGUI facePicker = gameObject.AddComponent <FacePickerGUI>(); facePicker.voxelArray = voxelArray; facePicker.message = "Tap to pick paint..."; facePicker.onlyFaces = true; facePicker.clearStoredSelection = false; facePicker.pickAction = () => { VoxelFace paint = voxelArray.GetSelectedPaint(); voxelArray.ClearSelection(); if (paint.IsEmpty()) { return; } voxelArray.SelectAllWithPaint(paint); }; }
public void Add(VoxelFace face, Material material) { foreach (var meshDetails in meshDetailsList) { if (meshDetails.material == material && meshDetails.faces.Count < MAX_FACES_PER_MESH) { meshDetails.faces.Add(face); meshDetails.dirty = true; return; } } var newMeshDetails = new MeshDetails(material); newMeshDetails.faces.Add(face); meshDetailsList.Add(newMeshDetails); }
// default block voxel renderer public static VoxelMeshData getVoxelMeshData(Boolean[] renderFaces, Vector3Int offset) { int textureIndex = 0; List <VoxelFace> faces = new List <VoxelFace>(); for (int i = 0; i < 6; i++) { if (renderFaces[i] == false) { continue; } VoxelFace face = getBlockVoxelFace(offset, i, textureIndex); faces.Add(face); } return(GetVoxelMeshFromFaces(faces)); }
private JSONObject WriteFace(VoxelFace face, int faceI, List <string> materials) { JSONObject faceObject = new JSONObject(); faceObject["i"].AsInt = faceI; if (face.material != null) { faceObject["mat"].AsInt = materials.IndexOf(face.material.name); } if (face.overlay != null) { faceObject["over"].AsInt = materials.IndexOf(face.overlay.name); } if (face.orientation != 0) { faceObject["orient"].AsInt = face.orientation; } return(faceObject); }
public static Vector3Int Direction(VoxelFace face) { switch (face) { case VoxelFace.Back: return(new Vector3Int(1, 0, 0)); case VoxelFace.Front: return(new Vector3Int(-1, 0, 0)); case VoxelFace.Left: return(new Vector3Int(0, 0, -1)); case VoxelFace.Right: return(new Vector3Int(0, 0, 1)); case VoxelFace.Top: return(new Vector3Int(0, 1, 0)); case VoxelFace.Bottom: return(new Vector3Int(0, -1, 0)); default: throw new ArgumentException(); } }
private void ReadVoxel(MessagePackObject voxelObj, VoxelArray voxelArray, List <Material> materials, List <Material> overlays, List <Substance> substances) { var voxelList = voxelObj.AsList(); if (voxelList.Count == 0) { return; } Vector3Int position = ReadVector3Int(voxelList[0]); Voxel voxel = null; voxel = voxelArray.VoxelAt(position, true); if (voxelList.Count >= 2) { foreach (var faceObj in voxelList[1].AsList()) { VoxelFace face = ReadFace(faceObj, out int faceI, materials, overlays); if (faceI != -1) { voxel.faces[faceI] = face; } } } if (voxelList.Count >= 3 && voxelList[2].AsInt32() != -1) { voxel.substance = substances[voxelList[2].AsInt32()]; } if (voxelList.Count >= 4) { foreach (var edgeObj in voxelList[3].AsList()) { ReadEdge(edgeObj, voxel); } } voxel.UpdateVoxel(); }
public static string GetTextureID(BlockType block, VoxelFace face) { switch (face) { case VoxelFace.Back: return(block.back); case VoxelFace.Front: return(block.front); case VoxelFace.Top: return(block.top); case VoxelFace.Bottom: return(block.bottom); case VoxelFace.Left: return(block.left); case VoxelFace.Right: return(block.right); default: throw new NotSupportedException(); } ; }
private void Orient(byte change) { int changeRotation = VoxelFace.GetOrientationRotation(change); bool changeFlip = VoxelFace.GetOrientationMirror(change); int paintRotation = VoxelFace.GetOrientationRotation(paint.orientation); bool paintFlip = VoxelFace.GetOrientationMirror(paint.orientation); if (paintFlip ^ changeFlip) { paintRotation += 4 - changeRotation; } else { paintRotation += changeRotation; } if (changeFlip) { paintFlip = !paintFlip; } paint.orientation = VoxelFace.Orientation(paintRotation, paintFlip); handler(paint); }
public void ConnectVoxelsFacesOnly(int i, int j, float sA) { // create a new Voxel_Face connecting i to j VoxelFace vF1 = new VoxelFace(); int k = voxelFaces.Count; vF1.meshIndex = k; vF1.surfaceArea = sA; vF1.outwardNormal = voxels[j].center - voxels[i].center; vF1.outwardNormal = Vector3.Normalize(vF1.outwardNormal); vF1.inwardNormal = vF1.outwardNormal; vF1.inwardNormal *= -1.0f; // convention: face is oriented from lower index to higher index if (j < i) { vF1.outwardNormal *= -1.0f; vF1.inwardNormal *= -1.0f; } // add it to the vector of voxel faces voxelFaces.Add(vF1); }
//welding two points only public void Weld( VoxelFace f2 , int p1 , int p2 ) { //no vert - creating it if (verts[p1]==null && f2.verts[p2]==null) verts[p1] = f2.verts[p2] = new VoxelVert(); //one of the verts exist - assign it to the other one else if (f2.verts[p2]==null && verts[p1]!=null) f2.verts[p2] = verts[p1]; else if (verts[p1]==null && f2.verts[p2]!=null) verts[p1] = f2.verts[p2]; verts[p1].AddFace(this); verts[p1].AddFace(f2); //if both of the verts exist - welding if (verts[p1]!=null && f2.verts[p2]!=null && verts[p1].coords != f2.verts[p2].coords) verts[p1].Replace(f2.verts[p2]); }
//welding three poins (side) using mid-point number public void Weld( VoxelFace fB , int pA2 , int pB2 , bool inverted ) { Weld(fB, prewPoint[pA2], nextPoint[pB2]); Weld(fB, pA2, pB2); Weld(fB, nextPoint[pA2], prewPoint[pB2]); }
public void AddFace( VoxelFace face ) { for (int i=0; i<6; i++) { if (faces[i]!=null) { if (faces[i] == face) return; //already added } else { faces[i] = face; break; } } }
public static void GenerateGreedy(List<Vector3> vertices, List<Vector2> uvs, List<Color32> colors, List<int> indexes, ref Vector3[] vertArray, ref Vector2[] uvArray, ref Color32[] colorArray, ref int[] indexArray, ref Voxel[] invoxels, float voxelSize,float overlapAmount, int xOffset, int yOffset, int zOffset, int xSize, int ySize, int zSize, int ub0, int ub1, int ub2, float selfShadeIntensity) #endif { vertices.Clear(); uvs.Clear(); colors.Clear(); indexes.Clear(); int i, j, k, l, w, h, u, v, n, side = 0; int[] x = new int[] { 0, 0, 0 }; int[] q = new int[] { 0, 0, 0 }; int[] du = new int[] { 0, 0, 0 }; int[] dv = new int[] { 0, 0, 0 }; int[] size = { xSize, ySize, zSize }; VoxelFace[] mask = new VoxelFace[(xSize * ySize * zSize) * 2]; VoxelFace voxelFace, voxelFace1; for (bool backFace = true, b = false; b != backFace; backFace = backFace && b, b = !b) { for (int d = 0; d < 3; d++) { u = (d + 1) % 3; v = (d + 2) % 3; x[0] = 0; x[1] = 0; x[2] = 0; q[0] = 0; q[1] = 0; q[2] = 0; q[d] = 1; if (d == 0) { side = backFace ? WEST : EAST; } else if (d == 1) { side = backFace ? BOTTOM : TOP; } else if (d == 2) { side = backFace ? SOUTH : NORTH; } for (x[d] = -1; x[d] < size[d];) { n = 0; for (x[v] = 0; x[v] < size[v]; x[v]++) { for (x[u] = 0; x[u] < size[u]; x[u]++) { if (x[d] >= 0) { voxelFace = new VoxelFace(); #if UNITY_EDITOR GetVoxelFace(voxelFace, x[0], x[1], x[2], side, ref invoxels, voxelSize, xOffset, yOffset, zOffset, xSize, ySize, zSize, ub0, ub1, ub2, selfShadeIntensity, paintMode); #else GetVoxelFace(voxelFace, x[0], x[1], x[2], side, ref invoxels, voxelSize, xOffset, yOffset, zOffset, xSize, ySize, zSize, ub0, ub1, ub2, selfShadeIntensity); #endif } else voxelFace = null; if (x[d] < size[d] - 1) { voxelFace1 = new VoxelFace(); #if UNITY_EDITOR GetVoxelFace(voxelFace1, x[0] + q[0], x[1] + q[1], x[2] + q[2], side, ref invoxels, voxelSize, xOffset, yOffset, zOffset, xSize, ySize, zSize, ub0, ub1, ub2, selfShadeIntensity, paintMode); #else GetVoxelFace(voxelFace1, x[0] + q[0], x[1] + q[1], x[2] + q[2], side, ref invoxels, voxelSize, xOffset, yOffset, zOffset, xSize, ySize, zSize, ub0, ub1, ub2, selfShadeIntensity); #endif } else voxelFace1 = null; if (voxelFace != null && voxelFace1 != null && voxelFace.Equals(voxelFace1)) mask[n++] = null; else { if(!backFace && voxelFace!=null) mask[n++] = new VoxelFace() { Active = voxelFace.Active, Color = voxelFace.Color, Side = voxelFace.Side, VertShade = voxelFace.VertShade }; if(backFace && voxelFace1!=null) mask[n++] = new VoxelFace() { Active = voxelFace1.Active, Color = voxelFace1.Color, Side = voxelFace1.Side, VertShade = voxelFace1.VertShade }; } } } x[d]++; n = 0; for (j = 0; j < size[v]; j++) { for (i = 0; i < size[u];) { if (mask[n] != null) { for (w = 1; i + w < size[u] && mask[n + w] != null && mask[n + w].Equals(mask[n]); w++) { } bool done = false; for (h = 1; j + h < size[v]; h++) { for (k = 0; k < w; k++) { if (mask[n + k + h*size[u]] == null || !mask[n + k + h*size[u]].Equals(mask[n])) { done = true; break; } } if (done) { break; } } if (mask[n].Active) { x[u] = i; x[v] = j; du[0] = 0; du[1] = 0; du[2] = 0; du[u] = w; dv[0] = 0; dv[1] = 0; dv[2] = 0; dv[v] = h; Quad(new Vector3(x[0] + du[0], x[1] + du[1], x[2] + du[2]), new Vector3(x[0] + du[0] + dv[0], x[1] + du[1] + dv[1], x[2] + du[2] + dv[2]), new Vector3(x[0] + dv[0], x[1] + dv[1], x[2] + dv[2]), new Vector3(x[0], x[1], x[2]), side, voxelSize, overlapAmount, mask[n], backFace, selfShadeIntensity, vertices, indexes, colors, uvs); } for (l = 0; l < h; ++l) { for (k = 0; k < w; ++k) { mask[n + k + l*size[u]] = null; } } i += w; n += w; } else { i++; n++; } } } } } } vertArray = vertices.ToArray(); uvArray = uvs.ToArray(); colorArray = colors.ToArray(); indexArray = indexes.ToArray(); }
public bool Equals(VoxelFace face) { return face.Active==Active && face.Color == Color && face.VertShade == VertShade; }
static void Quad(Vector3 topLeft, Vector3 topRight, Vector3 bottomRight,Vector3 bottomLeft,int dir,float voxelSize,float overlapAmount, VoxelFace voxel, bool backFace,float selfShadeIntensity,List<Vector3> vertices, List<int> indexes, List<Color32> colors, List<Vector2> uvs) { int index = vertices.Count; Vector3 overlapBL = Vector3.zero; Vector3 overlapBR = Vector3.zero; Vector3 overlapTL = Vector3.zero; Vector3 overlapTR = Vector3.zero; if (overlapAmount > 0f) { switch (dir) { case 0: case 1: overlapBL = new Vector3(-1, -1, 0)*overlapAmount; overlapBR = new Vector3(-1, 1, 0)*overlapAmount; overlapTR = new Vector3(1, 1, 0)*overlapAmount; overlapTL = new Vector3(1, -1, 0)*overlapAmount; break; case 2: case 3: overlapBL = new Vector3(0, -1, -1)*overlapAmount; overlapBR = new Vector3(0, -1, 1)*overlapAmount; overlapTR = new Vector3(0, 1, 1)*overlapAmount; overlapTL = new Vector3(0, 1, -1)*overlapAmount; break; case 4: case 5: overlapBL = new Vector3(-1, 0, -1)*overlapAmount; overlapBR = new Vector3(1, 0, -1)*overlapAmount; overlapTR = new Vector3(1, 0, 1)*overlapAmount; overlapTL = new Vector3(-1, 0, 1)*overlapAmount; break; } } vertices.Add((bottomLeft * voxelSize) + overlapBL); vertices.Add((bottomRight * voxelSize) + overlapBR); vertices.Add((topLeft * voxelSize) + overlapTL); vertices.Add((topRight * voxelSize) + overlapTR); Color temp = IntToColor(voxel.Color); int test1 = (((voxel.VertShade & Corners.TopRight) == Corners.TopRight) ? 1 : 0) + (((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft) ? 1 : 0) + (((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft) ? 1 : 0) + (((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight) ? 1 : 0); int test2 = (((voxel.VertShade & Corners.TopRight) == Corners.TopRight) ? 1 : 0) + (((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft) ? 1 : 0); int test3 = (((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft) ? 1 : 0) + (((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight) ? 1 : 0); if (((test2 > test3) && (test1>2)) || ((test2<=test3) && (test1==1))) { colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft ? (1f - selfShadeIntensity) : 1f), temp.a)); colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft ? (1f - selfShadeIntensity) : 1f), temp.a)); colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.TopRight) == Corners.TopRight ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.TopRight) == Corners.TopRight ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.TopRight) == Corners.TopRight ? (1f - selfShadeIntensity) : 1f), temp.a)); colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight ? (1f - selfShadeIntensity) : 1f), temp.a)); if (backFace) { indexes.Add(index + 2); indexes.Add(index); indexes.Add(index + 1); indexes.Add(index + 1); indexes.Add(index + 3); indexes.Add(index + 2); } else { indexes.Add(index + 2); indexes.Add(index + 3); indexes.Add(index + 1); indexes.Add(index + 1); indexes.Add(index); indexes.Add(index + 2); } } else { colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft ? (1f - selfShadeIntensity) : 1f), temp.a)); colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft ? (1f - selfShadeIntensity) : 1f), temp.a)); colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.TopRight) == Corners.TopRight ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.TopRight) == Corners.TopRight ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.TopRight) == Corners.TopRight ? (1f - selfShadeIntensity) : 1f), temp.a)); colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight ? (1f - selfShadeIntensity) : 1f), temp.a)); if (backFace) { indexes.Add(index + 3); indexes.Add(index + 2); indexes.Add(index); indexes.Add(index); indexes.Add(index + 1); indexes.Add(index + 3); } else { indexes.Add(index + 3); indexes.Add(index + 1); indexes.Add(index); indexes.Add(index); indexes.Add(index + 2); indexes.Add(index + 3); } } uvs.Add(new Vector2(0f, 0f)); uvs.Add(new Vector2(1f, 0f)); uvs.Add(new Vector2(0f, 1f)); uvs.Add(new Vector2(1f, 1f)); }
static void GetVoxelFace(VoxelFace voxelFace, int x, int y, int z, int side, ref Voxel[] invoxels, float voxelSize, int xOffset, int yOffset, int zOffset, int xSize, int ySize, int zSize, int ub0, int ub1, int ub2, float selfShadeIntensity) #endif { Voxel v = invoxels[(x + xOffset) + (ub0 + 1)*((y + yOffset) + (ub1 + 1)*(z + zOffset))]; voxelFace.Active = v.Active; #if UNITY_EDITOR if(paintMode == EditorPaintMode.Color) voxelFace.Color = ColorToInt(v.Color); else voxelFace.Color = ColorToInt(new Color32(v.Value,v.Value,v.Value,255)); #else voxelFace.Color = ColorToInt(v.Color); #endif voxelFace.VertShade = 0; voxelFace.Side = side; if (!voxelFace.Active) return; if (selfShadeIntensity > 0f) { switch (side) { case 0: case 1: if (IsVoxelAt(x + xOffset -1, y + yOffset, z + zOffset + (side==0?-1:1), ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset - 1, y + yOffset - 1, z + zOffset + (side == 0 ? -1 : 1), ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset, y + yOffset - 1, z + zOffset + (side == 0 ? -1 : 1), ref invoxels, ub0, ub1, ub2)) voxelFace.VertShade |= Corners.TopLeft; if (IsVoxelAt(x + xOffset + 1, y + yOffset, z + zOffset + (side == 0 ? -1 : 1), ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset + 1, y + yOffset - 1, z + zOffset + (side == 0 ? -1 : 1), ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset, y + yOffset - 1, z + zOffset + (side == 0 ? -1 : 1), ref invoxels, ub0, ub1, ub2)) voxelFace.VertShade |= Corners.TopRight; if (IsVoxelAt(x + xOffset - 1, y + yOffset, z + zOffset + (side == 0 ? -1 : 1), ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset - 1, y + yOffset + 1, z + zOffset + (side == 0 ? -1 : 1), ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset, y + yOffset + 1, z + zOffset + (side == 0 ? -1 : 1), ref invoxels, ub0, ub1, ub2)) voxelFace.VertShade |= Corners.BottomLeft; if (IsVoxelAt(x + xOffset + 1, y + yOffset, z + zOffset + (side == 0 ? -1 : 1), ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset + 1, y + yOffset + 1, z + zOffset + (side == 0 ? -1 : 1), ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset, y + yOffset + 1, z + zOffset + (side == 0 ? -1 : 1), ref invoxels, ub0, ub1, ub2)) voxelFace.VertShade |= Corners.BottomRight; break; case 2: case 3: if (IsVoxelAt(x + xOffset + (side == 3 ? -1 : 1), y + yOffset, z + zOffset-1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset + (side == 3 ? -1 : 1), y + yOffset - 1, z + zOffset-1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset + (side == 3 ? -1 : 1), y + yOffset - 1, z + zOffset, ref invoxels, ub0, ub1, ub2)) voxelFace.VertShade |= Corners.TopLeft; if (IsVoxelAt(x + xOffset + (side == 3 ? -1 : 1), y + yOffset, z + zOffset + 1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset + (side == 3 ? -1 : 1), y + yOffset - 1, z + zOffset + 1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset + (side == 3 ? -1 : 1), y + yOffset - 1, z + zOffset, ref invoxels, ub0, ub1, ub2)) voxelFace.VertShade |= Corners.BottomLeft; if (IsVoxelAt(x + xOffset + (side == 3 ? -1 : 1), y + yOffset, z + zOffset - 1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset + (side == 3 ? -1 : 1), y + yOffset + 1, z + zOffset - 1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset + (side == 3 ? -1 : 1), y + yOffset + 1, z + zOffset, ref invoxels, ub0, ub1, ub2)) voxelFace.VertShade |= Corners.TopRight; if (IsVoxelAt(x + xOffset + (side == 3 ? -1 : 1), y + yOffset, z + zOffset + 1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset + (side == 3 ? -1 : 1), y + yOffset + 1, z + zOffset + 1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset + (side == 3 ? -1 : 1), y + yOffset + 1, z + zOffset, ref invoxels, ub0, ub1, ub2)) voxelFace.VertShade |= Corners.BottomRight; break; case 4: case 5: if (IsVoxelAt(x + xOffset, y + yOffset + (side == 5 ? -1 : 1), z + zOffset - 1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset-1, y + yOffset + (side == 5 ? -1 : 1), z + zOffset - 1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset-1, y + yOffset + (side == 5 ? -1 : 1), z + zOffset, ref invoxels, ub0, ub1, ub2)) voxelFace.VertShade |= Corners.TopLeft; if (IsVoxelAt(x + xOffset, y + yOffset + (side == 5 ? -1 : 1), z + zOffset + 1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset-1, y + yOffset + (side == 5 ? -1 : 1), z + zOffset + 1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset-1, y + yOffset + (side == 5 ? -1 : 1), z + zOffset, ref invoxels, ub0, ub1, ub2)) voxelFace.VertShade |= Corners.TopRight; if (IsVoxelAt(x + xOffset, y + yOffset + (side == 5 ? -1 : 1), z + zOffset - 1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset+1, y + yOffset + (side == 5 ? -1 : 1), z + zOffset - 1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset+1, y + yOffset + (side == 5 ? -1 : 1), z + zOffset, ref invoxels, ub0, ub1, ub2)) voxelFace.VertShade |= Corners.BottomLeft; if (IsVoxelAt(x + xOffset, y + yOffset + (side == 5 ? -1 : 1), z + zOffset + 1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset+1, y + yOffset + (side == 5 ? -1 : 1), z + zOffset + 1, ref invoxels, ub0, ub1, ub2) || IsVoxelAt(x + xOffset+1, y + yOffset + (side == 5 ? -1 : 1), z + zOffset, ref invoxels, ub0, ub1, ub2)) voxelFace.VertShade |= Corners.BottomRight; break; } } switch (side) { case 0: voxelFace.Active = !IsVoxelAt(x + xOffset, y + yOffset, z+zOffset - 1, ref invoxels, ub0, ub1, ub2); break; case 1: voxelFace.Active = !IsVoxelAt(x + xOffset, y + yOffset, z + zOffset + 1, ref invoxels, ub0, ub1, ub2); break; case 2: voxelFace.Active = !IsVoxelAt(x + xOffset + 1, y + yOffset, z + zOffset, ref invoxels, ub0, ub1, ub2); break; case 3: voxelFace.Active = !IsVoxelAt(x + xOffset - 1, y + yOffset, z + zOffset, ref invoxels, ub0, ub1, ub2); break; case 4: voxelFace.Active = !IsVoxelAt(x + xOffset, y + yOffset + 1, z + zOffset, ref invoxels, ub0, ub1, ub2); break; case 5: voxelFace.Active = !IsVoxelAt(x + xOffset, y + yOffset - 1, z + zOffset, ref invoxels, ub0, ub1, ub2); break; } }
static void GetVoxelFace(VoxelFace voxelFace, int x, int y, int z, int side, ref Voxel[] invoxels, float voxelSize, int xOffset, int yOffset, int zOffset, int xSize, int ySize, int zSize, int ub0, int ub1, int ub2, float selfShadeIntensity, EditorPaintMode paintMode)
public static void GenerateCulled(List<Vector3> vertices, List<Vector2> uvs, List<Color32> colors, List<int> indexes, ref Vector3[] vertArray, ref Vector2[] uvArray, ref Color32[] colorArray, ref int[] indexArray, ref Voxel[] invoxels, float voxelSize,float overlapAmount, int xOffset, int yOffset, int zOffset, int xSize, int ySize, int zSize, int ub0, int ub1, int ub2, float selfShadeIntensity) #endif { vertices.Clear(); uvs.Clear(); colors.Clear(); indexes.Clear(); VoxelFace vf = new VoxelFace(); for (int z = 0; z < zSize; z++) for (int y = 0; y < ySize; y++) for (int x = 0; x < xSize; x++) { if (invoxels[xOffset + x + (ub0 + 1) * (yOffset + y + (ub1 + 1) * (zOffset + z))].Active == false) continue; Vector3 worldOffset = (new Vector3(x, y, z)); for (int f = 0; f < 6; f++) { #if UNITY_EDITOR GetVoxelFace(vf, x, y, z, f, ref invoxels, voxelSize, xOffset, yOffset, zOffset, xSize, ySize, zSize, ub0, ub1, ub2, selfShadeIntensity, paintMode); #else GetVoxelFace(vf, x, y, z, f, ref invoxels, voxelSize, xOffset, yOffset, zOffset, xSize, ySize, zSize, ub0, ub1, ub2, selfShadeIntensity); #endif if (vf.Active) { switch (f) { case 0: Quad(worldOffset + new Vector3(1, 0, 0), worldOffset + new Vector3(1, 1, 0), worldOffset + new Vector3(0, 1, 0), worldOffset + new Vector3(0, 0, 0), f, voxelSize, overlapAmount, vf, true, selfShadeIntensity, vertices, indexes, colors, uvs); break; case 1: Quad(worldOffset + new Vector3(1, 0, 1), worldOffset + new Vector3(1, 1, 1), worldOffset + new Vector3(0, 1, 1), worldOffset + new Vector3(0, 0, 1), f, voxelSize, overlapAmount, vf, false, selfShadeIntensity, vertices, indexes, colors, uvs); break; case 2: Quad(worldOffset + new Vector3(1, 1, 0), worldOffset + new Vector3(1, 1, 1), worldOffset + new Vector3(1, 0, 1), worldOffset + new Vector3(1, 0, 0), f, voxelSize, overlapAmount, vf, false, selfShadeIntensity, vertices, indexes, colors, uvs); break; case 3: Quad(worldOffset + new Vector3(0, 1, 0), worldOffset + new Vector3(0, 1, 1), worldOffset + new Vector3(0, 0, 1), worldOffset + new Vector3(0, 0, 0), f, voxelSize, overlapAmount, vf, true, selfShadeIntensity, vertices, indexes, colors, uvs); break; case 4: Quad(worldOffset + new Vector3(0, 1, 1), worldOffset + new Vector3(1, 1, 1), worldOffset + new Vector3(1, 1, 0), worldOffset + new Vector3(0, 1, 0), f, voxelSize, overlapAmount, vf, false, selfShadeIntensity, vertices, indexes, colors, uvs); break; case 5: Quad(worldOffset + new Vector3(0, 0, 1), worldOffset + new Vector3(1, 0, 1), worldOffset + new Vector3(1, 0, 0), worldOffset + new Vector3(0, 0, 0), f, voxelSize, overlapAmount, vf, true, selfShadeIntensity, vertices, indexes, colors, uvs); break; } } } } vertArray = vertices.ToArray(); uvArray = uvs.ToArray(); colorArray = colors.ToArray(); indexArray = indexes.ToArray(); }
public void CalculateTerrain() { terrainProgress = Progress.threadStarted; //bool isMainThread = System.Threading.Thread.CurrentThread.ManagedThreadId == Voxel.mainThreadId; //bool isMainThread = false; int x=0; int y=0; int z=0; //int nx=0; int ny=0; int nz=0; int dir = 0; int v=0; int f=0; int i = 0; VoxelBlock block; VoxelFace face; VoxelVert vert;// VoxelFace nface; //Vector3 pos; System.Collections.Generic.List<VoxelFace> faces = new System.Collections.Generic.List<VoxelFace>(); #region Calculating top and bottom points int topPoint = land.data.GetTopPoint(offsetX, offsetZ, offsetX+size, offsetZ+size)+1; int bottomPoint = Mathf.Max(0, land.data.GetBottomPoint(offsetX, offsetZ, offsetX+size, offsetZ+size)-2); int shortHeight = topPoint - bottomPoint; //emergency exit if chunk contains no blocks if (topPoint<=1) { visibleFaces.Clear(); terrainProgress = Progress.calculated; return; } #endregion bool[] existMatrix = new bool[size*size*shortHeight]; land.data.GetExistMatrix (existMatrix, offsetX, bottomPoint, offsetZ, offsetX+size, topPoint, offsetZ+size); VoxelBlock[] blocks = new VoxelBlock[size*shortHeight*size]; #region Creating all faces //for (y=bottomPoint; y<topPoint; y++) for (y=0; y<shortHeight; y++) for (x=0; x<size; x++) for (z=0; z<size; z++) { i = z*shortHeight*size + y*size + x; //if exists //if (land.data.GetExist(x+offsetX,y,z+offsetZ)) if (existMatrix[z*size*shortHeight + y*size + x]) for (dir = 0; dir<6; dir++) { //if has face at this side if (x+VoxelFace.dirToPosX[dir] >= 0 && x+VoxelFace.dirToPosX[dir] < size && //cap sides here y+VoxelFace.dirToPosY[dir] >= 0 && y+VoxelFace.dirToPosY[dir] < shortHeight && z+VoxelFace.dirToPosZ[dir] >= 0 && z+VoxelFace.dirToPosZ[dir] < size && !existMatrix[ (z+VoxelFace.dirToPosZ[dir])*size*shortHeight + (y+VoxelFace.dirToPosY[dir])*size + x+VoxelFace.dirToPosX[dir] ]) { if (blocks[i]==null) { blocks[i] = new VoxelBlock(x,y+bottomPoint,z); if (x<land.overlap || x>=size-land.overlap || z<land.overlap || z>=size-land.overlap || y == 0) blocks[i].visible = false; else blocks[i].visible = true; byte typeNum = land.data.GetBlock(x+offsetX, y+bottomPoint, z+offsetZ); if (typeNum < land.types.Length) blocks[i].type = land.types[typeNum]; else blocks[i].type = land.types[0]; blocks[i].chunk = this; } face = new VoxelFace(); faces.Add(face); blocks[i].faces[dir] = face; face.block = blocks[i]; face.dir = (byte)dir; //setting face type, and adding it to used types array //face.type = (byte)land.data.GetBlock(x+offsetX, y+bottomPoint, z+offsetZ); //if (!usedTypes.Contains(face.type)) usedTypes.Add(face.type); face.visible = face.block.type.filled; //land.data.exist[face.block.type]; //land.types[face.block.type].visible; //setting coords for (v=0;v<9;v++) { //pos = VoxelVert.posTable[ dir*9 + v ] + new Vector3(x,y,z); //face.coords[v] = 1000000 + pos.x*20000 + pos.y*200 + pos.z*2; } } } } #endregion #region Welding internal, Welding neig int maxSize = size-1; int maxHeight = shortHeight-1; for (y=0; y<shortHeight; y++) for (x=0; x<size; x++) for (z=0; z<size; z++) { int stepz = shortHeight*size; i = z*stepz + y*size + x; if (blocks[i]!=null) for (dir = 0; dir<6; dir++) { block = blocks[i]; face = block.faces[dir]; if (face==null) continue; //weld this block switch (dir) { case 0: face.Weld( block, 5, 0,1,2, 2,1,0); face.Weld( block, 2, 2,3,4, 2,1,0); face.Weld( block, 4, 4,5,6, 2,1,0); face.Weld( block, 3, 6,7,0, 2,1,0); if (x>0) face.Weld( blocks[i-1], 0, 6,7,0, 4,3,2); if (z>0) face.Weld( blocks[i-stepz], 0, 4,5,6, 2,1,0); break; case 1: face.Weld( block, 5, 0,1,2, 6,5,4); face.Weld( block, 3, 2,3,4, 6,5,4); face.Weld( block, 4, 4,5,6, 6,5,4); face.Weld( block, 2, 6,7,0, 6,5,4); if (x>0) face.Weld( blocks[i-1], 1, 2,3,4, 0,7,6); if (z>0) face.Weld( blocks[i-stepz], 1, 4,5,6, 2,1,0); break; case 2: face.Weld( block, 0, 0,1,2, 4,3,2); face.Weld( block, 5, 2,3,4, 0,7,6); face.Weld( block, 1, 4,5,6, 0,7,6); face.Weld( block, 4, 6,7,0, 4,3,2); if (y>0) face.Weld( blocks[i-size], 2, 4,5,6, 2,1,0); if (z>0) face.Weld( blocks[i-stepz], 2, 6,7,0, 4,3,2); break; case 3: face.Weld( block, 0, 0,1,2, 0,7,6); face.Weld( block, 4, 2,3,4, 0,7,6); face.Weld( block, 1, 4,5,6, 4,3,2); face.Weld( block, 5, 6,7,0, 4,3,2); if (y>0) face.Weld( blocks[i-size], 3, 4,5,6, 2,1,0); if (z>0) face.Weld( blocks[i-stepz], 3, 2,3,4, 0,7,6); break; case 4: face.Weld( block, 0, 0,1,2, 6,5,4); face.Weld( block, 2, 2,3,4, 0,7,6); face.Weld( block, 1, 4,5,6, 6,5,4); face.Weld( block, 3, 6,7,0, 4,3,2); if (y>0) face.Weld( blocks[i-size], 4, 4,5,6, 2,1,0); if (x>0) face.Weld( blocks[i-1], 4, 6,7,0, 4,3,2); break; case 5: face.Weld( block, 0, 0,1,2, 2,1,0); face.Weld( block, 3, 2,3,4, 0,7,6); face.Weld( block, 1, 4,5,6, 2,1,0); face.Weld( block, 2, 6,7,0, 4,3,2); if (y>0) face.Weld( blocks[i-size], 5, 4,5,6, 2,1,0); if (x>0) face.Weld( blocks[i-1], 5, 2,3,4, 0,7,6); break; } } } #endregion #region Cross-welding for (y=0; y<shortHeight; y++) for (x=0; x<size; x++) for (z=0; z<size; z++) { int stepz = shortHeight*size; i = z*stepz + y*size + x; int j = i; if (blocks[i]!=null) for (dir = 0; dir<6; dir++) { face = blocks[i].faces[dir]; if (face==null) continue; //weld cross block if (dir==0 && y<maxHeight) { j = i+size; if (x>0) face.Weld( blocks[j-1], 2, 6,7,0, 6,5,4); //x-1,y+1,z if (z>0) face.Weld( blocks[j-stepz], 5, 4,5,6, 6,5,4); //x,y+1,z-1 if (x<maxSize) face.Weld( blocks[j+1], 3, 2,3,4, 6,5,4); //x+1,y+1,z if (z<maxSize) face.Weld( blocks[j+stepz], 4, 0,1,2, 6,5,4); //x,y+1,z+1 } else if (dir==1 && y>0) { j = i-size; if (x>0) face.Weld( blocks[j-1], 2, 2,3,4, 2,1,0); //x-1,y-1,z if (z>0) face.Weld( blocks[j-stepz], 5, 4,5,6, 2,1,0); //x,y-1,z-1 if (x<maxSize) face.Weld( blocks[j+1], 3, 6,7,0, 2,1,0); //x+1,y-1,z if (z<maxSize) face.Weld( blocks[j+stepz], 4, 0,1,2, 2,1,0); //x,y-1,z+1 } else if (dir==2 && x<maxSize) { j = i+1; if (y>0) face.Weld( blocks[j-size], 0, 4,5,6, 0,7,6); //x+1,y-1,z if (z>0) face.Weld( blocks[j-stepz], 5, 6,7,0, 4,3,2); //x+1,y,z-1 if (y<maxHeight) face.Weld( blocks[j+size], 1, 0,1,2, 4,3,2);//x+1,y+1,z if (z<maxSize) face.Weld( blocks[j+stepz], 4, 2,3,4, 0,7,6); //x+1,y,z+1 } else if (dir==3 && x>0) { j = i-1; if (y>0) face.Weld( blocks[j-size], 0, 4,5,6, 4,3,2); //x-1,y-1,z if (z>0) face.Weld( blocks[j-stepz], 5, 2,3,4, 0,7,6); //x-1,y,z-1 if (y<maxHeight) face.Weld( blocks[j+size], 1, 0,1,2, 0,7,6);//x-1,y+1,z if (z<maxSize) face.Weld( blocks[j+stepz], 4, 6,7,0, 4,3,2); //x-1,y,z+1 } else if (dir==4 && z>0) { j = i-stepz; if (y>0) face.Weld( blocks[j-size], 0, 4,5,6, 2,1,0); //x,y-1,z-1 if (x>0) face.Weld( blocks[j-1], 2, 6,7,0, 4,3,2); //x-1,y,z-1 if (y<maxHeight) face.Weld( blocks[j+size], 1, 0,1,2, 2,1,0);//x,y+1,z-1 if (x<maxSize) face.Weld( blocks[j+1], 3, 2,3,4, 0,7,6); //x+1,y,z-1 } else if (dir==5 && z<maxSize) { j = i+stepz; if (y>0) face.Weld( blocks[j-size], 0, 4,5,6, 6,5,4); //x,y-1,z+1 if (x>0) face.Weld( blocks[j-1], 2, 2,3,4, 0,7,6); //x-1,y,z+1 if (y<maxHeight) face.Weld( blocks[j+size], 1, 0,1,2, 6,5,4);//x,y+1,z+1 if (x<maxSize) face.Weld( blocks[j+1], 3, 6,7,0, 4,3,2); //x+1,y,z+1 } for (v=0;v<9;v++) { vert = face.verts[v]; //setting new vert if (vert==null) { vert = new VoxelVert(); face.verts[v] = vert; } vert.pos = VoxelVert.posTable[ dir*9 + v ] + new Vector3(x,y,z); vert.AddFace(face); } //face.LinkVerts(); } } #endregion #region Linking (adding verts neigs) for (f=0;f<faces.Count;f++) faces[f].LinkVerts(); #endregion #region Lifting on BottomPoint for (f=0;f<faces.Count;f++) { face = faces[f]; for (v=0;v<9;v++) if (!face.verts[v].processed) { face.verts[v].pos += new Vector3(0,bottomPoint,0); face.verts[v].processed = true; } } for (f=0;f<faces.Count;f++) //clearing for (v=0;v<9;v++) faces[f].verts[v].processed = false; #endregion #region Relaxing //setting vert relax for (f=0;f<faces.Count;f++) { for (v=0;v<9;v++) { faces[f].verts[v].relax += faces[f].block.type.smooth; faces[f].verts[v].relaxCount += 1; } } for (f=0;f<faces.Count;f++) for (v=0;v<9;v++) if (faces[f].verts[v].relaxCount != 0) { faces[f].verts[v].relax = faces[f].verts[v].relax / faces[f].verts[v].relaxCount; faces[f].verts[v].relaxCount = 0; } //averaging corners for (f=0;f<faces.Count;f++) { face = faces[f]; if (!face.verts[0].processed) { face.verts[0].pos += face.verts[0].GetRelax()*2; face.verts[0].processed=true; } if (!face.verts[2].processed) { face.verts[2].pos += face.verts[2].GetRelax()*2; face.verts[2].processed=true; } if (!face.verts[4].processed) { face.verts[4].pos += face.verts[4].GetRelax()*2; face.verts[4].processed=true; } if (!face.verts[6].processed) { face.verts[6].pos += face.verts[6].GetRelax()*2; face.verts[6].processed=true; } } //averaging mid verts for (f=0;f<faces.Count;f++) { face = faces[f]; face.verts[1].pos = (face.verts[0].pos + face.verts[2].pos) * 0.5f; face.verts[3].pos = (face.verts[2].pos + face.verts[4].pos) * 0.5f; face.verts[5].pos = (face.verts[4].pos + face.verts[6].pos) * 0.5f; face.verts[7].pos = (face.verts[6].pos + face.verts[0].pos) * 0.5f; face.verts[8].pos = (face.verts[0].pos + face.verts[2].pos + face.verts[4].pos + face.verts[6].pos) * 0.25f; //returning processed flags face.verts[0].processed = false; face.verts[2].processed = false; face.verts[4].processed = false; face.verts[6].processed = false; } //seconary relax for (f=0;f<faces.Count;f++) { face = faces[f]; for (v=0;v<9;v++) if (!face.verts[v].processed) { face.verts[v].relaxed = face.verts[v].GetRelax(); face.verts[v].processed = true; } } for (f=0;f<faces.Count;f++) for (v=0;v<9;v++) faces[f].verts[v].processed = false; for (f=0;f<faces.Count;f++) { face = faces[f]; for (v=0;v<9;v++) if (!face.verts[v].processed) { face.verts[v].pos += face.verts[v].relaxed; face.verts[v].processed = true; } } #endregion #region Setting normals for (f=0;f<faces.Count;f++) { face = faces[f]; face.verts[0].normal += Vector3.Cross(face.verts[1].pos-face.verts[0].pos, face.verts[7].pos-face.verts[0].pos).normalized; face.verts[2].normal += Vector3.Cross(face.verts[3].pos-face.verts[2].pos, face.verts[1].pos-face.verts[2].pos).normalized; face.verts[4].normal += Vector3.Cross(face.verts[5].pos-face.verts[4].pos, face.verts[3].pos-face.verts[4].pos).normalized; face.verts[6].normal += Vector3.Cross(face.verts[7].pos-face.verts[6].pos, face.verts[5].pos-face.verts[6].pos).normalized; face.verts[1].normal += Vector3.Cross(face.verts[8].pos-face.verts[1].pos, face.verts[0].pos-face.verts[1].pos).normalized + Vector3.Cross(face.verts[2].pos-face.verts[1].pos, face.verts[8].pos-face.verts[1].pos).normalized; face.verts[3].normal += Vector3.Cross(face.verts[8].pos-face.verts[3].pos, face.verts[2].pos-face.verts[3].pos).normalized + Vector3.Cross(face.verts[4].pos-face.verts[3].pos, face.verts[8].pos-face.verts[3].pos).normalized; face.verts[5].normal += Vector3.Cross(face.verts[8].pos-face.verts[5].pos, face.verts[4].pos-face.verts[5].pos).normalized + Vector3.Cross(face.verts[6].pos-face.verts[5].pos, face.verts[8].pos-face.verts[5].pos).normalized; face.verts[7].normal += Vector3.Cross(face.verts[8].pos-face.verts[7].pos, face.verts[6].pos-face.verts[7].pos).normalized + Vector3.Cross(face.verts[0].pos-face.verts[7].pos, face.verts[8].pos-face.verts[7].pos).normalized; face.verts[8].normal = Vector3.Cross(face.verts[1].pos-face.verts[5].pos, face.verts[3].pos-face.verts[7].pos).normalized; } if (land.normalsRandom > 0.01f) { for (x=0; x<size; x++) for (z=0; z<size; z++) for (y=0; y<shortHeight; y++) { i = z*shortHeight*size + y*size + x; if (blocks[i]==null) continue; if (!blocks[i].visible) continue; Vector3 normalRandom = new Vector3(Random.value-0.5f, Random.value-0.5f, Random.value-0.5f)*1; for (f=0;f<6;f++) if (blocks[i].faces[f]!=null && blocks[i].faces[f].visible) for (v=0;v<9;v++) blocks[i].faces[f].verts[v].normal += normalRandom; } } #endregion #region Set visible faces //visibleFaces.Clear(); visibleFaces = new System.Collections.Generic.List<VoxelFace>(); for (x=0; x<size; x++) for (z=0; z<size; z++) for (y=0; y<shortHeight; y++) { i = z*shortHeight*size + y*size + x; if (blocks[i]==null) continue; if (!blocks[i].visible) continue; for (f=0;f<6;f++) if (blocks[i].faces[f]!=null && blocks[i].faces[f].visible) visibleFaces.Add(blocks[i].faces[f]); } #endregion #region Set collider hierarchy boundsMin = new Vector2(offsetX + land.overlap, offsetZ + land.overlap); boundsMax = new Vector2(offsetX - land.overlap*2 + size, offsetZ - land.overlap*2 + size); boundsCenter = (boundsMin+boundsMax) / 2f; faceHolders = new FaceHolder[16]; int facesPerHolder = Mathf.CeilToInt((size-land.overlap*2) / 4f); for (x=0; x<4; x++) for (z=0; z<4; z++) { faceHolders[z*4+x] = new FaceHolder(); faceHolders[z*4+x].faces = new List<VoxelFace>(); faceHolders[z*4+x].min = new Vector2(boundsMin.x + facesPerHolder*x, boundsMin.y + facesPerHolder*z); faceHolders[z*4+x].center = faceHolders[z*4+x].min + new Vector2(facesPerHolder/2f, facesPerHolder/2f); if (x==3) faceHolders[z*4+x].max = new Vector2(boundsMax.x, boundsMin.y + facesPerHolder*(z+1)); else if (z==3) if (x==3) faceHolders[z*4+x].max = new Vector2(boundsMin.x + facesPerHolder*(x+1), boundsMax.y); else faceHolders[z*4+x].max = new Vector2(boundsMin.x + facesPerHolder*(x+1), boundsMin.y + facesPerHolder*(z+1)); } for (f=0; f<visibleFaces.Count; f++) { face = visibleFaces[f]; x = face.block.x / facesPerHolder; z = face.block.z / facesPerHolder; faceHolders[z*4+x].faces.Add(face); } #endregion terrainProgress = Progress.calculated; }
static void Quad(Vector3 topLeft, Vector3 topRight, Vector3 bottomRight,Vector3 bottomLeft,float voxelSize,VoxelFace voxel, bool backFace,float selfShadeIntensity,List<Vector3> vertices, List<int> indexes, List<Color32> colors, List<Vector2> uvs) { int index = vertices.Count; vertices.Add(bottomLeft * voxelSize); vertices.Add(bottomRight * voxelSize); vertices.Add(topLeft * voxelSize); vertices.Add(topRight * voxelSize); Color temp = IntToColor(voxel.Color); int test1 = (((voxel.VertShade & Corners.TopRight) == Corners.TopRight) ? 1 : 0) + (((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft) ? 1 : 0) + (((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft) ? 1 : 0) + (((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight) ? 1 : 0); int test2 = (((voxel.VertShade & Corners.TopRight) == Corners.TopRight) ? 1 : 0) + (((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft) ? 1 : 0); int test3 = (((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft) ? 1 : 0) + (((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight) ? 1 : 0); if (((test2 > test3) && (test1>2)) || ((test2<=test3) && (test1==1))) { colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft ? (1f - selfShadeIntensity) : 1f), temp.a)); colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft ? (1f - selfShadeIntensity) : 1f), temp.a)); colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.TopRight) == Corners.TopRight ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.TopRight) == Corners.TopRight ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.TopRight) == Corners.TopRight ? (1f - selfShadeIntensity) : 1f), temp.a)); colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight ? (1f - selfShadeIntensity) : 1f), temp.a)); if (backFace) { indexes.Add(index + 2); indexes.Add(index); indexes.Add(index + 1); indexes.Add(index + 1); indexes.Add(index + 3); indexes.Add(index + 2); } else { indexes.Add(index + 2); indexes.Add(index + 3); indexes.Add(index + 1); indexes.Add(index + 1); indexes.Add(index); indexes.Add(index + 2); } } else { colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.TopLeft) == Corners.TopLeft ? (1f - selfShadeIntensity) : 1f), temp.a)); colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.BottomLeft) == Corners.BottomLeft ? (1f - selfShadeIntensity) : 1f), temp.a)); colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.TopRight) == Corners.TopRight ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.TopRight) == Corners.TopRight ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.TopRight) == Corners.TopRight ? (1f - selfShadeIntensity) : 1f), temp.a)); colors.Add(new Color(temp.r * ((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight ? (1f - selfShadeIntensity) : 1f), temp.g * ((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight ? (1f - selfShadeIntensity) : 1f), temp.b * ((voxel.VertShade & Corners.BottomRight) == Corners.BottomRight ? (1f - selfShadeIntensity) : 1f), temp.a)); if (backFace) { indexes.Add(index + 3); indexes.Add(index + 2); indexes.Add(index); indexes.Add(index); indexes.Add(index + 1); indexes.Add(index + 3); } else { indexes.Add(index + 3); indexes.Add(index + 1); indexes.Add(index); indexes.Add(index); indexes.Add(index + 2); indexes.Add(index + 3); } } uvs.Add(new Vector2(1f, 1f)); uvs.Add(new Vector2(0f, 1f)); uvs.Add(new Vector2(0f, 0f)); uvs.Add(new Vector2(1f, 0f)); }