//public enum EditMode {none, standard, dig, add, replace, smooth}; //standard mode is similar to add one, except the preliminary switch to opposite in add public CoordDir Min(CoordDir pos, Voxeland.EditMode mode = Voxeland.EditMode.none) { switch (form) { //case Form.single: if (mode==Voxeland.EditMode.add) pos = pos.opposite; break; //shifting pos to opposite if single add mode //in Alter case Form.blob: pos.x -= extent + 1; pos.y -= extent + 1; pos.z -= extent + 1; break; //getting 1-block boundary for opposites case Form.volume: pos.x -= extent; pos.y -= extent; pos.z -= extent; break; case Form.stamp: if (stamp == null) { return(pos); } if (getStamp) { pos += getStampMin; } else { pos += stamp.cube.offset; } break; } return(pos); }
public void BlurExistMatrix(Matrix3 <float> src, int iterations = 10) //src is an exist (bool) array, 0 is empty, 1 is exists { Matrix3 <float> dst = src.Copy(); //to fill matrix borders CoordDir start = src.cube.offset + 1; //new CoordDir(src.offsetX+1, src.offsetY+1, src.offsetZ+1); CoordDir end = src.cube.offset + src.cube.size - 1; for (int i = 0; i < iterations; i++) { for (int x = start.x; x < end.x; x++) { for (int y = start.y; y < end.y; y++) { for (int z = start.z; z < end.z; z++) { float val = src[x, y, z] * 4; val += src[x + 1, y, z]; val += src[x - 1, y, z]; val += src[x, y + 1, z]; val += src[x, y - 1, z]; val += src[x, y, z + 1]; val += src[x, y, z - 1]; dst[x, y, z] = val / 10; } } } for (int a = 0; a < src.array.Length; a++) { src.array[a] = dst.array[a]; //copy dst to src for new iteration } } }
public CoordDir Max(CoordDir pos, Voxeland.EditMode mode = Voxeland.EditMode.none) //note taht Max is never reached { switch (form) { //case Form.single: if (mode==Voxeland.EditMode.add) pos = pos.opposite; break; //shifting pos to opposite if single add mode case Form.blob: pos.x += extent + 1; pos.y += extent + 1; pos.z += extent + 1; break; //getting 1-block boundary on opposite case Form.volume: pos.x += extent; pos.y += extent; pos.z += extent; break; case Form.stamp: if (stamp == null) { return(pos + 1); } if (getStamp) { pos += getStampMax; } else { pos += stamp.cube.offset + stamp.cube.size; } break; } pos.x++; pos.y++; pos.z++; return(pos); }
public CoordDir GetChunkCoord(CoordDir worldCoord, int chunkSize) //gets chunk CoordDirinates using wholeterrain unit CoordDir { return(new CoordDir ( worldCoord.x >= 0 ? (int)(worldCoord.x / chunkSize) : (int)((worldCoord.x + 1) / chunkSize) - 1, 0, worldCoord.z >= 0 ? (int)(worldCoord.z / chunkSize) : (int)((worldCoord.z + 1) / chunkSize) - 1 )); }
public int GetTriIndexByCoord(CoordDir coord) { if (colliderIndexToCoord == null) { throw new System.NullReferenceException("No colliderIndexToCoord defined"); } for (int i = 0; i < colliderIndexToCoord.Length; i++) { if (colliderIndexToCoord[i].x == coord.x && colliderIndexToCoord[i].y == coord.y && colliderIndexToCoord[i].z == coord.z && colliderIndexToCoord[i].dir == coord.dir) //4 times faster than //if (chunk.colliderIndexToCoord[i] == center) { return(i); } } //throw new System.ArgumentOutOfRangeException("Could not find face index with coord: " + coord); //happens right after blob brush edit return(-1); }
public Matrix3(CoordDir offset, CoordDir size, T[] array = null) { cube = new CoordCube(offset, size); count = cube.size.x * cube.size.y * cube.size.z; if (array != null && array.Length < count) { Debug.LogError("Array length: " + array.Length + " is lower then matrix capacity: " + count); } if (array != null && array.Length >= count) { this.array = array; } else { this.array = new T[count]; } }
public int GetPos(CoordDir c) { #if WDEBUG if (c.x < offset.x || c.x >= offset.x + size.x) { throw new System.ArgumentOutOfRangeException("x", "Index Out Of Range (" + offset.x + "-" + (offset.x + size.x) + "): " + c.x); } if (c.y < offset.y || c.y >= offset.y + size.y) { throw new System.ArgumentOutOfRangeException("y", "Index Out Of Range (" + offset.y + "-" + (offset.y + size.y) + "): " + c.y); } if (c.z < offset.z || c.z >= offset.z + size.z) { throw new System.ArgumentOutOfRangeException("z", "Index Out Of Range (" + offset.z + "-" + (offset.z + size.z) + "): " + c.z); } #endif return((c.z - offset.z) * size.x * size.y + (c.y - offset.y) * size.x + c.x - offset.x); }
public Transform GetObjectByCoord(CoordDir coord) { Coord chunkCoord = this.rect.offset; int childCount = transform.childCount; for (int i = 0; i < childCount; i++) { Transform tfm = transform.GetChild(i); if (Mathf.FloorToInt(tfm.localPosition.x + chunkCoord.x) == coord.x && (int)tfm.localPosition.y == coord.y && Mathf.FloorToInt(tfm.localPosition.z + chunkCoord.z) == coord.z) { if (tfm.name == "Grass") { continue; //ignoring grass objs } return(tfm); } } return(null); }
public static CoordDir Min(CoordDir[] coords) { CoordDir min = new CoordDir(int.MaxValue, int.MaxValue, int.MaxValue, 7); for (int i = 0; i < coords.Length; i++) { if (coords[i].x < min.x) { min.x = coords[i].x; } if (coords[i].y < min.y) { min.y = coords[i].y; } if (coords[i].z < min.z) { min.z = coords[i].z; } } return(min); }
public static CoordDir Max(CoordDir[] coords) { CoordDir max = new CoordDir(int.MinValue, int.MinValue, int.MinValue, 7); for (int i = 0; i < coords.Length; i++) { if (coords[i].x > max.x) { max.x = coords[i].x; } if (coords[i].y > max.y) { max.y = coords[i].y; } if (coords[i].z > max.z) { max.z = coords[i].z; } } return(max); }
public T this[CoordDir c] { get { #if WDEBUG if (c.x < cube.offset.x || c.x >= cube.offset.x + cube.size.x) { throw new System.ArgumentOutOfRangeException("c", "Index Out Of Range (" + cube.offset.x + "-" + cube.offset.x + cube.size.x + "): " + c.x); } if (c.y < cube.offset.y || c.y >= cube.offset.y + cube.size.y) { throw new System.ArgumentOutOfRangeException("c", "Index Out Of Range (" + cube.offset.y + "-" + cube.offset.y + cube.size.y + "): " + c.y); } if (c.z < cube.offset.z || c.z >= cube.offset.z + cube.size.z) { throw new System.ArgumentOutOfRangeException("c", "Index Out Of Range (" + cube.offset.z + "-" + cube.offset.z + cube.size.z + "): " + c.z); } #endif return(array[(c.z - cube.offset.z) * cube.size.x * cube.size.y + (c.y - cube.offset.y) * cube.size.x + c.x - cube.offset.x]); } set { #if WDEBUG if (c.x < cube.offset.x || c.x >= cube.offset.x + cube.size.x) { throw new System.ArgumentOutOfRangeException("x", "Index Out Of Range (" + cube.offset.x + "-" + cube.offset.x + cube.size.x + "): " + c.x); } if (c.y < cube.offset.y || c.y >= cube.offset.y + cube.size.y) { throw new System.ArgumentOutOfRangeException("y", "Index Out Of Range (" + cube.offset.y + "-" + cube.offset.y + cube.size.y + "): " + c.y); } if (c.z < cube.offset.z || c.z >= cube.offset.z + cube.size.z) { throw new System.ArgumentOutOfRangeException("z", "Index Out Of Range (" + cube.offset.z + "-" + cube.offset.z + cube.size.z + "): " + c.z); } #endif array[(c.z - cube.offset.z) * cube.size.x * cube.size.y + (c.y - cube.offset.y) * cube.size.x + c.x - cube.offset.x] = value; } }
public void AddVoxelandFace(CoordDir coord, Chunk chunk, float opacity = 1) { //getting chunk if (chunk == null) { return; } Mesh chunkMesh = chunk.hiMesh; if (chunkMesh == null || chunkMesh.vertexCount == 0) { return; //empty mesh check } //finding index int index = chunk.GetTriIndexByCoord(coord); //adding 4 hi-faces to highlight if (index >= 0) { AddVoxelandFace(chunkMesh, index, chunk.transform, opacity); } }
public void OnSceneGUI () { //updating Inspector GUI if thread is working (it lags less if done from OnSceneGUI... somehow) if (ThreadWorker.IsWorking("Voxeland") || gaugeDisplayed) Repaint(); Voxeland voxeland = (Voxeland)target; if (voxeland.data == null) return; //disabling selection if (voxeland.guiLockSelection) { HandleUtility.AddDefaultControl( GUIUtility.GetControlID(FocusType.Passive) ); Tools.current = Tool.None; } //hiding wireframe //voxeland.transform.ToggleDisplayWireframe(!voxeland.guiHideWireframe); //switching highlight intensity mode if (voxeland.highlight != null && voxeland.highlight.material != null && voxeland.highlight.meshRenderer.sharedMaterial != null && voxeland.highlight.meshRenderer.sharedMaterial.HasProperty("_Linear")) voxeland.highlight.meshRenderer.sharedMaterial.SetInt("_Linear", PlayerSettings.colorSpace==ColorSpace.Linear? 1 : 0); //getting mouse button if (Event.current.type == EventType.MouseDown) mouseButton = Event.current.button; if (Event.current.rawType == EventType.MouseUp) mouseButton = -1; //getting mouse pos SceneView sceneview = UnityEditor.SceneView.lastActiveSceneView; if (sceneview==null || sceneview.camera==null) return; Vector2 mousePos = Event.current.mousePosition; mousePos = new Vector2(mousePos.x/sceneview.camera.pixelWidth, mousePos.y/sceneview.camera.pixelHeight); #if UNITY_5_4_OR_NEWER mousePos *= EditorGUIUtility.pixelsPerPoint; #endif mousePos.y = 1 - mousePos.y; //aiming Ray aimRay = sceneview.camera.ViewportPointToRay(mousePos); CoordDir aimCoord = voxeland.PointOut(aimRay); //focusing on brush if(Event.current.commandName == "FrameSelected") { Event.current.Use(); if (aimCoord.exists) UnityEditor.SceneView.lastActiveSceneView.LookAt( voxeland.transform.TransformPoint( aimCoord.vector3 ), UnityEditor.SceneView.lastActiveSceneView.rotation, Mathf.Max(voxeland.brush.extent*6, 20), UnityEditor.SceneView.lastActiveSceneView.orthographic, false); else { Coord rectCenter = voxeland.chunks.deployedRects[0].Center * voxeland.chunkSize; int rectExtend = voxeland.chunks.deployedRects[0].size.x * voxeland.chunkSize; int height; byte temp; voxeland.data.GetTopTypePoint(rectCenter.x, rectCenter.z, out height, out temp); UnityEditor.SceneView.lastActiveSceneView.LookAt( voxeland.transform.TransformPoint( new Vector3(rectCenter.x, height, rectCenter.z) ), UnityEditor.SceneView.lastActiveSceneView.rotation, rectExtend, UnityEditor.SceneView.lastActiveSceneView.orthographic, false); } } //if any change if (prevAimCoord != aimCoord || mouseButton==0) { //getting edit mode Voxeland.EditMode editMode = Voxeland.EditMode.none; bool buttonDown = false; if (!voxeland.continuousPainting) buttonDown = Event.current.type==EventType.MouseDown && Event.current.button==0; else buttonDown = mouseButton==0; if (buttonDown && !Event.current.alt) { if (Event.current.control && Event.current.shift) editMode = voxeland.controlShiftEditMode; else if (Event.current.shift) editMode = voxeland.shiftEditMode; else if (Event.current.control) editMode = voxeland.controlEditMode; else editMode = voxeland.standardEditMode; } //highlight if (voxeland.highlight!=null) // && Event.current.type!=EventType.KeyDown && Event.current.type!=EventType.mouseDrag) //do not redraw highlight on alt pressed { if (aimCoord.exists) voxeland.Highlight(aimCoord, voxeland.brush, isEditing:editMode!=Voxeland.EditMode.none); else voxeland.highlight.Clear(); //clearing highlight if nothing aimed or voxeland not selected } //altering if (editMode!=Voxeland.EditMode.none && aimCoord.exists) { voxeland.Alter(aimCoord, voxeland.brush, editMode, landType:voxeland.landTypes.selected, objectType:voxeland.objectsTypes.selected, grassType:voxeland.grassTypes.selected); } prevAimCoord = aimCoord; SceneView.lastActiveSceneView.Repaint(); } //if coord or button change }
public CoordCube(int offsetX, int offsetY, int offsetZ, int sizeX, int sizeY, int sizeZ) { this.offset = new CoordDir(offsetX, offsetY, offsetZ, 7); this.size = new CoordDir(sizeX, sizeY, sizeZ, 7); }
public CoordCube(CoordDir offset, CoordDir size) { this.offset = offset; this.size = size; }
public void Process(CoordDir pos, Matrix3 <byte> matrix, Voxeland.EditMode mode, Form formOverride, byte type) //overriding brush form to place objects and grass { //blurring matrix in case of blur mode Matrix3 <float> blurredExist = null; if (mode == Voxeland.EditMode.smooth) { blurredExist = new Matrix3 <float>(matrix.cube); for (int i = 0; i < blurredExist.array.Length; i++) { if (matrix.array[i] != Data.emptyByte) { blurredExist.array[i] = 1; } else { blurredExist.array[i] = 0; } } BlurExistMatrix(blurredExist); } //single brush if (formOverride == Form.single) { switch (mode) { case Voxeland.EditMode.add: case Voxeland.EditMode.replace: matrix[pos.x, pos.y, pos.z] = type; break; //already switched add to opposite, so add==replace case Voxeland.EditMode.dig: matrix[pos.x, pos.y, pos.z] = Data.emptyByte; break; } } //blob brush if (formOverride == Form.blob) { CoordDir[] neigCoords = ChunkMesh.NeighbourCoordinates(pos, matrix, extent, round: round); for (int i = 0; i < neigCoords.Length; i++) { int x = neigCoords[i].x; int y = neigCoords[i].y; int z = neigCoords[i].z; CoordDir neigOpposite = neigCoords[i].opposite; int ox = neigOpposite.x; int oy = neigOpposite.y; int oz = neigOpposite.z; switch (mode) { case Voxeland.EditMode.add: matrix[ox, oy, oz] = type; break; case Voxeland.EditMode.replace: matrix[x, y, z] = type; break; case Voxeland.EditMode.dig: matrix[x, y, z] = Data.emptyByte; break; case Voxeland.EditMode.smooth: if (blurredExist[ox, oy, oz] > 0.5f && matrix[ox, oy, oz] == Data.emptyByte) { matrix[ox, oy, oz] = ClosestExistingType(matrix, ox, oy, oz); //TODO: exist check } if (blurredExist[x, y, z] < 0.5f && matrix[x, y, z] != Data.emptyByte) { matrix[x, y, z] = Data.emptyByte; } break; } } } //volume brush else if (formOverride == Form.volume) { CoordDir min = matrix.cube.Min; CoordDir max = matrix.cube.Max; for (int x = min.x; x < max.x; x++) { for (int y = min.y; y < max.y; y++) { for (int z = min.z; z < max.z; z++) { //ignoring out-of-sphere if (round) { int dx = x - pos.x; int dy = y - pos.y; int dz = z - pos.z; if (dx * dx + dy * dy + dz * dz > (extent + 0.5f) * (extent + 0.5f)) { continue; } } //setting block int i = matrix.cube.GetPos(x, y, z); switch (mode) { case Voxeland.EditMode.add: matrix.array[i] = type; break; case Voxeland.EditMode.dig: matrix.array[i] = Data.emptyByte; break; case Voxeland.EditMode.replace: if (matrix.array[i] != Data.emptyByte) { matrix.array[i] = type; } break; //TODO: exists check case Voxeland.EditMode.smooth: if (blurredExist.array[i] > 0.5f && (matrix.array[i] == Data.emptyByte || matrix.array[i] >= Data.constructorByte)) { matrix.array[i] = ClosestExistingType(matrix, x, y, z); //if blured exists but matrix empty adding closest //TODO: exist check } if (blurredExist.array[i] < 0.5f && (matrix.array[i] != Data.emptyByte && matrix.array[i] < Data.constructorByte)) { matrix.array[i] = Data.emptyByte; //if blured empty but matrix exists } break; } } } } } else if (formOverride == Form.stamp) { if (getStamp) { stamp = new Matrix3 <bool>(getStampMin, matrix.cube.size); for (int x = 0; x < matrix.cube.size.x; x++) { for (int y = 0; y < matrix.cube.size.y; y++) { for (int z = 0; z < matrix.cube.size.z; z++) { if (matrix[x + matrix.cube.offset.x, y + matrix.cube.offset.y, z + matrix.cube.offset.z] != Data.emptyByte) { stamp[x + stamp.cube.offset.x, y + stamp.cube.offset.y, z + stamp.cube.offset.z] = true; //TODO: exists check } } } } } else if (stamp != null) { for (int x = 0; x < stamp.cube.size.x; x++) { for (int y = 0; y < stamp.cube.size.y; y++) { for (int z = 0; z < stamp.cube.size.z; z++) { CoordDir s = new CoordDir(x, y, z) + stamp.cube.offset; CoordDir m = new CoordDir(x, y, z) + matrix.cube.offset; switch (mode) { case Voxeland.EditMode.add: if (stamp[s]) { matrix[m] = type; } break; case Voxeland.EditMode.dig: if (stamp[s]) { matrix[m] = Data.emptyByte; } break; case Voxeland.EditMode.replace: if (matrix[m] != 0 && stamp[s]) { matrix[m] = type; } break; //TODO: exists check case Voxeland.EditMode.smooth: if (stamp[s]) { if (blurredExist[m] > 0.5f && (matrix[m] == Data.emptyByte || matrix[m] >= Data.constructorByte)) { matrix[m] = ClosestExistingType(matrix, x, y, z); //if blured exists but matrix empty adding closest //TODO: exist check } if (blurredExist[m] < 0.5f && (matrix[m] != Data.emptyByte && matrix[m] < Data.constructorByte)) { matrix[m] = Data.emptyByte; //if blured empty but matrix exists } } break; } } } } } } }
public void Process(CoordDir pos, Matrix3 <byte> matrix, Voxeland.EditMode mode, byte type) { Process(pos, matrix, mode, form, type); }
public int this[CoordDir c] { get { return((c.z - offset.z) * size.x * size.y + (c.y - offset.y) * size.x + c.x - offset.x); } }
public bool Contains(CoordDir c) { return(c.x >= offset.x && c.x < offset.x + size.x && c.y >= offset.y && c.y < offset.y + size.y && c.z >= offset.z && c.z < offset.z + size.z); }
public CoordDir(CoordDir c, byte d) { this.x = c.x; this.y = c.y; this.z = c.z; this.dir = d; }