public void AddFace(IEnumerable <Face> faces, FaceMask mask) { this.WritePadding(); this.streamWriter.Write("f"); foreach (Face face in faces) { this.streamWriter.Write(" "); this.streamWriter.Write(face.Vertex.ToString(en_US)); bool tex = ((mask & FaceMask.Tex) == FaceMask.Tex); bool nor = ((mask & FaceMask.Normal) == FaceMask.Normal); if (tex || nor) { this.streamWriter.Write("/"); if (tex) { this.streamWriter.Write(face.Tex.ToString(en_US)); } if (nor) { this.streamWriter.Write("/"); this.streamWriter.Write(face.Normal.ToString(en_US)); } } } this.streamWriter.WriteLine(); }
/// <summary>Uses the given enabled faces to use <see cref="GameObject.SetActive(bool)"/>.</summary> /// <param name="enabled">A <see cref="FaceMask"/> that represents the only faces that should be enabled.</param> public void ToggleFaces(FaceMask enabled) { right.SetActive(enabled.PosX); left.SetActive(enabled.NegX); top.SetActive(enabled.PosY); bottom.SetActive(enabled.NegY); front.SetActive(enabled.PosZ); back.SetActive(enabled.NegZ); }
private string createGeometry(MeshFilter meshFilter) { Geometry3JS geometry = new Geometry3JS(); geometry.name = meshFilter.name; Mesh mesh = meshFilter.sharedMesh; geometry.metadata.vertices = mesh.vertexCount; geometry.metadata.normals = mesh.normals.Length; geometry.metadata.uvs = mesh.uv.Length; geometry.metadata.faces = mesh.triangles.Length / 3; FaceMask code = FaceMask.TRIANGLE; // Vertices geometry.data.vertices = new float[mesh.vertexCount * 3]; Vector3[] vertices = mesh.vertices; for (int i = 0; i < mesh.vertexCount; i++) { Vector3 vertex = vertices[i]; // (-1) * geometry.data.vertices[i * 3] = vertex.x; geometry.data.vertices[i * 3 + 1] = vertex.y; geometry.data.vertices[i * 3 + 2] = (-1) * vertex.z; } // Normals geometry.data.normals = new float[mesh.normals.Length * 3]; Vector3[] normals = mesh.normals; if (normals.Length > 0) { code = code | FaceMask.VERTEX_NORMAL; } for (int i = 0; i < normals.Length; i++) { Vector3 normal = normals[i]; normal.Normalize(); // (-1) * geometry.data.normals[i * 3] = normal.x; geometry.data.normals[i * 3 + 1] = normal.y; geometry.data.normals[i * 3 + 2] = (-1) * normal.z; } // UV geometry.data.uvs = new float[1, mesh.uv.Length * 2]; Vector2[] uvs = mesh.uv; if (uvs.Length > 0) { code = code | FaceMask.FACE_VERTEX_UV; } for (int i = 0; i < uvs.Length; i++) { Vector2 uv = uvs[i]; geometry.data.uvs[0, i * 2] = uv.x; geometry.data.uvs[0, i * 2 + 1] = uv.y; } // Colors geometry.data.colors = new float[mesh.colors.Length * 3]; Color[] colors = mesh.colors; for (int i = 0; i < colors.Length; i++) { Color color = colors[i]; geometry.data.colors[i * 3] = color.r; geometry.data.colors[i * 3 + 1] = color.b; geometry.data.colors[i * 3 + 2] = color.g; } // Faces int subMeshCount = mesh.subMeshCount; if (subMeshCount > 1) { code = code | FaceMask.FACE_MATERIAL; } switch ((int)code) { case 0: // 0, [vertex_index, vertex_index, vertex_index] geometry.data.faces = createFaces(mesh); break; case 2: // 2, [vertex_index, vertex_index, vertex_index], // [material_index] geometry.data.faces = createFacesWithMaterials(mesh); break; case 8: // 8, [vertex_index, vertex_index, vertex_index], // [vertex_uv, vertex_uv, vertex_uv] geometry.data.faces = createFacesWithUV(mesh); break; case 10: // 10, [vertex_index, vertex_index, vertex_index], // [material_index], // [vertex_uv, vertex_uv, vertex_uv] geometry.data.faces = createFacesWithMaterialsUV(mesh); break; case 32: // 32, [vertex_index, vertex_index, vertex_index], // [vertex_normal, vertex_normal, vertex_normal] geometry.data.faces = createFacesWithNormals(mesh); break; case 34: // 34, [vertex_index, vertex_index, vertex_index], // [material_index], // [vertex_normal, vertex_normal, vertex_normal] geometry.data.faces = createFacesWithMaterialsNormals(mesh); break; case 40: // 40, [vertex_index, vertex_index, vertex_index], // [vertex_uv, vertex_uv, vertex_uv], // [vertex_normal, vertex_normal, vertex_normal] geometry.data.faces = createFacesWithUVNormals(mesh); break; case 42: // 42, [vertex_index, vertex_index, vertex_index], // [material_index], // [vertex_uv, vertex_uv, vertex_uv], // [vertex_normal, vertex_normal, vertex_normal] geometry.data.faces = createFacesWithMaterialsUVNormals(mesh); break; } content.geometries.Add(geometry); geometries.Add(geometry.uuid, mesh); return(geometry.uuid); }
public BoolEnumerator(FaceMask mask) => this.mask = mask;
/// <summary> /// Create the mesh from the current voxel data /// </summary> public void CreateMesh() { try { var vertices = new List <Vector3>(); var normals = new List <Vector3>(); var colors = new List <Color>(); var uv = new List <Vector2>(); var uv2 = new List <Vector2>(); var uv3 = new List <Vector2>(); var triangles = new List <int>(); Vector3 offset = new Vector3( _width * _voxelScaleFactor.x, _height * _voxelScaleFactor.y, _depth * _voxelScaleFactor.z) * _levelOfDetailDivisor / 2.0f; // GreedyMesh (volume, dims) // Sweep over 3-axes // dimension = 0 -> y, z // dimension = 1 -> z, x // dimension = 2 -> x, y for (int dimension = 0; dimension < 3; dimension++) { // 0 -> x, 1 -> y, 2 -> z int u = (dimension + 1) % 3; int v = (dimension + 2) % 3; int dimensionU = 0; int dimensionV = 0; int dimensionMax = 0; switch (dimension) { case 0: dimensionMax = _width / _levelOfDetailDivisor; break; case 1: dimensionMax = _height / _levelOfDetailDivisor; break; case 2: dimensionMax = _depth / _levelOfDetailDivisor; break; } switch (u) { case 0: dimensionU = _width / _levelOfDetailDivisor; break; case 1: dimensionU = _height / _levelOfDetailDivisor; break; case 2: dimensionU = _depth / _levelOfDetailDivisor; break; } switch (v) { case 0: dimensionV = _width / _levelOfDetailDivisor; break; case 1: dimensionV = _height / _levelOfDetailDivisor; break; case 2: dimensionV = _depth / _levelOfDetailDivisor; break; } int maskSize = dimensionU * dimensionV; FaceMask <T>[] mask = new FaceMask <T> [maskSize]; int[] x = { 0, 0, 0 }; int[] q = { 0, 0, 0 }; q[dimension] = 1; x[dimension] = -1; // All normal directions start in the negative direction int[,] normalDirections = new int[dimensionU, dimensionV]; for (int normalU = 0; normalU < dimensionU; normalU++) { for (int normalV = 0; normalV < dimensionV; normalV++) { normalDirections[normalU, normalV] = -1; } } while (x[dimension] < dimensionMax) { // Compute mask int maskIndex = 0; for (x[v] = 0; x[v] < dimensionV; x[v]++) { for (x[u] = 0; x[u] < dimensionU; x[u]++) { bool first; if (0 > x[dimension] || _voxels[Utilities.GetIndex(x[0] * _levelOfDetailDivisor, x[1] * _levelOfDetailDivisor, x[2] * _levelOfDetailDivisor, _width, _height, _depth)].Empty) { first = false; } else { first = true; } bool second; if (x[dimension] >= dimensionMax - 1 || _voxels[Utilities.GetIndex((x[0] + q[0]) * _levelOfDetailDivisor, (x[1] + q[1]) * _levelOfDetailDivisor, (x[2] + q[2]) * _levelOfDetailDivisor, _width, _height, _depth)].Empty) { second = false; } else { second = true; } if (first != second) { mask[maskIndex].HasFace = true; if (first) { mask[maskIndex].Voxel = _voxels[Utilities.GetIndex(x[0] * _levelOfDetailDivisor, x[1] * _levelOfDetailDivisor, x[2] * _levelOfDetailDivisor, _width, _height, _depth)]; mask[maskIndex].FirstOrSecond = 1; } else { mask[maskIndex].Voxel = _voxels[Utilities.GetIndex((x[0] + q[0]) * _levelOfDetailDivisor, (x[1] + q[1]) * _levelOfDetailDivisor, (x[2] + q[2]) * _levelOfDetailDivisor, _width, _height, _depth)]; mask[maskIndex].FirstOrSecond = 2; } } else { mask[maskIndex].HasFace = false; } ++maskIndex; } } //Increment x[dimension] x[dimension]++; //Generate mesh for mask using lexicographic ordering int n = 0; for (int j = 0; j < dimensionV; j++) { int i = 0; while (i < dimensionU) { if (mask[n].HasFace) { //Compute width int w = 1; if (n + w < mask.Length) { while ( mask[n].HasFace == mask[n + w].HasFace && i + w < dimensionU && mask[n].FirstOrSecond == mask[n + w].FirstOrSecond && mask[n].Voxel.Equals(mask[n + w].Voxel) ) { w++; if (n + w >= mask.Length) { break; } } } //Compute height (this is slightly awkward) bool done = false; int h; for (h = 1; j + h < dimensionV; h++) { for (int k = 0; k < w; k++) { if ( mask[n].HasFace != mask[n + k + h * dimensionU].HasFace || mask[n].FirstOrSecond != mask[n + k + h * dimensionU].FirstOrSecond || !mask[n].Voxel.Equals(mask[n + k + h * dimensionU].Voxel) ) { done = true; break; } } if (done) { break; } } //Add quad // Get the starting point x[u] = i; x[v] = j; // Get the change in the dimensions for end point int[] du = { 0, 0, 0 }; du[u] = w; int[] dv = { 0, 0, 0 }; dv[v] = h; // Get mask direction int maskNormalDirection = normalDirections[i, j]; // +/- represents normal direction FaceType faceType = FaceType.None; if (u == 1 && v == 2) // X { faceType = maskNormalDirection > 0 ? FaceType.XPositive : FaceType.XNegative; } else if (u == 2 && v == 0) // Y { faceType = maskNormalDirection > 0 ? FaceType.YPositive : FaceType.YNegative; } else if (u == 0 && v == 1) // Z { faceType = maskNormalDirection > 0 ? FaceType.ZPositive : FaceType.ZNegative; } int baseVerticesNum = vertices.Count; // If the face is rendered, add it to the triangle list, otherwise skip it if (mask[n].Voxel.AddVoxelToMesh(faceType, w, h, colors, uv, uv2, uv3)) { // Vertices vertices.Add(new Vector3((x[0]) * _voxelScaleFactor.x, (x[1]) * _voxelScaleFactor.y, (x[2]) * _voxelScaleFactor.z) * _levelOfDetailDivisor - offset); // 0 vertices.Add(new Vector3((x[0] + du[0]) * _voxelScaleFactor.x, (x[1] + du[1]) * _voxelScaleFactor.y, (x[2] + du[2]) * _voxelScaleFactor.z) * _levelOfDetailDivisor - offset); // 1 vertices.Add(new Vector3((x[0] + du[0] + dv[0]) * _voxelScaleFactor.x, (x[1] + du[1] + dv[1]) * _voxelScaleFactor.y, (x[2] + du[2] + dv[2]) * _voxelScaleFactor.z) * _levelOfDetailDivisor - offset); // 2 vertices.Add(new Vector3((x[0] + dv[0]) * _voxelScaleFactor.x, (x[1] + dv[1]) * _voxelScaleFactor.y, (x[2] + dv[2]) * _voxelScaleFactor.z) * _levelOfDetailDivisor - offset); // 3 // Normals switch (faceType) { case FaceType.XPositive: case FaceType.XNegative: normals.Add(new Vector3(maskNormalDirection, 0.0f, 0.0f)); normals.Add(new Vector3(maskNormalDirection, 0.0f, 0.0f)); normals.Add(new Vector3(maskNormalDirection, 0.0f, 0.0f)); normals.Add(new Vector3(maskNormalDirection, 0.0f, 0.0f)); break; case FaceType.YPositive: case FaceType.YNegative: normals.Add(new Vector3(0.0f, maskNormalDirection, 0.0f)); normals.Add(new Vector3(0.0f, maskNormalDirection, 0.0f)); normals.Add(new Vector3(0.0f, maskNormalDirection, 0.0f)); normals.Add(new Vector3(0.0f, maskNormalDirection, 0.0f)); break; case FaceType.ZPositive: case FaceType.ZNegative: normals.Add(new Vector3(0.0f, 0.0f, maskNormalDirection)); normals.Add(new Vector3(0.0f, 0.0f, maskNormalDirection)); normals.Add(new Vector3(0.0f, 0.0f, maskNormalDirection)); normals.Add(new Vector3(0.0f, 0.0f, maskNormalDirection)); break; } if (maskNormalDirection == 1) { // Triangles triangles.Add(baseVerticesNum); // 0 triangles.Add(baseVerticesNum + 1); // 1 triangles.Add(baseVerticesNum + 2); // 2 triangles.Add(baseVerticesNum); // 0 triangles.Add(baseVerticesNum + 2); // 2 triangles.Add(baseVerticesNum + 3); // 3 } else { // Triangles triangles.Add(baseVerticesNum); // 0 triangles.Add(baseVerticesNum + 2); // 2 triangles.Add(baseVerticesNum + 1); // 1 triangles.Add(baseVerticesNum); // 0 triangles.Add(baseVerticesNum + 3); // 3 triangles.Add(baseVerticesNum + 2); // 2 } } // Set covered area to opposite normal direction for (int normalU = i; normalU < i + w; ++normalU) { for (int normalV = j; normalV < j + h; ++normalV) { normalDirections[normalU, normalV] *= -1; } } //Zero-out mask for (int l = 0; l < h; l++) { for (int k = 0; k < w; k++) { mask[n + k + l * dimensionU].HasFace = false; } } //Increment counters and continue i += w; n += w; } else { i++; n++; } } } } } Vertices = vertices.ToArray(); Normals = normals.ToArray(); Colors = colors.ToArray(); UV = uv.ToArray(); UV2 = uv2.ToArray(); UV3 = uv3.ToArray(); Triangles = triangles.ToArray(); Utilities.TangentSolver(Triangles, Vertices, Normals, UV); Completed = true; } catch (Exception exception) { Debug.Log(string.Format("Error creating mesh: {0}", exception.Message)); } }