Example #1
0
        static int Main(string[] args)
        {
            if (args.Length < 1)
            {
                Console.WriteLine("Usage: input_file.obj [options]");
                Console.WriteLine("  Options:");
                Console.WriteLine("    -verbose");
                return(1);
            }
            var filePath = args[0];

            s_verbose = (args.Length >= 2 && string.Compare(args[1], "-verbose") == 0);
            // Load object file.
            if (!File.Exists(filePath))
            {
                Console.WriteLine($"Specified file not found: {filePath}");
                return(1);
            }

            Console.WriteLine($"Loading {args[0]}...");

            var objLoaderFactory = new ObjLoaderFactory();
            var materialProvider = new MaterialNullStreamProvider();
            var objLoader        = objLoaderFactory.Create(materialProvider);

            LoadResult loadResult;

            using (var fileStream = File.OpenRead(args[0]))
            {
                loadResult = objLoader.Load(fileStream);
            }

            Console.WriteLine($"   {loadResult.Groups.Count} shapes");

            // Create empty atlas.
            XAtlas.SetPrint(PrintCallback, s_verbose);
            Atlas atlas = Atlas.Create();

            // Set progress callback.
            stopwatch = new Stopwatch();
            atlas.SetProgressCallback(ProgressCallback, IntPtr.Zero);

            var globalStopwatch = Stopwatch.StartNew();

            // Add meshes to atlas.
            uint totalVertices = 0, totalFaces = 0;
            var  modelMeshes = ObjParserHelper.GenerateMeshes(loadResult).ToArray();
            int  meshIndex   = 0;

            foreach (var mesh in modelMeshes)
            {
                var indexBuffer        = mesh.IndexBuffer;
                var vertexBuffer       = mesh.VertexBuffer;
                var indexBufferHandle  = GCHandle.Alloc(indexBuffer, GCHandleType.Pinned);
                var vertexBufferHandle = GCHandle.Alloc(vertexBuffer, GCHandleType.Pinned);

                var meshDecl = new MeshDecl();
                meshDecl.VertexCount          = (uint)vertexBuffer.Length;
                meshDecl.VertexPositionData   = vertexBufferHandle.AddrOfPinnedObject();
                meshDecl.VertexPositionStride = VertexPositionNormalTexture.Stride;

                //var normalElement = vertexLayout.Elements.FirstOrDefault(x => x.Semantic == ElementSemanticType.Normal);
                //if (normalElement != default)
                //{
                meshDecl.VertexNormalData   = IntPtr.Add(meshDecl.VertexPositionData, sizeof(float) * 3);
                meshDecl.VertexNormalStride = VertexPositionNormalTexture.Stride;
                //}

                //var texCoordElement = vertexLayout.Elements.FirstOrDefault(x => x.Semantic == ElementSemanticType.TexCoord);
                //if (texCoordElement != default)
                //{
                meshDecl.VertexUvData   = IntPtr.Add(meshDecl.VertexNormalData, sizeof(float) * 3);
                meshDecl.VertexUvStride = VertexPositionNormalTexture.Stride;
                //}

                meshDecl.IndexCount  = (uint)indexBuffer.Length;
                meshDecl.IndexData   = indexBufferHandle.AddrOfPinnedObject();
                meshDecl.IndexFormat = IndexFormat.UInt16;

#if !OBJ_TRIANGULATE
                //if (objPositions.Length != indices.Length / 3)
                {
                    //meshDecl.FaceVertexCount = objMesh.num_vertices.data();
                    //meshDecl.FaceCount = (uint32_t)objMesh.num_vertices.size();
                }
#endif
                var error = atlas.AddMesh(meshDecl, 1);
                indexBufferHandle.Free();
                vertexBufferHandle.Free();
                if (error != AddMeshError.Success)
                {
                    atlas.Destroy();
                    Console.WriteLine($"Error adding mesh {meshIndex} '{mesh.Name}': {XAtlas.StringForEnum(error)}\n");
                    return(1);
                }

                meshIndex++;
                totalVertices += meshDecl.VertexCount;
                if (meshDecl.FaceCount > 0)
                {
                    totalFaces += meshDecl.FaceCount;
                }
                else
                {
                    totalFaces += meshDecl.IndexCount / 3; // Assume triangles if MeshDecl.FaceCount not specified.
                }
            }

            atlas.AddMeshJoin(); // Not necessary. Only called here so geometry totals are printed after the AddMesh progress indicator.
            Console.WriteLine($"   {totalVertices} total vertices");
            Console.WriteLine($"   {totalFaces} total faces");

            // Generate atlas.
            Console.WriteLine("Generating atlas");
            atlas.Generate();
            Console.WriteLine($"   {atlas.ChartCount} charts");
            Console.WriteLine($"   {atlas.AtlasCount} atlases");
            int i;
            for (i = 0; i < atlas.AtlasCount; i++)
            {
                Console.WriteLine($"      {i}: {atlas.Utilization[i] * 100.0f:0.00}% utilization");
            }

            Console.WriteLine($"   {atlas.Width}x{atlas.Height} resolution");
            totalVertices = 0;
            i             = 0;
            foreach (var mesh in atlas.Meshes)
            {
                totalVertices += mesh.VertexCount;
                // Input and output index counts always match.
                if (mesh.IndexCount != modelMeshes[i++].IndexBuffer.Length)
                {
                    throw new InvalidOperationException("Input and output index counts does not match");
                }
            }

            globalStopwatch.Stop();

            Console.WriteLine($"   {totalVertices} total vertices");
            Console.WriteLine($"{globalStopwatch.Elapsed.TotalSeconds} seconds ({globalStopwatch.ElapsedMilliseconds} ms) elapsed total");

            // Cleanup.
            atlas.Destroy();
            Console.WriteLine("Done");

            return(0);
        }
 public ObjToVoxelReader()
 {
     this.loaderFactory          = new ObjLoaderFactory();
     this.materialStreamProvider = new MaterialNullStreamProvider();
 }