Пример #1
0
 public ModelLoader(Device device, TextureLoadHandler textureLoadHandler)
 {
     _device             = device;
     _textureLoadHandler = textureLoadHandler;
     _importer           = new AssimpImporter();
     _importer.SetConfig(new NormalSmoothingAngleConfig(66.0f));
 }
Пример #2
0
		public SimpleOpenGLSample() : base() {
			Title = "Quack! - Assimp.NET Simple OpenGL Sample";

			String fileName = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "duck.dae");

			AssimpImporter importer = new AssimpImporter();
			importer.SetConfig(new NormalSmoothingAngleConfig(66.0f));
			m_model = importer.ImportFile(fileName, PostProcessPreset.TargetRealTimeMaximumQuality);
			ComputeBoundingBox();
		}
Пример #3
0
        public SimpleOpenGLSample() : base()
        {
            Title = "Quack! - Assimp.NET Simple OpenGL Sample";

            String fileName = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "duck.dae");

            AssimpImporter importer = new AssimpImporter();

            importer.SetConfig(new NormalSmoothingAngleConfig(66.0f));
            m_model = importer.ImportFile(fileName, PostProcessPreset.TargetRealTimeMaximumQuality);
            ComputeBoundingBox();
        }
Пример #4
0
        private Scene LoadDaeScene(String path)
        {
            Scene scene;

            using (var importer = new AssimpImporter())
            {
                importer.SetConfig(new NormalSmoothingAngleConfig(66.0f));
                scene = importer.ImportFile(path, PostProcessPreset.TargetRealTimeMaximumQuality);
            }

            return(scene);
        }
Пример #5
0
        private ContentCompilerResult CompileFromFileInternal(string fileName, ModelCompilerOptions compilerOptions)
        {
            logger = new Logger();
            var result = new ContentCompilerResult()
            {
                Logger = logger
            };

            modelFilePath  = fileName;
            modelDirectory = Path.GetDirectoryName(modelFilePath);

            // Preload AssimpLibrary if not already loaded
            if (!AssimpLibrary.Instance.LibraryLoaded)
            {
                var rootPath = Path.GetDirectoryName(typeof(AssimpLibrary).Assembly.Location);
                AssimpLibrary.Instance.LoadLibrary(Path.Combine(rootPath, AssimpLibrary.Instance.DefaultLibraryPath32Bit), Path.Combine(rootPath, AssimpLibrary.Instance.DefaultLibraryPath64Bit));
            }

            var importer = new AssimpImporter();

            importer.SetConfig(new Assimp.Configs.MaxBoneCountConfig(72));
            //importer.SetConfig(new NormalSmoothingAngleConfig(66.0f));

            // Steps for Direct3D Right-Handed, should we make this configurable?
            var steps = PostProcessSteps.FlipUVs | PostProcessSteps.FlipWindingOrder | PostProcessSteps.LimitBoneWeights | PostProcessSteps.SplitByBoneCount;

            // Setup quality
            switch (compilerOptions.Quality)
            {
            case ModelRealTimeQuality.Low:
                steps |= PostProcessPreset.TargetRealTimeFast;
                break;

            case ModelRealTimeQuality.Maximum:
                steps |= PostProcessPreset.TargetRealTimeMaximumQuality;
                break;

            default:
                steps |= PostProcessPreset.TargetRealTimeQuality;
                break;
            }

            scene = importer.ImportFile(fileName, steps);
            model = new ModelData();
            ProcessScene();

            result.IsContentGenerated = true;
            result.ModelData          = model;

            return(result);
        }
Пример #6
0
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Console.WriteLine("Usage: ModelCompiler.exe model.dae");
                return;
            }

            foreach (string filename in args)
            {
                AssimpImporter   importer = new AssimpImporter();
                PostProcessSteps steps    = PostProcessPreset.TargetRealTimeMaximumQuality;
                steps |= PostProcessSteps.OptimizeMeshes | PostProcessSteps.SplitLargeMeshes | PostProcessSteps.Triangulate
                         | PostProcessSteps.FlipUVs | PostProcessSteps.LimitBoneWeights;
                importer.SetConfig(new VertexBoneWeightLimitConfig(2));
                Scene scene = importer.ImportFile(filename, steps);

                Vector3D bbMin = new Vector3D(float.MaxValue, float.MaxValue, float.MaxValue);
                Vector3D bbMax = new Vector3D(float.MinValue, float.MinValue, float.MinValue);

                Node meshNode = scene.RootNode;

                while (!meshNode.HasMeshes)
                {
                    meshNode = meshNode.Children[0];
                }

                Mesh            nodeGeometry        = scene.Meshes[meshNode.MeshIndices[0]];
                List <Vector3D> transformedVertices = new List <Vector3D>();

                foreach (Vector3D vertex in nodeGeometry.Vertices)
                {
                    Vector4 tempv = new Vector4(vertex.X, vertex.Y, vertex.Z, 1.0f);
                    Matrix  tempm = Matrix.Scaling(0.1f) * Matrix.RotationYawPitchRoll(((float)Math.PI / 2.0f), ((float)Math.PI / 2.0f), 0.0f) *
                                    new Matrix(meshNode.Transform.A1, meshNode.Transform.A2, meshNode.Transform.A3, meshNode.Transform.A3,
                                               meshNode.Transform.B1, meshNode.Transform.B2, meshNode.Transform.B3, meshNode.Transform.B3,
                                               meshNode.Transform.C1, meshNode.Transform.C2, meshNode.Transform.C3, meshNode.Transform.C3,
                                               meshNode.Transform.D1, meshNode.Transform.D2, meshNode.Transform.D3, meshNode.Transform.D3);
                    Vector4 finalvec = Vector4.Transform(tempv, tempm);

                    transformedVertices.Add(new Vector3D(finalvec.X, finalvec.Y, finalvec.Z));
                }

                using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(filename + ".mdl")))
                {
                    foreach (Vector3D vector in transformedVertices)
                    {
                        bbMin.X = Math.Min(vector.X, bbMin.X);
                        bbMin.Y = Math.Min(vector.Y, bbMin.Y);
                        bbMin.Z = Math.Min(vector.Z, bbMin.Z);

                        bbMax.X = Math.Max(vector.X, bbMax.X);
                        bbMax.Y = Math.Max(vector.Y, bbMax.Y);
                        bbMax.Z = Math.Max(vector.Z, bbMax.Z);
                    }

                    writer.Write(bbMin.X);
                    writer.Write(bbMin.Y);
                    writer.Write(bbMin.Z);

                    writer.Write(bbMax.X);
                    writer.Write(bbMax.Y);
                    writer.Write(bbMax.Z);

                    //writer.Write(scene.Meshes.Length);
                    writer.Write(1);

                    Mesh currentMesh = nodeGeometry;

                    if (!currentMesh.HasTextureCoords(0))
                    {
                        Console.WriteLine("ERROR: model must have texture coordinates");
                        return;
                    }

                    Vector3D[] texCoords = currentMesh.GetTextureCoords(0);

                    writer.Write(currentMesh.VertexCount);

                    for (int j = 0; j < currentMesh.VertexCount; j++)
                    {
                        writer.Write(transformedVertices[j].X);
                        writer.Write(transformedVertices[j].Y);
                        writer.Write(transformedVertices[j].Z);

                        writer.Write(texCoords[j].X);
                        writer.Write(texCoords[j].Y);
                    }

                    writer.Write(currentMesh.Faces.Length * 3);
                    for (int j = 0; j < currentMesh.Faces.Length; j++)
                    {
                        Face currentFace = currentMesh.Faces[j];

                        if (currentFace.IndexCount != 3)
                        {
                            Console.WriteLine("ERROR: non-triangle found!");
                            Console.ReadKey();
                            return;
                        }

                        foreach (uint index in currentFace.Indices)
                        {
                            writer.Write((int)index);
                        }
                    }

                    //writer.Write(currentMesh.Faces.Length * 3);
                    //for (int j = 0; j < currentMesh.Faces.Length; j++)
                    //{
                    //    Face currentFace = currentMesh.Faces[j];

                    //    if (currentFace.IndexCount != 3)
                    //    {
                    //        Console.WriteLine("ERROR: non-triangle found!");
                    //        Console.ReadKey();
                    //        return;
                    //    }

                    //    foreach (uint index in currentFace.Indices)
                    //    {
                    //        writer.Write(transformedVertices[(int)index].X);
                    //        writer.Write(transformedVertices[(int)index].Y);
                    //        writer.Write(transformedVertices[(int)index].Z);

                    //        writer.Write(texCoords[index].X);
                    //        writer.Write(texCoords[index].Y);
                    //    }
                    //}
                }
            }
        }
        public void TestImportFromFile()
        {
            String path = Path.Combine(TestHelper.RootPath, "TestFiles\\sphere.obj");

            AssimpImporter importer = new AssimpImporter();

            importer.SetConfig(new NormalSmoothingAngleConfig(55.0f));
            importer.Scale = .5f;
            importer.XAxisRotation = 25.0f;
            importer.YAxisRotation = 50.0f;
            importer.VerboseLoggingEnabled = true;

            Assert.IsTrue(importer.ContainsConfig(NormalSmoothingAngleConfig.NormalSmoothingAngleConfigName));

            importer.RemoveConfigs();

            Assert.IsFalse(importer.ContainsConfig(NormalSmoothingAngleConfig.NormalSmoothingAngleConfigName));

            importer.SetConfig(new NormalSmoothingAngleConfig(65.0f));
            importer.SetConfig(new NormalSmoothingAngleConfig(22.5f));
            importer.RemoveConfig(NormalSmoothingAngleConfig.NormalSmoothingAngleConfigName);

            Assert.IsFalse(importer.ContainsConfig(NormalSmoothingAngleConfig.NormalSmoothingAngleConfigName));

            importer.SetConfig(new NormalSmoothingAngleConfig(65.0f));

            Scene scene = importer.ImportFile(path, PostProcessPreset.TargetRealTimeMaximumQuality);

            Assert.IsNotNull(scene);
            Assert.IsTrue((scene.SceneFlags & SceneFlags.Incomplete) != SceneFlags.Incomplete);
        }
        private void LoadSceneB()
        {
            Console.WriteLine("Thread B: Starting import.");
            AssimpImporter importer = new AssimpImporter();
            String path = Path.Combine(TestHelper.RootPath, "TestFiles\\duck.dae");

            importer.AttachLogStream(new ConsoleLogStream("Thread B:"));
            importer.SetConfig(new NormalSmoothingAngleConfig(55.0f));
            Console.WriteLine("Thread B: Importing");
            Scene scene = importer.ImportFile(path);
            Console.WriteLine("Thread B: Done importing");
        }
        private void ConvertSceneC()
        {
            Console.WriteLine("Thread C: Starting convert.");
            AssimpImporter importer = new AssimpImporter();
            String path = Path.Combine(TestHelper.RootPath, "TestFiles\\duck.dae");
            String outputPath = Path.Combine(TestHelper.RootPath, "TestFiles\\duck2.obj");

            importer.AttachLogStream(new ConsoleLogStream("Thread C:"));
            importer.SetConfig(new NormalSmoothingAngleConfig(55.0f));
            importer.SetConfig(new FavorSpeedConfig(true));
            importer.VerboseLoggingEnabled = true;

            Console.WriteLine("Thread C: Converting");
            ExportDataBlob blob = importer.ConvertFromFileToBlob(path, "obj");

            Console.WriteLine("Thread C: Done converting");
        }
Пример #10
0
 public ModelLoader(Device device)
 {
     m_device   = device;
     m_importer = new AssimpImporter();
     m_importer.SetConfig(new NormalSmoothingAngleConfig(66.0f));
 }
Пример #11
0
        public override NodeContent Import(string filename, ContentImporterContext context)
        {
            ContentIdentity identity = new ContentIdentity(filename, GetType().Name);

            const int MAX_BONE_WEIGHTS             = 4;
            VertexBoneWeightLimitConfig boneConfig = new VertexBoneWeightLimitConfig(MAX_BONE_WEIGHTS);

            AssimpImporter importer = new AssimpImporter();

            importer.SetConfig(boneConfig);

            importer.AttachLogStream(new LogStream((msg, userData) => context.Logger.LogMessage(msg)));
            Scene scene = importer.ImportFile(filename,
                                              PostProcessSteps.FlipUVs |
                                              PostProcessSteps.JoinIdenticalVertices |
                                              PostProcessSteps.Triangulate |
                                              PostProcessSteps.SortByPrimitiveType |
                                              PostProcessSteps.FindInvalidData |
                                              PostProcessSteps.LimitBoneWeights |
                                              PostProcessSteps.FixInFacingNormals);


            // Root node
            NodeContent rootNode = new NodeContent
            {
                Name      = scene.RootNode.Name,
                Identity  = identity,
                Transform = Matrix.Transpose(ToXna(scene.RootNode.Transform))
            };


            // Materials
            MaterialContent[] materials = new MaterialContent[scene.MaterialCount];

            for (int m = 0; m < scene.MaterialCount; m++)
            {
                materials[m] = new BasicMaterialContent();

                materials[m].Identity = identity;
                // For some reason, there is all kinds of nasty junk in this string:
                materials[m].Name = CleanInput(scene.Materials[m].Name);

                for (int t = 0; t < scene.Materials[m].GetTextureCount(TextureType.Diffuse); t++)
                {
                    TextureSlot diffuseMap = scene.Materials[m].GetTexture(TextureType.Diffuse, t);
                    if (!String.IsNullOrEmpty(diffuseMap.FilePath))
                    {
                        materials[m].Textures.Add("Texture" + (t > 0 ? t.ToString() : ""),
                                                  new ExternalReference <TextureContent>(diffuseMap.FilePath, identity));
                    }
                }
            }


            // Bones

            // We find 'mesh container' nodes with the best names for those meshes while looking for the bones,
            // and will need them later when we create the MeshContents. I have a feeling that this won't work
            // in general, and may need to be made more robust.
            Dictionary <Mesh, string>      meshNames     = new Dictionary <Mesh, string>();
            Dictionary <Node, BoneContent> nodeToBoneMap = new Dictionary <Node, BoneContent>();
            BoneContent skeleton = null;    // The root bone for the model.

            List <Node> hierarchyNodes = scene.RootNode.Children.SelectDeep(n => n.Children).ToList();

            foreach (Node node in hierarchyNodes)
            {
                BoneContent bone = new BoneContent
                {
                    Name      = node.Name,
                    Transform = Matrix.Transpose(ToXna(node.Transform))
                };


                if (node.MeshIndices != null)
                {
                    // This node is a 'mesh container' instead of a bone, so we only care about extracting the name of the mesh.
                    foreach (int meshIndex in node.MeshIndices)
                    {
                        if (!meshNames.ContainsKey(scene.Meshes[meshIndex]))
                        {
                            meshNames.Add(scene.Meshes[meshIndex], node.Name);
                        }
                    }
                }
                else if (node.Parent == scene.RootNode)
                {
                    if (skeleton == null)
                    {
                        // This will be our skeleton so put the animations here:
                        if (scene.HasAnimations)
                        {
                            foreach (Animation assimpAnim in scene.Animations)
                            {
                                if (assimpAnim.HasNodeAnimations)
                                {
                                    AnimationContent newAnim = new AnimationContent();
                                    newAnim.Identity = identity;
                                    newAnim.Duration = TimeSpan.FromSeconds(assimpAnim.DurationInTicks / assimpAnim.TicksPerSecond);
                                    newAnim.Name     = assimpAnim.Name;

                                    foreach (NodeAnimationChannel nac in assimpAnim.NodeAnimationChannels)
                                    {
                                        Node animatedNode = hierarchyNodes.Find(n => n.Name == nac.NodeName);

                                        AnimationChannel newChan = BuildAnimtionChannel(animatedNode, nac);

                                        newAnim.Channels.Add(nac.NodeName, newChan);
                                    }

                                    if (String.IsNullOrEmpty(assimpAnim.Name))
                                    {
                                        bone.Animations.Add("SkelematorNoAnimationName", newAnim);
                                    }
                                    else
                                    {
                                        bone.Animations.Add(assimpAnim.Name, newAnim);
                                    }
                                }
                            }
                        }
                        rootNode.Children.Add(bone);
                        skeleton = bone;
                    }
                    else
                    {
                        context.Logger.LogWarning(null, identity, "Found multiple skeletons in the model, throwing extras away...");
                    }
                }
                else
                {
                    BoneContent parent = nodeToBoneMap[node.Parent];
                    parent.Children.Add(bone);
                }

                nodeToBoneMap.Add(node, bone);
            }


            // Meshes
            Dictionary <Mesh, MeshContent> meshes = new Dictionary <Mesh, MeshContent>();

            foreach (Mesh sceneMesh in scene.Meshes)
            {
                // See comment about meshNames at the beginning of the bone section.
                MeshBuilder mb = MeshBuilder.StartMesh(meshNames[sceneMesh]);

                mb.SwapWindingOrder = true; // Appears to require this...

                int positionIndex = -1;

                for (int v = 0; v < sceneMesh.VertexCount; v++)
                {
                    Vector3D vert = sceneMesh.Vertices[v];

                    // CreatePosition should just return a 0-based index of the newly added vertex.
                    positionIndex = mb.CreatePosition(new Vector3(vert.X, vert.Y, vert.Z));

                    if (positionIndex != v)
                    {
                        throw new InvalidContentException("Something unexpected happened while building a MeshContent from the Assimp scene mesh's vertices.  The scene mesh may contains duplicate vertices.");
                    }
                }

                if (positionIndex + 1 < 3)
                {
                    throw new InvalidContentException("There were not enough vertices in the Assimp scene mesh.");
                }



                // Create vertex channels
                int normalVertexChannelIndex = mb.CreateVertexChannel <Vector3>(VertexChannelNames.Normal());

                int[] texCoordVertexChannelIndex = new int[sceneMesh.TextureCoordsChannelCount];
                for (int x = 0; x < sceneMesh.TextureCoordsChannelCount; x++)
                {
                    texCoordVertexChannelIndex[x] = mb.CreateVertexChannel <Vector2>(VertexChannelNames.TextureCoordinate(x));
                }

                int boneWeightVertexChannelIndex = -1;

                if (sceneMesh.HasBones)
                {
                    boneWeightVertexChannelIndex = mb.CreateVertexChannel <BoneWeightCollection>(VertexChannelNames.Weights());
                }


                // Prepare vertex channel data
                BoneWeightCollection[] boneWeightData = null;
                if (sceneMesh.HasBones)
                {
                    boneWeightData = new BoneWeightCollection[sceneMesh.VertexCount];

                    for (int v = 0; v < sceneMesh.VertexCount; v++)
                    {
                        boneWeightData[v] = new BoneWeightCollection();
                    }

                    foreach (Bone sceneMeshBone in sceneMesh.Bones)
                    {
                        // We have to assume that the bone's name matches up with a node, and therefore one of our BoneContents.
                        foreach (VertexWeight sceneMeshBoneWeight in sceneMeshBone.VertexWeights)
                        {
                            boneWeightData[sceneMeshBoneWeight.VertexID].Add(new BoneWeight(sceneMeshBone.Name, sceneMeshBoneWeight.Weight));
                        }
                    }

                    for (int v = 0; v < sceneMesh.VertexCount; v++)
                    {
                        if (boneWeightData[v].Count <= 0)
                        {
                            throw new InvalidContentException("Encountered vertices without bone weights.");
                        }

                        boneWeightData[v].NormalizeWeights();
                    }
                }

                // Set the per-geometry data
                mb.SetMaterial(materials[sceneMesh.MaterialIndex]);
                mb.SetOpaqueData(new OpaqueDataDictionary());

                // Add each vertex
                for (int f = 0; f < sceneMesh.FaceCount; f++)
                {
                    if (sceneMesh.Faces[f].IndexCount != 3)
                    {
                        throw new InvalidContentException("Only triangular faces allowed.");
                    }

                    for (int t = 0; t < 3; t++)
                    {
                        mb.SetVertexChannelData(normalVertexChannelIndex, ToXna(sceneMesh.Normals[sceneMesh.Faces[f].Indices[t]]));

                        for (int x = 0; x < sceneMesh.TextureCoordsChannelCount; x++)
                        {
                            mb.SetVertexChannelData(texCoordVertexChannelIndex[x], ToXnaVector2((sceneMesh.GetTextureCoords(x))[sceneMesh.Faces[f].Indices[t]]));
                        }

                        if (sceneMesh.HasBones)
                        {
                            mb.SetVertexChannelData(boneWeightVertexChannelIndex, boneWeightData[sceneMesh.Faces[f].Indices[t]]);
                        }

                        mb.AddTriangleVertex((int)(sceneMesh.Faces[f].Indices[t]));
                    }
                }

                MeshContent mesh = mb.FinishMesh();
                rootNode.Children.Add(mesh);
                meshes.Add(sceneMesh, mesh);
            }

            return(rootNode);
        }