public unsafe void TestImportFromMemory()
        {
            String path = Path.Combine(TestHelper.RootPath, "TestFiles\\duck.dae");

            byte[] memory = File.ReadAllBytes(path);

            fixed(byte *ptr = memory)
            {
                AssimpContext importer = new AssimpContext();

                LogStream.IsVerboseLoggingEnabled = true;

                LogStream logstream = new LogStream(delegate(String msg, String userData)
                {
                    Console.WriteLine(msg);
                });

                logstream.Attach();

                Scene scene = importer.ImportFileFromMemory(new IntPtr(ptr), (uint)memory.Length, ".dae");

                Assert.IsNotNull(scene);
                Assert.IsTrue((scene.SceneFlags & SceneFlags.Incomplete) != SceneFlags.Incomplete);
            }
        }
예제 #2
0
        private void LoadModel(Asset asset)
        {
            // TODO: Remove assimp
            var context = new AssimpContext();

            var logStream = new LogStream((msg, userData) =>
            {
                Logging.Log($"{msg}");
            });

            logStream.Attach();

            var extension = Path.GetExtension(asset.MountPath).Substring(1);

            using var memoryStream = new MemoryStream(asset.Data);
            memoryStream.Seek(0, SeekOrigin.Begin);

            var scene = context.ImportFile("Content/" + asset.MountPath,
                                           PostProcessSteps.Triangulate
                                           | PostProcessSteps.PreTransformVertices
                                           | PostProcessSteps.RemoveRedundantMaterials
                                           | PostProcessSteps.CalculateTangentSpace
                                           | PostProcessSteps.OptimizeMeshes
                                           | PostProcessSteps.OptimizeGraph
                                           | PostProcessSteps.ValidateDataStructure
                                           | PostProcessSteps.GenerateNormals
                                           | PostProcessSteps.FlipUVs);

            directory = Path.GetDirectoryName(asset.MountPath);

            ProcessNode(scene.RootNode, scene);
        }
예제 #3
0
        //
        //  IMPOTER
        //

        private void InitLog()
        {
            LogStream logstream = new LogStream(delegate(String msg, String userData)
            {
                Console.WriteLine(msg);
            });

            logstream.Attach();
        }
예제 #4
0
        private void button1_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            // Получаем выбранный файл
            string filename = openFileDialog1.FileName;

            textBox1.AppendText(String.Format("Load: {0} {1}", filename, Environment.NewLine));

            // Включим логи для импортера
            LogStream logstream = new LogStream(delegate(String msg, String userData)
            {
                textBox1.AppendText(msg + Environment.NewLine);
            });

            logstream.Attach();


            // Импортиуем
            UVCoords = new List <Vector3D>();                                                               // Координаты
            UVVertex = new HashSet <Vector3D>();                                                            // Точки
            AssimpContext importer = new AssimpContext();
            Scene         scene    = importer.ImportFile(filename, PostProcessSteps.ValidateDataStructure); // (PostProcessSteps.FindInstances | PostProcessSteps.ValidateDataStructure)

            if (scene.Meshes.Count > 0)
            {
                Mesh mesh = scene.Meshes[0];

                if (mesh.TextureCoordinateChannelCount > 0)
                {
                    UVCoords = mesh.TextureCoordinateChannels[0];


                    foreach (Vector3D uv in UVCoords)
                    {
                        UVVertex.Add(uv);
                    }
                }
            }

            DrawImage();
            importer.Dispose();
            Refresh();
        }
예제 #5
0
        public Scene BuildAssimpScene(MemoryStream model_data, string format_hint)
        {
            Scene tmp_scene;

            using (var importer = new AssimpContext())
            {
                importer.SetConfig(new NormalSmoothingAngleConfig(66.0f));
                LogStream logstream = new LogStream((msg, userData) => _logger.Log(msg));
                logstream.Attach();
                tmp_scene = importer.ImportFileFromStream(model_data
                                                          , PostProcessPreset.TargetRealTimeFast
                                                          , format_hint);
                // we could load the model into our own data structures here
            }
            if (tmp_scene == null || tmp_scene.SceneFlags.HasFlag(SceneFlags.Incomplete))
            {
                throw new Exception("Bad file format. Could not read data.");
            }
            return(tmp_scene);
        }
예제 #6
0
        public static Scene LoadFbx(string fileName)
        {
            //Create a new importer
            using (var importer = new AssimpContext())
            {
                //This is how we add a configuration (each config is its own class)
                NormalSmoothingAngleConfig config = new NormalSmoothingAngleConfig(66.0f);
                importer.SetConfig(config);

                //This is how we add a logging callback
                LogStream logstream = new LogStream(delegate(String msg, String userData) {
                    Console.WriteLine(msg);
                });
                logstream.Attach();

                //Import the model. All configs are set. The model
                //is imported, loaded into managed memory. Then the unmanaged memory is released, and everything is reset.
                Scene model = importer.ImportFile(fileName, PostProcessPreset.TargetRealTimeMaximumQuality);

                return(model);
            }
        }
예제 #7
0
        public void TestImportFromStream()
        {
            String path = Path.Combine(TestHelper.RootPath, "TestFiles\\duck.dae");

            FileStream fs = File.OpenRead(path);

            AssimpContext importer = new AssimpContext();

            LogStream.IsVerboseLoggingEnabled = true;

            LogStream logstream = new LogStream(delegate(String msg, String userData)
            {
                Console.WriteLine(msg);
            });

            logstream.Attach();

            Scene scene = importer.ImportFileFromStream(fs, ".dae");

            fs.Close();

            Assert.IsNotNull(scene);
            Assert.IsTrue((scene.SceneFlags & SceneFlags.Incomplete) != SceneFlags.Incomplete);
        }
예제 #8
0
        public void TestExportBadFormatId()
        {
            AssimpContext importer            = new AssimpContext();
            NormalSmoothingAngleConfig config = new NormalSmoothingAngleConfig(66.0f);

            importer.SetConfig(config);

            LogStream logStream = new LogStream(delegate(string msg, string userData)
            {
                Console.WriteLine(msg);
            });

            logStream.Attach();

            Scene collada = importer.ImportFile(Path.Combine(TestHelper.RootPath, "TestFiles/duck.dae"));

            bool success = importer.ExportFile(collada, Path.Combine(TestHelper.RootPath, "TestFiles/output/exportedCollada.dae"), "dae");

            Assert.IsFalse(success);

            success = importer.ExportFile(collada, Path.Combine(TestHelper.RootPath, "TestFiles/output/exportedCollada.dae"), "collada");

            Assert.IsTrue(success);
        }
예제 #9
0
        public static void LoadSource(this RMesh rmesh, string filename)
        {
            AssimpContext context = new AssimpContext();

            context.SetConfig(new Assimp.Configs.FBXImportAllMaterialsConfig(true));
            context.SetConfig(new Assimp.Configs.FBXImportAllGeometryLayersConfig(true));
            context.SetConfig(new Assimp.Configs.MultithreadingConfig(2));
            context.SetConfig(new Assimp.Configs.FBXStrictModeConfig(false));
            if (!context.IsImportFormatSupported(Path.GetExtension(filename)))
            {
                throw new ReactorException("Attempted to load a model that Assimp doesn't know how to load");
            }
            LogStream log = new LogStream((msg, user) => {
                RLog.Info(msg.Remove(msg.Length - 2));
            });

            log.Attach();
            int   platform = (int)Environment.OSVersion.Platform;
            Scene scene    = context.ImportFile(filename,
                                                PostProcessSteps.FindInvalidData |
                                                PostProcessSteps.GenerateSmoothNormals |
                                                PostProcessSteps.Triangulate |
                                                PostProcessSteps.GenerateUVCoords |
                                                PostProcessSteps.CalculateTangentSpace |
                                                PostProcessSteps.PreTransformVertices);

            if (scene.HasMeshes)
            {
                foreach (Mesh mesh in scene.Meshes)
                {
                    if (!mesh.HasVertices)
                    {
                        continue;
                    }
                    RMeshPart rmeshpart = RMeshPart.Create <RMeshPart> ();


                    RVertexData [] data = new RVertexData [mesh.VertexCount];

                    List <int> indicesList = new List <int> ();

                    if (mesh.HasFaces)
                    {
                        foreach (Face face in mesh.Faces)
                        {
                            indicesList.AddRange(face.Indices.ToArray());
                            foreach (int index in face.Indices)
                            {
                                Vector3D p = mesh.Vertices [index];
                                data [index].Position = new Vector3(p.X, p.Y, p.Z);
                                if (mesh.HasTextureCoords(0))
                                {
                                    Vector3D t = mesh.TextureCoordinateChannels [0] [index];
                                    data [index].TexCoord = new Vector2(t.X, -t.Y);
                                }

                                if (mesh.HasNormals)
                                {
                                    Vector3D n = mesh.Normals [index];
                                    data [index].Normal = new Vector3(n.X, n.Y, n.Z);
                                }

                                if (mesh.HasTangentBasis)
                                {
                                    Vector3D b = mesh.BiTangents [index];
                                    Vector3D t = mesh.Tangents [index];
                                    data [index].Bitangent = new Vector3(b.X, b.Y, b.Z);
                                    data [index].Tangent   = new Vector3(t.X, t.Y, t.Z);
                                }
                            }
                        }
                    }



                    RVertexBuffer vbuffer = new RVertexBuffer(typeof(RVertexData), mesh.VertexCount, RBufferUsage.WriteOnly, true);


                    RIndexBuffer ibuffer = new RIndexBuffer(typeof(int), indicesList.Count, RBufferUsage.WriteOnly);
                    ibuffer.SetData(indicesList.ToArray());

                    vbuffer.SetData <RVertexData> (data);

#if WINDOWS
                    var separator = "\\";
#else
                    var separator = "/";
#endif

                    rmeshpart.VertexBuffer = vbuffer;
                    rmeshpart.IndexBuffer  = ibuffer;

                    RMaterial material = new RMaterial(rmesh.Name + ":Material");

                    if (scene.HasMaterials)
                    {
                        Material mat = scene.Materials[mesh.MaterialIndex];
                        material.Shininess = mat.Shininess;
                        material.SetColor(RMaterialColor.DIFFUSE, new RColor(mat.ColorDiffuse.R, mat.ColorDiffuse.G, mat.ColorDiffuse.B, mat.ColorDiffuse.A));
                        if (mat.HasTextureDiffuse)
                        {
                            var        texFileName = Path.GetFileName(mat.TextureDiffuse.FilePath.Replace("\\", separator).Replace("/", separator));
                            RTexture2D tex         = (RTexture2D)RTextures.Instance.CreateTexture <RTexture2D>(texFileName, "/textures/" + texFileName.ToLower());
                            tex.Bind();
                            tex.GenerateMipmaps();
                            tex.SetTextureMagFilter(RTextureMagFilter.Linear);
                            tex.SetTextureMinFilter(RTextureMinFilter.LinearMipmapLinear);
                            tex.SetTextureWrapMode(RTextureWrapMode.Repeat, RTextureWrapMode.Repeat);
                            tex.Unbind();
                            material.SetTexture(RTextureLayer.DIFFUSE, tex);
                        }
                        if (mat.HasTextureNormal)
                        {
                            var        texFileName = Path.GetFileName(mat.TextureNormal.FilePath.Replace("\\", separator).Replace("/", separator));
                            RTexture2D tex         = (RTexture2D)RTextures.Instance.CreateTexture <RTexture2D>(texFileName, "/textures/" + texFileName.ToLower());
                            tex.Bind();
                            tex.GenerateMipmaps();
                            tex.SetTextureMagFilter(RTextureMagFilter.Linear);
                            tex.SetTextureMinFilter(RTextureMinFilter.LinearMipmapLinear);
                            tex.SetTextureWrapMode(RTextureWrapMode.Repeat, RTextureWrapMode.Repeat);
                            tex.Unbind();
                            material.SetTexture(RTextureLayer.NORMAL, tex);
                        }
                        if (mat.HasTextureAmbient)
                        {
                            var        texFileName = Path.GetFileName(mat.TextureAmbient.FilePath.Replace("\\", separator).Replace("/", separator));
                            RTexture2D tex         = (RTexture2D)RTextures.Instance.CreateTexture <RTexture2D>(texFileName, "/textures/" + texFileName.ToLower());
                            tex.SetTextureMagFilter(RTextureMagFilter.Linear);
                            tex.SetTextureMinFilter(RTextureMinFilter.LinearMipmapLinear);
                            tex.SetTextureWrapMode(RTextureWrapMode.Repeat, RTextureWrapMode.Repeat);
                            material.SetTexture(RTextureLayer.AMBIENT, tex);
                        }
                        if (mat.HasTextureHeight)
                        {
                            var        texFileName = Path.GetFileName(mat.TextureHeight.FilePath.Replace("\\", separator).Replace("/", separator));
                            RTexture2D tex         = (RTexture2D)RTextures.Instance.CreateTexture <RTexture2D>(texFileName, "/textures/" + texFileName.ToLower());
                            tex.SetTextureMagFilter(RTextureMagFilter.Linear);
                            tex.SetTextureMinFilter(RTextureMinFilter.LinearMipmapLinear);
                            tex.SetTextureWrapMode(RTextureWrapMode.Repeat, RTextureWrapMode.Repeat);
                            material.SetTexture(RTextureLayer.HEIGHT, tex);
                        }
                        if (mat.HasTextureEmissive)
                        {
                            var        texFileName = Path.GetFileName(mat.TextureEmissive.FilePath.Replace("\\", separator).Replace("/", separator));
                            RTexture2D tex         = (RTexture2D)RTextures.Instance.CreateTexture <RTexture2D>(texFileName, "/textures/" + texFileName.ToLower());
                            tex.SetTextureMagFilter(RTextureMagFilter.Linear);
                            tex.SetTextureMinFilter(RTextureMinFilter.LinearMipmapLinear);
                            tex.SetTextureWrapMode(RTextureWrapMode.Repeat, RTextureWrapMode.Repeat);
                            material.SetTexture(RTextureLayer.GLOW, tex);
                        }
                        if (mat.HasTextureSpecular)
                        {
                            var        texFileName = Path.GetFileName(mat.TextureSpecular.FilePath.Replace("\\", separator).Replace("/", separator));
                            RTexture2D tex         = (RTexture2D)RTextures.Instance.CreateTexture <RTexture2D>(texFileName, "/textures/" + texFileName.ToLower());
                            tex.SetTextureMagFilter(RTextureMagFilter.Linear);
                            tex.SetTextureMinFilter(RTextureMinFilter.LinearMipmapLinear);
                            tex.SetTextureWrapMode(RTextureWrapMode.Repeat, RTextureWrapMode.Repeat);
                            material.SetTexture(RTextureLayer.SPECULAR, tex);
                        }
                    }
                    rmeshpart.Material = material;
                    rmesh.Parts.Add(rmeshpart);
                }
                //return rmesh;
            }
            //return null;
            if (rmesh.Parts.Count == 0)
            {
                throw new ReactorException("Attempted to load a model when Assimp couldn't find any verticies!");
            }

            context.Dispose();
        }
예제 #10
0
        public override bool Execute(List <string> args)
        {
            if (args.Count < 1 || args.Count > 2)
            {
                return(false);
            }

            TagInstance destination = _cache.Tags[0x3317];

            if (args.Count == 2)
            {
                destination = ArgumentParser.ParseTagIndex(_cache, args[0]);

                if (!destination.IsInGroup("mode"))
                {
                    Console.WriteLine("Specified tag is not a render_model: " + args[0]);
                    return(false);
                }

                args = args.Skip(1).ToList();
            }

            var builder = new RenderModelBuilder(_info.Version);

            // Add a root node
            var node = builder.AddNode(new RenderModel.Node
            {
                Name            = _stringIds.GetStringId("street_cone"),
                ParentNode      = -1,
                FirstChildNode  = -1,
                NextSiblingNode = -1,
                DefaultRotation = new Vector4(0, 0, 0, -1),
                DefaultScale    = 1,
                InverseForward  = new Vector3(1, 0, 0),
                InverseLeft     = new Vector3(0, 1, 0),
                InverseUp       = new Vector3(0, 0, 1),
            });

            // Begin building the default region and permutation
            builder.BeginRegion(_stringIds.GetStringId("default"));
            builder.BeginPermutation(_stringIds.GetStringId("default"));

            using (var importer = new AssimpContext())
            {
                Scene model;
                using (var logStream = new LogStream((msg, userData) => Console.WriteLine(msg)))
                {
                    logStream.Attach();
                    model = importer.ImportFile(args[0],
                                                PostProcessSteps.CalculateTangentSpace |
                                                PostProcessSteps.GenerateNormals |
                                                PostProcessSteps.JoinIdenticalVertices |
                                                PostProcessSteps.SortByPrimitiveType |
                                                PostProcessSteps.PreTransformVertices |
                                                PostProcessSteps.Triangulate);
                    logStream.Detach();
                }

                Console.WriteLine("Assembling vertices...");

                // Build a multipart mesh from the model data,
                // with each model mesh mapping to a part of one large mesh and having its own material
                builder.BeginMesh();
                ushort partStartVertex = 0;
                ushort partStartIndex  = 0;
                var    vertices        = new List <RigidVertex>();
                var    indices         = new List <ushort>();
                foreach (var mesh in model.Meshes)
                {
                    for (var i = 0; i < mesh.VertexCount; i++)
                    {
                        var position  = mesh.Vertices[i];
                        var normal    = mesh.Normals[i];
                        var uv        = mesh.TextureCoordinateChannels[0][i];
                        var tangent   = mesh.Tangents[i];
                        var bitangent = mesh.BiTangents[i];
                        vertices.Add(new RigidVertex
                        {
                            Position = new Vector4(position.X, position.Y, position.Z, 1),
                            Normal   = new Vector3(normal.X, normal.Y, normal.Z),
                            Texcoord = new Vector2(uv.X, uv.Y),
                            Tangent  = new Vector4(tangent.X, tangent.Y, tangent.Z, 1),
                            Binormal = new Vector3(bitangent.X, bitangent.Y, bitangent.Z),
                        });
                    }

                    // Build the index buffer
                    var meshIndices = mesh.GetIndices();
                    indices.AddRange(meshIndices.Select(i => (ushort)(i + partStartVertex)));

                    // Define a material and part for this mesh
                    var material = builder.AddMaterial(new RenderMaterial
                    {
                        RenderMethod = _cache.Tags[0x101F],
                    });
                    builder.DefinePart(material, partStartIndex, (ushort)meshIndices.Length, (ushort)mesh.VertexCount);

                    // Move to the next part
                    partStartVertex += (ushort)mesh.VertexCount;
                    partStartIndex  += (ushort)meshIndices.Length;
                }

                // Bind the vertex and index buffers
                builder.BindRigidVertexBuffer(vertices, node);
                builder.BindIndexBuffer(indices, PrimitiveType.TriangleList);
                builder.EndMesh();
            }

            builder.EndPermutation();
            builder.EndRegion();

            Console.WriteLine("Building Blam mesh data...");

            var resourceStream = new MemoryStream();
            var renderModel    = builder.Build(_info.Serializer, resourceStream);

            Console.WriteLine("Writing resource data...");

            // Add a new resource for the model data
            var resources = new ResourceDataManager();

            resources.LoadCachesFromDirectory(_fileInfo.DirectoryName);
            resourceStream.Position = 0;
            resources.Add(renderModel.Geometry.Resource, ResourceLocation.Resources, resourceStream);

            Console.WriteLine("Writing tag data...");

            using (var cacheStream = _fileInfo.Open(FileMode.Open, FileAccess.ReadWrite))
            {
                var tag     = destination;
                var context = new TagSerializationContext(cacheStream, _cache, _stringIds, tag);
                _info.Serializer.Serialize(context, renderModel);
            }
            Console.WriteLine("Model imported successfully!");
            return(true);
        }
예제 #11
0
        public static void Init()
        {
            AssimpContext importer            = new AssimpContext();
            NormalSmoothingAngleConfig config = new NormalSmoothingAngleConfig(66.0f);

            importer.SetConfig(config);

            LogStream logStream = new LogStream(delegate(string msg, string userData)
            {
                Console.WriteLine(msg);
            });

            logStream.Attach();

            Scene scene = importer.ImportFile(@"resources/icosphere.obj", PostProcessPreset.TargetRealTimeQuality);

            Mesh.Icosphere = scene.Meshes[0];

            scene = importer.ImportFile(@"resources/icosphereHigh.obj", PostProcessPreset.TargetRealTimeQuality);
            Mesh.IcosphereHigh = scene.Meshes[0];

            scene         = importer.ImportFile(@"resources/asteroid.obj", PostProcessPreset.TargetRealTimeQuality);
            Mesh.Asteroid = scene.Meshes[0];

            scene      = importer.ImportFile(@"resources/point.obj", PostProcessPreset.TargetRealTimeQuality);
            Mesh.Point = scene.Meshes[0];

            scene     = importer.ImportFile(@"resources/cube.obj", PostProcessPreset.TargetRealTimeQuality);
            Mesh.Cube = scene.Meshes[0];

            scene       = importer.ImportFile(@"resources/camera.obj", PostProcessPreset.TargetRealTimeQuality);
            Mesh.Camera = scene.Meshes[0];

            scene             = importer.ImportFile(@"resources/skybox.obj", PostProcessPreset.TargetRealTimeQuality);
            Mesh.SkyboxFront  = scene.Meshes[0];
            Mesh.SkyboxBack   = scene.Meshes[1];
            Mesh.SkyboxRight  = scene.Meshes[2];
            Mesh.SkyboxLeft   = scene.Meshes[3];
            Mesh.SkyboxTop    = scene.Meshes[4];
            Mesh.SkyboxBottom = scene.Meshes[5];

            scene          = importer.ImportFile(@"resources/gizmoPosX.ply", PostProcessPreset.TargetRealTimeQuality);
            Mesh.GizmoXPos = scene.Meshes[0];
            scene          = importer.ImportFile(@"resources/gizmoPosY.ply", PostProcessPreset.TargetRealTimeQuality);
            Mesh.GizmoYPos = scene.Meshes[0];
            scene          = importer.ImportFile(@"resources/gizmoPosZ.ply", PostProcessPreset.TargetRealTimeQuality);
            Mesh.GizmoZPos = scene.Meshes[0];

            scene          = importer.ImportFile(@"resources/gizmoRotX.ply", PostProcessPreset.TargetRealTimeQuality);
            Mesh.GizmoXRot = scene.Meshes[0];
            scene          = importer.ImportFile(@"resources/gizmoRotY.ply", PostProcessPreset.TargetRealTimeQuality);
            Mesh.GizmoYRot = scene.Meshes[0];
            scene          = importer.ImportFile(@"resources/gizmoRotZ.ply", PostProcessPreset.TargetRealTimeQuality);
            Mesh.GizmoZRot = scene.Meshes[0];

            scene        = importer.ImportFile(@"resources/text000.obj", PostProcessPreset.TargetRealTimeQuality);
            Mesh.Text000 = scene.Meshes[0];
            scene        = importer.ImportFile(@"resources/text090.obj", PostProcessPreset.TargetRealTimeQuality);
            Mesh.Text090 = scene.Meshes[0];
            scene        = importer.ImportFile(@"resources/text180.obj", PostProcessPreset.TargetRealTimeQuality);
            Mesh.Text180 = scene.Meshes[0];
            scene        = importer.ImportFile(@"resources/text270.obj", PostProcessPreset.TargetRealTimeQuality);
            Mesh.Text270 = scene.Meshes[0];

            importer.Dispose();
            logStream.Detach();
        }
예제 #12
0
        static public AssimpVolume LoadFromFile(string filename)
        {
            string path = Path.Combine("Assets", "Models", filename);

            AssimpContext importer = new AssimpContext();

            NormalSmoothingAngleConfig normalSmoothing = new NormalSmoothingAngleConfig(66.0f);

            importer.SetConfig(normalSmoothing);

            LogStream logStream = new LogStream
                                  (
                delegate(string message, string userData)
            {
                Console.Write(message);
            }
                                  );

            logStream.Attach();

            Scene model = importer.ImportFile(path, PostProcessPreset.TargetRealTimeMaximumQuality);
            Mesh  mesh  = model.Meshes[0];

            AssimpVolume v = new AssimpVolume();

            List <Vector3> newVertices = new List <Vector3>();

            foreach (Assimp.Vector3D vert in mesh.Vertices)
            {
                newVertices.Add(new Vector3(vert.X, vert.Y, vert.Z));
            }
            v.vertices = newVertices.ToArray();

            v.indices = mesh.GetIndices();

            if (mesh.HasNormals)
            {
                v.generateNormals = false;
                List <Vector3> newNormals = new List <Vector3>();
                foreach (Assimp.Vector3D n in mesh.Normals)
                {
                    newNormals.Add(new Vector3(n.X, n.Y, n.Z));
                }
                v.normals = newNormals.ToArray();
            }

            if (mesh.HasTextureCoords(0))
            {
                List <Vector2> newTextureCoords = new List <Vector2>();
                foreach (Assimp.Vector3D tc in mesh.TextureCoordinateChannels[0])
                {
                    newTextureCoords.Add(new Vector2(tc.X, tc.Y));
                }
                v.textureCoords = newTextureCoords.ToArray();
            }

            if (mesh.HasVertexColors(0))
            {
                List <Vector3> newColors = new List <Vector3>();
                foreach (Assimp.Color4D c in mesh.VertexColorChannels[0])
                {
                    newColors.Add(new Vector3(c.R, c.G, c.B));
                }
                v.colors = newColors.ToArray();
            }

            importer.Dispose();
            return(v);
        }
예제 #13
0
 public LogPipe(LogStore logStore)
 {
     _logStore = logStore;
     _stream   = new LogStream(LogStreamCallback);
     _stream.Attach();
 }
예제 #14
0
        public override object Execute(List <string> args)
        {
            if (args.Count < 1 || args.Count > 2)
            {
                return(false);
            }

            var stringIdCount  = Cache.StringTable.Count;
            var destinationTag = Cache.TagCache.GetTag(@"objects\gear\human\industrial\street_cone\street_cone", "mode");

            string vertexType = "rigid";

            if (args[0] == "skinned" || args[0] == "rigid")
            {
                vertexType = args[0];
                args.RemoveAt(0);
            }

            if (args.Count == 2)
            {
                if (!Cache.TryGetTag(args[0], out destinationTag) || !destinationTag.IsInGroup("mode"))
                {
                    Console.WriteLine("Specified tag is not a render_model: " + args[0]);
                    return(false);
                }

                args.RemoveAt(0);
            }

            RenderModel edMode = null;

            using (var cacheStream = Cache.OpenCacheReadWrite())
                edMode = Cache.Deserialize <RenderModel>(cacheStream, destinationTag);

            // Get a list of the original nodes
            var nodeIndices = new Dictionary <string, int>();

            foreach (var a in edMode.Nodes)
            {
                nodeIndices.Add(Cache.StringTable.GetString(a.Name), edMode.Nodes.IndexOf(a));
            }

            // Read the custom model file
            if (!File.Exists(args[0]))
            {
                return(false);
            }

            Console.WriteLine($"File date: {File.GetLastWriteTime(args[0])}");

            var builder = new RenderModelBuilder(Cache);

            using (var importer = new AssimpContext())
            {
                Scene model;

                if (vertexType == "skinned")
                {
                    using (var logStream = new LogStream((msg, userData) => Console.WriteLine(msg)))
                    {
                        logStream.Attach();
                        model = importer.ImportFile(args[0],
                                                    PostProcessSteps.CalculateTangentSpace |
                                                    PostProcessSteps.GenerateNormals |
                                                    PostProcessSteps.SortByPrimitiveType |
                                                    PostProcessSteps.Triangulate);
                        logStream.Detach();
                    }

                    for (var i = 0; i < model.Meshes.Count; i++)
                    {
                        if (!model.Meshes[i].HasBones)
                        {
                            throw new Exception($"Mesh \"{model.Meshes[i].Name}\" has no bones!");
                        }
                    }
                }
                else
                {
                    using (var logStream = new LogStream((msg, userData) => Console.WriteLine(msg)))
                    {
                        logStream.Attach();
                        model = importer.ImportFile(args[0],
                                                    PostProcessSteps.CalculateTangentSpace |
                                                    PostProcessSteps.GenerateNormals |
                                                    PostProcessSteps.JoinIdenticalVertices |
                                                    PostProcessSteps.SortByPrimitiveType |
                                                    PostProcessSteps.PreTransformVertices |
                                                    PostProcessSteps.Triangulate);
                        logStream.Detach();
                    }
                }

                Console.WriteLine("Assembling vertices...");

                // Add nodes
                var rigidNode = builder.AddNode(new RenderModel.Node
                {
                    Name            = Cache.StringTable.GetStringId("street_cone"),
                    ParentNode      = -1,
                    FirstChildNode  = -1,
                    NextSiblingNode = -1,
                    DefaultRotation = new RealQuaternion(0, 0, 0, -1),
                    DefaultScale    = 1,
                    InverseForward  = new RealVector3d(1, 0, 0),
                    InverseLeft     = new RealVector3d(0, 1, 0),
                    InverseUp       = new RealVector3d(0, 0, 1),
                });

                // Build a multipart mesh from the model data,
                // with each model mesh mapping to a part of one large mesh and having its own material
                ushort partStartVertex = 0;
                ushort partStartIndex  = 0;

                var rigidVertices   = new List <RigidVertex>();
                var skinnedVertices = new List <SkinnedVertex>();

                var indices = new List <ushort>();

                Dictionary <string, int> newNodes = new Dictionary <string, int>();
                foreach (var mesh in model.Meshes)
                {
                    var meshIndex = model.Meshes.IndexOf(mesh);

                    Console.Write($"Enter a region name for '{mesh.Name}' (mesh index {meshIndex}): ");
                    var regionName     = Console.ReadLine();
                    var regionStringId = Cache.StringTable.GetStringId(regionName);

                    if (regionStringId == StringId.Invalid)
                    {
                        regionStringId = Cache.StringTable.AddString(regionName);
                    }

                    // Begin building the default region and permutation
                    builder.BeginRegion(regionStringId);
                    builder.BeginPermutation(Cache.StringTable.GetStringId("default"));
                    builder.BeginMesh();

                    for (var i = 0; i < mesh.VertexCount; i++)
                    {
                        var position = mesh.Vertices[i];
                        var normal   = mesh.Normals[i];
                        var uv       = mesh.TextureCoordinateChannels[0][i];

                        var tangent   = mesh.Tangents.Count != 0 ? mesh.Tangents[i] : new Vector3D();
                        var bitangent = mesh.BiTangents.Count != 0 ? mesh.BiTangents[i] : new Vector3D();

                        if (vertexType == "skinned")
                        {
                            var blendIndicesList = new List <byte>();
                            var blendWeightsList = new List <float>();
                            var bonesList        = new List <string>();

                            foreach (var bone in mesh.Bones)
                            {
                                foreach (var vertexInfo in bone.VertexWeights)
                                {
                                    if (vertexInfo.VertexID == i)
                                    {
                                        bonesList.Add(bone.Name);
                                        blendIndicesList.Add((byte)nodeIndices[bone.Name]);
                                        blendWeightsList.Add(vertexInfo.Weight);
                                    }
                                }
                            }

                            var blendIndices = new byte[4];
                            var blendWeights = new float[4];

                            for (int j = 0; j < blendIndicesList.Count; j++)
                            {
                                if (j < 4)
                                {
                                    blendIndices[j] = blendIndicesList[j];
                                }
                            }

                            for (int j = 0; j < blendWeightsList.Count; j++)
                            {
                                if (j < 4)
                                {
                                    blendWeights[j] = blendWeightsList[j];
                                }
                            }

                            skinnedVertices.Add(new SkinnedVertex
                            {
                                Position     = new RealQuaternion(position.X, position.Y, position.Z, 1),
                                Texcoord     = new RealVector2d(uv.X, -uv.Y),
                                Normal       = new RealVector3d(normal.X, normal.Y, normal.Z),
                                Tangent      = new RealQuaternion(tangent.X, tangent.Y, tangent.Z, 1),
                                Binormal     = new RealVector3d(bitangent.X, bitangent.Y, bitangent.Z),
                                BlendIndices = blendIndices,
                                BlendWeights = blendWeights
                            });
                        }
                        else
                        {
                            rigidVertices.Add(new RigidVertex
                            {
                                Position = new RealQuaternion(position.X, position.Y, position.Z, 1),
                                Texcoord = new RealVector2d(uv.X, -uv.Y),
                                Normal   = new RealVector3d(normal.X, normal.Y, normal.Z),
                                Tangent  = new RealQuaternion(tangent.X, tangent.Y, tangent.Z, 1),
                                Binormal = new RealVector3d(bitangent.X, bitangent.Y, bitangent.Z),
                            });
                        }
                    }

                    // Build the index buffer
                    var meshIndices = mesh.GetIndices();
                    indices.AddRange(meshIndices.Select(i => (ushort)(i + partStartVertex)));

                    // Define a material and part for this mesh
                    var material = builder.AddMaterial(new RenderMaterial
                    {
                        RenderMethod = Cache.TagCache.GetTag(@"shaders\invalid", "rmsh"),
                    });

                    builder.BeginPart(material, partStartIndex, (ushort)meshIndices.Length, (ushort)mesh.VertexCount);
                    builder.DefineSubPart(partStartIndex, (ushort)meshIndices.Length, (ushort)mesh.VertexCount);
                    builder.EndPart();

                    // Move to the next part
                    partStartVertex += (ushort)mesh.VertexCount;
                    partStartIndex  += (ushort)meshIndices.Length;

                    // Bind the vertex and index buffers
                    if (vertexType == "skinned")
                    {
                        builder.BindSkinnedVertexBuffer(skinnedVertices);
                    }
                    else
                    {
                        builder.BindRigidVertexBuffer(rigidVertices, rigidNode);
                    }

                    builder.BindIndexBuffer(indices, IndexBufferFormat.TriangleList);
                    builder.EndMesh();
                    builder.EndPermutation();
                    builder.EndRegion();
                }
            }

            Console.Write("Building render_geometry...");

            var resourceStream = new MemoryStream();
            var renderModel    = builder.Build(Cache.Serializer, resourceStream);

            if (vertexType == "skinned")
            {
                // Copy required data from the original render_model tag
                renderModel.Nodes                   = edMode.Nodes;
                renderModel.MarkerGroups            = edMode.MarkerGroups;
                renderModel.RuntimeNodeOrientations = edMode.RuntimeNodeOrientations;
            }

            Console.WriteLine("done.");


            //
            // Serialize the new render_model tag
            //

            Console.Write("Writing render_model tag data...");

            using (var cacheStream = Cache.OpenCacheReadWrite())
                Cache.Serialize(cacheStream, destinationTag, renderModel);

            Console.WriteLine("done.");

            //
            // Save any new string ids
            //

            if (stringIdCount != Cache.StringTable.Count)
            {
                Console.Write("Saving string ids...");


                Cache.SaveStrings();

                Console.WriteLine("done");
            }

            Console.WriteLine("Model imported successfully!");

            return(true);
        }
예제 #15
0
        static int nullBonesC = 0;         //TODO remove this counter

        public static void Main(string[] args)
        {
            //Dir
            if (Directory.Exists("./obj"))
            {
                Console.WriteLine("Directory Found");
            }
            else
            {
                printError("Creating Dir");
                Directory.CreateDirectory("./obj");
            }

            //File Input
            string fileName = "./obj/" + getUserInput("File name");

            if (fileName == "./obj/")
            {
                string[] possibleFiles = Directory.GetFiles("./obj");
                foreach (string currFileName in possibleFiles)
                {
                    if (!currFileName.EndsWith(".txt") && !currFileName.EndsWith(".js"))
                    {
                        fileName = currFileName;
                        break;
                    }
                }
            }
            else
            {
                string[] possibleFiles = Directory.GetFiles("./obj");
                foreach (string currFileName in possibleFiles)
                {
                    if (!currFileName.Contains("fileName"))
                    {
                        fileName = currFileName;
                        break;
                    }
                }
            }

            Console.WriteLine("Files found, starting to read them");

            try { File.Delete("./obj/output.txt"); }
            catch (Exception e)
            {
                printError("No file to delete, ignore this error" + e);
            }
            //Create a new importer
            AssimpContext importer = new AssimpContext();

            importer.SetConfig(new IFCUseCustomTriangulationConfig(true));

            importer.SetConfig(new SortByPrimitiveTypeConfig(PrimitiveType.Line | PrimitiveType.Point));
            importer.SetConfig(new VertexBoneWeightLimitConfig(4));
            //This is how we add a configuration (each config is its own class)
            //NormalSmoothingAngleConfig config = new NormalSmoothingAngleConfig(66.0f);
            //importer.SetConfig(config);

            //This is how we add a logging callback
            LogStream logstream = new LogStream(delegate(String msg, String userData)
            {
                Console.WriteLine(msg);
            });

            logstream.Attach();

            //Import the model. All configs are set. The model
            //is imported, loaded into managed memory. Then the unmanaged memory is released, and everything is reset.
            //Triangulating is already being done
            //TODO aiProcess_JoinIdenticalVertices (Index buffer objects)
            scene = importer.ImportFile(fileName, PostProcessPreset.TargetRealTimeMaximumQuality | PostProcessSteps.FlipUVs | PostProcessSteps.OptimizeMeshes | PostProcessSteps.OptimizeGraph | PostProcessSteps.SortByPrimitiveType | PostProcessSteps.LimitBoneWeights);

            extractBones(scene.RootNode);
            createBoneTree(scene.RootNode, -1, Matrix4x4.Identity);

            parseNode(scene.RootNode);
            //End of example
            importer.Dispose();
            adjVert = (Lookup <Vector3D, triAndVertIndex>)toLookup.ToLookup((item) => item.Key, (item) => item.Value);

            //First 3 => Point, Second 3 => Line
            //TODO Make this a bit better
            //For each triangle, store some bary coords
            Bary[] bary = new Bary[normals.Count];             //Filled with: default( int )
            //Edit

            #region Bary coords and bones
            //Lines:
            for (int j = 0; j < toLookup.Count; j += 3)
            {
                Vector3D v0   = toLookup[j + 2].Key - toLookup[j + 1].Key;
                Vector3D v1   = toLookup[j + 2].Key - toLookup[j].Key;
                Vector3D v2   = toLookup[j + 1].Key - toLookup[j].Key;
                double   area = Math.Abs(Vector3D.Cross(v1, v2).Length()) / 2;               //Determinant of a 2D matrix, used to calculate the area of a parallelogram


                IEnumerable <triAndVertIndex> matchingVertices0 = adjVert[toLookup[j].Key];
                IEnumerable <triAndVertIndex> matchingVertices1 = adjVert[toLookup[j + 1].Key];
                IEnumerable <triAndVertIndex> matchingVertices2 = adjVert[toLookup[j + 2].Key];
                //2 Matching points
                //TriIndex = triangle index of the adjacent triangle
                foreach (triAndVertIndex index in matchingVertices0)
                {
                    //Oh, yeah! It's working! (Magic!)
                    //TODO turn this into a function as well
                    foreach (triAndVertIndex otherIndex in matchingVertices1)
                    {
                        //If it is part of the same line
                        if (otherIndex.triIndex == index.triIndex)
                        {
                            double angleBetweenTriangles = (Vector3D.Dot(faceNormals[j / 3], faceNormals[otherIndex.triIndex]));
                            if (angleBetweenTriangles < THRESHOLD)
                            {
                                //area = 1/2*base*height
                                //2*area / base = height

                                /*
                                 * dist = vec3(area / v0.Length(), 0, 0);
                                 * gl_Position = gl_PositionIn[0];
                                 * EmitVertex();
                                 * dist = vec3(0, area / v1.Length(), 0);
                                 * gl_Position = gl_PositionIn[1];
                                 * EmitVertex();
                                 * dist = vec3(0, 0, area / v2.Length());
                                 * gl_Position = gl_PositionIn[2];
                                 * EmitVertex();*/
                                bary[j / 3].l2 = area / v2.Length();                                 // 1;// angleBetweenTriangles + addTo;
                            }
                            //If we found the adjacent triangle, we can go to the next one
                            break;
                        }
                    }
                }
                foreach (triAndVertIndex index in matchingVertices1)
                {
                    foreach (triAndVertIndex otherIndex in matchingVertices2)
                    {
                        if (otherIndex.triIndex == index.triIndex)
                        {
                            double angleBetweenTriangles = (Vector3D.Dot(faceNormals[j / 3], faceNormals[otherIndex.triIndex]));
                            if (angleBetweenTriangles < THRESHOLD)
                            {
                                bary[j / 3].l0 = area / v0.Length();                                // TODO angleBetweenTriangles + addTo;
                            }
                            break;
                        }
                    }
                }
                foreach (triAndVertIndex index in matchingVertices2)
                {
                    foreach (triAndVertIndex otherIndex in matchingVertices0)
                    {
                        if (otherIndex.triIndex == index.triIndex)
                        {
                            double angleBetweenTriangles = (Vector3D.Dot(faceNormals[j / 3], faceNormals[otherIndex.triIndex]));
                            if (angleBetweenTriangles < THRESHOLD)
                            {
                                bary[j / 3].l1 = area / v1.Length();                                // TODO angleBetweenTriangles + addTo;
                            }
                            break;
                        }
                    }
                }
            }

            //Draw the points as well
            for (int j = 0; j < toLookup.Count; j += 3)
            {
                Vector3D v0   = toLookup[j + 2].Key - toLookup[j + 1].Key;
                Vector3D v1   = toLookup[j + 2].Key - toLookup[j].Key;
                Vector3D v2   = toLookup[j + 1].Key - toLookup[j].Key;
                double   area = Math.Abs(Vector3D.Cross(v1, v2).Length()) / 2;               //Determinant of a 2D matrix, used to calculate the area of a parallelogram


                IEnumerable <triAndVertIndex> matchingVertices0 = adjVert[toLookup[j].Key];
                IEnumerable <triAndVertIndex> matchingVertices1 = adjVert[toLookup[j + 1].Key];
                IEnumerable <triAndVertIndex> matchingVertices2 = adjVert[toLookup[j + 2].Key];

                /*int numberOfAdjBary = 0;
                 *
                 * //Index of the adjacent triangle
                 * foreach (triAndVertIndex index in matchingVertices0)
                 * {
                 *      //TODO turn this into a function as well
                 *      if ((bary[index.triIndex], ((index.vertIndex + 1) % 3) + 3] > 0 || bary[index.triIndex, ((index.vertIndex + 2) % 3) + 3] > 0)
                 *              && index.triIndex != j / 3)
                 *      {
                 *              numberOfAdjBary++;
                 *      }
                 * }
                 * //Every line is actually 2 lines
                 * if (numberOfAdjBary >= 4)
                 * {
                 *      //Now, we need to do the point calculations
                 *      double dist0 = area / v0.Length();
                 *      //bary[j / 3, 0] = ;
                 * }
                 * numberOfAdjBary = 0;
                 * foreach (triAndVertIndex index in matchingVertices1)
                 * {
                 *      if ((bary[index.triIndex, ((index.vertIndex + 1) % 3) + 3] > 0 || bary[index.triIndex, ((index.vertIndex + 2) % 3) + 3] > 0)
                 *              && index.triIndex != j / 3)
                 *      {
                 *              numberOfAdjBary++;
                 *      }
                 * }
                 * if (numberOfAdjBary >= 4)
                 * {
                 *      bary[j / 3, 1] = area / v1.Length();
                 * }
                 * numberOfAdjBary = 0;
                 * foreach (triAndVertIndex index in matchingVertices2)
                 * {
                 *      if ((bary[index.triIndex, ((index.vertIndex + 1) % 3) + 3] > 0 || bary[index.triIndex, ((index.vertIndex + 2) % 3) + 3] > 0)
                 *              && index.triIndex != j / 3)
                 *      {
                 *              numberOfAdjBary++;
                 *      }
                 * }
                 * if (numberOfAdjBary >= 4)
                 * {
                 *      bary[j / 3, 2] = area / v2.Length();
                 * }***/
            }
            #endregion
#if true
            //Create the output file
            StreamWriter JSONFile = File.CreateText("./obj/output.txt");
            //Write to file
            JSONFile.Write("model = [");
            bool firstTime = true;
            for (int j = 0, texCount = 0; j < vertices.Count; j++)
            {
                var        index    = j - texCount;
                Vector3D[] currVert = Program.vertices[j];
                if (currVert.Length == 1)
                {
                    if (firstTime)
                    {
                        JSONFile.Write("{");
                        firstTime = false;
                    }
                    else
                    {
                        JSONFile.Write("]},\n{");
                    }
                    JSONFile.Write("name:\"" + texNames[(int)currVert[0].X] + "\",model:[");
                    Console.Write(texNames[(int)currVert[0].X] + "---");
                    texCount++;
                }
                else
                {
                    //Edit
                    string[] baryCoordsOfTri = toBary(bary[index]);
                    //Triangle
                    for (int i = 0; i < 3; i++)
                    {
                        JSONFile.Write(Vec3DToString(currVert[i]));
                        JSONFile.Write(UVToString(uvs[index][i]));
                        JSONFile.Write(Vec3DToString(normals[index][i]));

                        JSONFile.Write(baryCoordsOfTri[i]);
                        bones[index][i].Weights[1] = 0;
                        if (bones[index][i].BoneIDs[1] == -1)
                        {
                            bones[index][i].Weights[0] = 1;
                        }
                        if (bones[index][i].Weights[0] == 0.5)
                        {
                            bones[index][i].Weights[0] = 0.49f;
                        }
                        JSONFile.Write((bones[index][i].BoneIDs[0] + 0.5) + "," + (bones[index][i].BoneIDs[1] + 0.5)
                                       + "," + bones[index][i].Weights[0] + ",");

                        if (bones[index][i].Weights[0] > 0.45 && bones[index][i].Weights[0] < 0.55)
                        {
                            //printError("W1: " + string.Join(",.,", bones[index][i].Weights));
                        }

                        if (bones[index][i].Weights[0] > 0.9)
                        {
                            //printError("W1: " + string.Join(",.,", bones[index][i].Weights));
                        }
                    }
                }
            }


            JSONFile.Write("]}];");
            JSONFile.Close();
#endif

            StreamWriter bonesFile = File.CreateText("./obj/outputBones.txt");
            //You are going to have to reorder the parts manually
            bonesFile.Write("bones = [");

            foreach (BoneInfo boneNode in boneNodesList)
            {
                //TODO Number of bones (To nearest power of 2)
                //TODO Max number of influencing bones per vertex
                Quaternion rot, offsetRot;
                Vector3D   translation, offsetTranslation;
                Vector3D   scale, offsetScale;
                boneNode.localMat.Decompose(out scale, out rot, out translation);

                boneNode.BoneOffsetMatrix.Decompose(out offsetScale, out offsetRot, out offsetTranslation);
                //Console.WriteLine(QuaternionToString(rot) + "->\n" + MatToString1(rot.GetMatrix()));
                //Console.WriteLine(QuaternionToString(rot) + "->\n" + Matrix4x4.FromTranslation(translation));

                //Don't use .ToString(), use a custom function!
                bonesFile.WriteLine(
                    "{name:\"" + boneNode.Name + "\",parent:" + boneNode.Parent +
                    ",pos:[" + Vec3DToString(translation, false) + "],qRot:[" + QuaternionToString(rot) + "],offsetPos:["
                    + Vec3DToString(offsetTranslation, false) + "],offsetRot:[" + QuaternionToString(offsetRot) + "]},");
            }

            bonesFile.Write("];");
            bonesFile.WriteLine("\nvar animations = [];");
            bonesFile.Close();

            try { File.Delete("./obj/output.js"); } catch (Exception) { };
            try { File.Delete("./obj/outputBones.js"); } catch (Exception) { };
            try { File.Move("./obj/output.txt", Path.ChangeExtension("./obj/output.txt", ".js")); } catch (Exception) { };
            try { File.Move("./obj/outputBones.txt", Path.ChangeExtension("./obj/outputBones.txt", ".js")); } catch (Exception) { };

            Console.WriteLine("Info: {0} Bones    {1} vertices without bones", boneNodesList.Count, nullBonesC);
            Console.WriteLine("DONE!");
            Console.Read();
        }