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); }
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)); }
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 UpdateVoxel() { bool inEditor = InEditor(); Material coloredHighlightMaterial = null; if (substance != null && substance.highlight != Color.clear) { coloredHighlightMaterial = substance.highlightMaterial; } bool xRay = false; if (substance != null && inEditor) { xRay = substance.xRay; } if (xRay) { gameObject.layer = 8; // XRay layer } else { gameObject.layer = 0; // default } int numFilledFaces = 0; foreach (VoxelFace f in faces) { if (!f.IsEmpty()) { numFilledFaces++; } } var vertices = new Vector3[numFilledFaces * 4]; var uvs = new Vector2[numFilledFaces * 4]; var normals = new Vector3[numFilledFaces * 4]; var tangents = new Vector4[numFilledFaces * 4]; float[] vertexPos = new float[3]; // reusable numFilledFaces = 0; int numMaterials = 0; for (int faceNum = 0; faceNum < 6; faceNum++) { VoxelFace face = faces[faceNum]; if (face.IsEmpty()) { continue; } int axis = FaceIAxis(faceNum); Vector3 normal = DirectionForFaceI(faceNum); int rotation = VoxelFace.GetOrientationRotation(face.orientation); bool mirrored = VoxelFace.GetOrientationMirror(face.orientation); // ST space is always upright Vector3 positiveS_xyz = POSITIVE_S_XYZ[faceNum]; // positive S in XYZ space Vector3 positiveT_xyz = POSITIVE_T_XYZ[faceNum]; int uRot = rotation; if (mirrored) { uRot += 3; } int vRot; if (!mirrored) { vRot = uRot + 3; } else { vRot = uRot + 1; } Vector2 positiveU_st = POSITIVE_U_ST[uRot % 4]; Vector2 positiveV_st = POSITIVE_U_ST[vRot % 4]; Vector3 positiveU_xyz = positiveS_xyz * positiveU_st.x + positiveT_xyz * positiveU_st.y; Vector3 positiveV_xyz = positiveS_xyz * positiveV_st.x + positiveT_xyz * positiveV_st.y; Vector4 tangent = new Vector4(positiveU_xyz.x, positiveU_xyz.y, positiveU_xyz.z, mirrored ? 1 : -1); // example for faceNum = 5 (z min) // 0 bottom left // 1 bottom right // 2 top right // 3 top left for (int i = 0; i < 4; i++) { int vertexI = numFilledFaces * 4 + i; vertexPos[axis] = faceNum % 2; vertexPos[(axis + 1) % 3] = SQUARE_LOOP[i].x; vertexPos[(axis + 2) % 3] = SQUARE_LOOP[i].y; Vector3 vertex = new Vector3(vertexPos[0], vertexPos[1], vertexPos[2]); vertices[vertexI] = vertex; normals[vertexI] = normal; tangents[vertexI] = tangent; vertex += transform.position; Vector2 uv = new Vector2( vertex.x * positiveU_xyz.x + vertex.y * positiveU_xyz.y + vertex.z * positiveU_xyz.z, vertex.x * positiveV_xyz.x + vertex.y * positiveV_xyz.y + vertex.z * positiveV_xyz.z); uvs[vertexI] = uv; } numFilledFaces++; if (xRay) { numMaterials++; } else { if (face.material != null) { numMaterials++; } if (face.overlay != null) { numMaterials++; } } if (coloredHighlightMaterial != null) { numMaterials++; } if (face.addSelected || face.storedSelected) { numMaterials++; } } Mesh mesh = GetComponent <MeshFilter>().mesh; mesh.name = "Voxel Mesh"; mesh.Clear(); mesh.vertices = vertices; mesh.uv = uvs; mesh.normals = normals; mesh.tangents = tangents; mesh.subMeshCount = numMaterials; Material[] materials = new Material[numMaterials]; numFilledFaces = 0; numMaterials = 0; for (int faceI = 0; faceI < 6; faceI++) { VoxelFace face = faces[faceI]; if (face.IsEmpty()) { continue; } var triangles = new int[6]; if (faceI % 2 == 1) { triangles[0] = numFilledFaces * 4 + 0; triangles[1] = numFilledFaces * 4 + 1; triangles[2] = numFilledFaces * 4 + 2; triangles[3] = numFilledFaces * 4 + 0; triangles[4] = numFilledFaces * 4 + 2; triangles[5] = numFilledFaces * 4 + 3; } else { triangles[0] = numFilledFaces * 4 + 0; triangles[1] = numFilledFaces * 4 + 2; triangles[2] = numFilledFaces * 4 + 1; triangles[3] = numFilledFaces * 4 + 0; triangles[4] = numFilledFaces * 4 + 3; triangles[5] = numFilledFaces * 4 + 2; } if (xRay) { materials[numMaterials] = xRayMaterial; mesh.SetTriangles(triangles, numMaterials); numMaterials++; } else { if (face.material != null) { materials[numMaterials] = face.material; mesh.SetTriangles(triangles, numMaterials); numMaterials++; } if (face.overlay != null) { materials[numMaterials] = face.overlay; mesh.SetTriangles(triangles, numMaterials); numMaterials++; } } if (coloredHighlightMaterial != null) { materials[numMaterials] = coloredHighlightMaterial; mesh.SetTriangles(triangles, numMaterials); numMaterials++; } if (face.addSelected || face.storedSelected) { materials[numMaterials] = selectedMaterial; mesh.SetTriangles(triangles, numMaterials); numMaterials++; } numFilledFaces++; } Renderer renderer = GetComponent <Renderer>(); renderer.materials = materials; MeshCollider meshCollider = GetComponent <MeshCollider>(); BoxCollider boxCollider = GetComponent <BoxCollider>(); if (inEditor) { renderer.enabled = true; meshCollider.enabled = true; // force the collider to update. It otherwise might not since we're using the same mesh object // this fixes a bug where rays would pass through a voxel that used to be empty meshCollider.sharedMesh = null; meshCollider.sharedMesh = mesh; boxCollider.enabled = false; } else { boxCollider.enabled = true; if (substance == null && !IsEmpty()) // a wall { renderer.enabled = true; boxCollider.isTrigger = false; } else if (substance != null) { renderer.enabled = false; boxCollider.isTrigger = true; } else // probably an object { renderer.enabled = false; boxCollider.enabled = false; } meshCollider.sharedMesh = null; meshCollider.enabled = false; } } // end UpdateVoxel()