private static void AppendTexturedFaces(Dictionary <BlockFaceTexture, List <TexturedFace> > texturedFaces, TextureCoordinateDictionary textureCoordinates, Block blockType, Volume volume, Face face, FaceVertices faceVertices) { BlockFaceTexture blockFaceTexture = blockType.GetFaceTexture(face); TexturedFace texturedFace = new TexturedFace(volume, face, faceVertices); List <TexturedFace> texturedFacesList; if (texturedFaces.TryGetValue(blockFaceTexture, out texturedFacesList)) { texturedFacesList.Add(texturedFace); } else { texturedFacesList = new List <TexturedFace>(); texturedFacesList.Add(texturedFace); texturedFaces.Add(blockFaceTexture, texturedFacesList); } textureCoordinates.EnsureExists(texturedFace.textureMapping); }
private static void ProcessBlocks(string outputPath, Dictionary <CoordinateInt, Block> rawBlocks) { /* We need to identify any bricks that are hidden from vision. */ Console.WriteLine("Identifying invisible blocks."); HashSet <CoordinateInt> invisibleBricks = new HashSet <CoordinateInt>(); foreach (KeyValuePair <CoordinateInt, Block> pair in rawBlocks) { if (IsInvisible(pair.Key, rawBlocks)) { invisibleBricks.Add(pair.Key); } } foreach (CoordinateInt coord in invisibleBricks) { rawBlocks.Remove(coord); } Console.WriteLine("Identified {0} invisible bricks.", invisibleBricks.Count); /* Before we can start expanding cubes, we need to organize by block type. */ Console.WriteLine("Extracting largest volumes."); Dictionary <Block, List <Volume> > volumizedWorld = new Dictionary <Block, List <Volume> >(); foreach (KeyValuePair <Block, HashSet <CoordinateInt> > pair in OrganizeRawBlocks(rawBlocks)) { volumizedWorld.Add(pair.Key, new List <Volume>(new LargestVolumeExtractor(pair.Value, invisibleBricks))); } /* Scan for interior faces that we can remove. */ HiddenFaces.totalHiddenFaces = 0; Console.WriteLine("Identifying interior faces."); Dictionary <Block, List <FacedVolume> > facedVolumizedWorld = HiddenFaces.DetectHiddenFaces(volumizedWorld, rawBlocks); Console.WriteLine("Identified {0} interior faces.", HiddenFaces.totalHiddenFaces); /* Storage for the actual 3D geometry. */ List <CoordinateDecimal> vertices = new List <CoordinateDecimal>(); Dictionary <string, List <FaceVertices> > collisionBoxes = new Dictionary <string, List <FaceVertices> >(); Dictionary <BlockFaceTexture, List <TexturedFace> > texturedFaces = new Dictionary <BlockFaceTexture, List <TexturedFace> >(); TextureCoordinateDictionary textureCoordinates = new TextureCoordinateDictionary(); /* Build the textured faces from the volumes. */ foreach (KeyValuePair <Block, List <FacedVolume> > pair in facedVolumizedWorld) { List <FacedVolume> volumes = pair.Value; for (int idx = 0; idx < volumes.Count; idx++) { FacedVolume facedVolume = volumes[idx]; Iterators.FacesInVolume(vertices.Count, facedVolume.excludedFaces, (Face face, FaceVertices faceVertices) => { AppendTexturedFaces(texturedFaces, textureCoordinates, pair.Key, facedVolume.volume, face, faceVertices); }); Iterators.VerticesInVolume(volumes[idx].volume, (CoordinateDecimal a) => { vertices.Add(a); }); } } Console.WriteLine(textureCoordinates.mappingList.Count + " unique texture coordinates."); /* Delete duplicate vertices before adding collision UBXs because the UBX vertices will all be unique. */ Console.WriteLine("Detecting duplicate vertices."); int duplicatesRemoved = DuplicateVertices.DetectAndErase(vertices, texturedFaces); Console.WriteLine(duplicatesRemoved + " duplicate vertices removed."); Console.WriteLine("Generate UBX collision volumes."); foreach (KeyValuePair <Block, List <FacedVolume> > pair in facedVolumizedWorld) { List <FacedVolume> volumes = pair.Value; for (int idx = 0; idx < volumes.Count; idx++) #warning Potential for collision meshes to be far from visual mesh! { MakeCollisionUBX("UBX_" + pair.Key.ToString() + string.Format("_{0:00}", idx), volumes[idx].volume, vertices, collisionBoxes); } } /* Export the geometry to Wavefront's OBJ format. */ WavefrontObj objFile = new WavefrontObj(vertices, collisionBoxes, texturedFaces, textureCoordinates, facedVolumizedWorld); /* Save the OBJ file to the specified destination. */ File.WriteAllText(outputPath, objFile.ToString()); }