public void importmodel() { //string fileName = "F:/UNITY stuff/FlexHub/FlexHub_parts/FBX-Parts_FlexHub/Part_72.fbx"; allnodes.Clear(); //Create a new importer AssimpImporter importer = new AssimpImporter(); // create an importer instance //importer.SetConfig (new con) Scene model = importer.ImportFile(filetoImport, //import hte specified file PostProcessSteps.JoinIdenticalVertices | PostProcessSteps.FindInvalidData | PostProcessSteps.RemoveRedundantMaterials | PostProcessSteps.FixInFacingNormals ); Debug.Log(model.RootNode.Name + "\n" + "-----------------------------"); // get the root node name MasterNode = model.RootNode; // get the master node of the scene GameObject gobject = convertNodes(MasterNode); // call the function and pass the resulting GO to a new GO //int count = gobject.transform.childCount; //for(int i = 0; i < count; i++) //{ // Transform obj = gobject.transform.GetChild(i); // Debug.Log(obj.name); //} importer.Dispose(); // diacard the importer when importing is done }
public void importmodel() { //string fileName = "F:/UNITY stuff/FlexHub/FlexHub_parts/FBX-Parts_FlexHub/Part_72.fbx"; allnodes.Clear(); //Create a new importer importer = new AssimpImporter(); // create an importer instance //importer.SetConfig (new con) model = importer.ImportFile(filetoImport //import the specified file //PostProcessSteps.JoinIdenticalVertices | //PostProcessSteps.FindInvalidData | //PostProcessSteps.RemoveRedundantMaterials | //PostProcessSteps.FixInFacingNormals ); Debug.Log(model.RootNode.Name + "\n" + "-----------------------------"); // get the root node name MasterNode = model.RootNode; // get the master node of the scene meshesinmodel = model.Meshes; GameObject gobject = convertNodes(MasterNode); // call the function and pass the resulting GO to a new GO importer.Dispose(); // diacard the importer when importing is done }
public AssimpModelLoader(string modelFilePath, SkeletonPerVertexBoneInfluenceType skeletonType = SkeletonPerVertexBoneInfluenceType.ThreeBones) { m_skeletonType = skeletonType; var importer = new AssimpImporter(); m_scene = importer.ImportFile(modelFilePath, PostProcessSteps.FlipUVs | PostProcessSteps.CalculateTangentSpace); }
public void importmodel() { //string fileName = "F:/UNITY stuff/FlexHub/FlexHub_parts/FBX-Parts_FlexHub/Part_72.fbx"; allnodes.Clear(); //Create a new importer importer = new AssimpImporter(); // create an importer instance //importer.SetConfig (new con) model = importer.ImportFile(filetoImport, //import the specified file //PostProcessSteps.JoinIdenticalVertices | PostProcessSteps.Triangulate | //very important PostProcessSteps.FindInvalidData | PostProcessSteps.RemoveRedundantMaterials ); Debug.Log(model.RootNode.Name + "\n" + "-----------------------------"); // get the root node name MasterNode = model.RootNode; // get the master node of the scene //meshesinmodel = model.Meshes; Debug.Log("No.Of Meshes in the model : " + model.MeshCount + "\n" + "-----------------------------"); //foreach (Assimp.Mesh m in meshesinmodel) //{ // Debug.Log("Polygon type: " +m.PrimitiveType); // /*************************************************************************************/ // Debug.Log("No. Vertices in this mesh: " +m.VertexCount); // verticesinmesh = m.Vertices; // for (int y = 0; y < verticesinmesh.Length; ++y) // { // Debug.Log ("vertex " + (y+1) + " is " + verticesinmesh[y]); // } // Debug.Log("No.Vertices detected in this mesh: " +verticesinmesh.Length); // /*************************************************************************************/ // Debug.Log("Faces in this mesh: " + m.FaceCount); // facesinmesh = m.Faces; // foreach (Assimp.Face f in facesinmesh) // { // faceindices = f.Indices; // for (int x = 0; x < faceindices.Length; ++x) // { // Debug.Log(faceindices[x]); // } // Debug.Log("Length of the face indeces array: "+faceindices.Length); // } // Debug.Log("No.Faces detected in this mesh: " + facesinmesh.Length); //} GameObject gobject = convertNodes(MasterNode); // call the function and pass the resulting GO to a new GO importer.Dispose(); // diacard the importer when importing is done }
/// <summary> /// Loads a model file into the model. /// </summary> /// <param name="assetManager">AssetManager that provides texture assets</param> /// <param name="fileName">File name of the model.</param> public void Load(AssetManager assetManager, string fileName) { using (var importer = new AssimpImporter()) { var scene = importer.ImportFile(fileName, postProcessing); this.Load(new AssetLoadContext(assetManager, Path.GetFileNameWithoutExtension(fileName), "."), scene); } }
public void Construct(string path, Action <Vector3, Vector3, Vector2> appendVertex, Action <Int3> appendIndex, int index) { Assimp.AssimpImporter importer = new AssimpImporter(); Scene scene = importer.ImportFile(path, PostProcessPreset.ConvertToLeftHanded | PostProcessPreset.TargetRealTimeQuality); Assimp.Mesh mesh = scene.Meshes[index % scene.MeshCount]; int offset = 0; Construct(mesh, appendVertex, appendIndex, ref offset); }
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(); }
public void TestObjLoad() { String path = Path.Combine(TestHelper.RootPath, "TestFiles\\sphere.obj"); AssimpImporter importer = new AssimpImporter(); Scene scene = importer.ImportFile(path); Assert.IsNotNull(scene); Assert.IsNotNull(scene.RootNode); Assert.IsTrue(scene.RootNode.Name.Equals("sphere.obj")); }
public AssimpModel(RenderContext context, string fileName) { this.FileName = Path.GetFileName(fileName); this.context = context; loader = new BasicSubresourceLoader(Path.GetDirectoryName(fileName)); AssimpImporter importer = new AssimpImporter(); modelScene = importer.ImportFile(fileName, PostProcessSteps.Triangulate | PostProcessSteps.GenerateSmoothNormals); Visibility = true; Initialize(); }
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); }
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(); }
public void ConstructAll(string path, Action <Vector3, Vector3, Vector2> appendVertex, Action <Int3> appendIndex) { Assimp.AssimpImporter importer = new AssimpImporter(); Scene scene = importer.ImportFile(path, PostProcessPreset.ConvertToLeftHanded | PostProcessPreset.TargetRealTimeQuality); int offset = 0; foreach (Assimp.Mesh m in scene.Meshes) { Construct(m, appendVertex, appendIndex, ref offset); } }
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); }
public Model Load(string fileName) { Scene scene = _importer.ImportFile(fileName, PostProcessPreset.TargetRealTimeMaximumQuality); //use this directory path to load textures from _modelPath = Path.GetDirectoryName(fileName); var model = new Model(); var identity = Matrix.Identity; AddVertexData(model, scene, scene.RootNode, _device, ref identity); ComputeBoundingBox(model, scene); return(model); }
public void LoadScene() { AssimpImporter importer = new AssimpImporter(); LogStream logstream = new LogStream(delegate(String msg, String userData) { Console.WriteLine(msg); }); importer.AttachLogStream(logstream); m_scene = importer.ImportFile(Path.Combine(m_scenePath, m_sceneFileName)); // Oslobadjanje resursa koriscenih za ucitavanje podataka o sceni. importer.Dispose(); }
/// <summary> /// Ucitavanje podataka o sceni iz odgovarajuceg fajla. /// </summary> public void LoadScene() { // Instanciranje klase za ucitavanje podataka o sceni. AssimpImporter importer = new AssimpImporter(); // Definisanje callback delegata za belezenje poruka u toku ucitavanja podataka o sceni. LogStream logstream = new LogStream(delegate(String msg, String userData) { Console.WriteLine(msg); }); importer.AttachLogStream(logstream); // Ucitavanje podataka o sceni iz odgovarajuceg fajla. m_scene = importer.ImportFile(Path.Combine(m_scenePath, m_sceneFileName)); // Oslobadjanje resursa koriscenih za ucitavanje podataka o sceni. importer.Dispose(); }
public List <DX11IndexedGeometry> LoadModelsFromFile(string path, AssimpLoadInformation loadInfo) { Assimp.AssimpImporter importer = new AssimpImporter(); Scene scene = importer.ImportFile(path, PostProcessPreset.ConvertToLeftHanded | PostProcessPreset.TargetRealTimeQuality); List <DX11IndexedGeometry> result = new List <DX11IndexedGeometry>(); for (int j = 0; j < scene.MeshCount; j++) { Assimp.Mesh mesh = scene.Meshes[j]; if (mesh.HasFaces && mesh.HasVertices) { result.Add(this.LoadFromMesh(mesh, loadInfo)); } } return(result); }
public Model Load(string basePath, string fileName) { string absoluteFilePath = Path.Combine(basePath, fileName); Scene scene = m_importer.ImportFile(absoluteFilePath, PostProcessSteps.GenerateSmoothNormals); //use this directory path to load textures from m_modelPath = Path.GetDirectoryName(absoluteFilePath); Model model = new Model(); model.basePath = basePath; model.modelPath = fileName; Matrix identity = Matrix.Identity; AddVertexData(model, scene, scene.RootNode, m_device, ref identity); ComputeBoundingBox(model, scene); return(model); }
private static void BuildMesh(D3D10.Device d, string meshArgs) { string name = meshArgs.Split(',')[0]; InputElement[] layout = (InputElement[])typeof(MeshInputElements10).GetField(meshArgs.Split(',')[1]).GetValue(typeof(MeshInputElements10)); string fileName = ConfigurationSettings.AppSettings["ExportsFolder"] + name; AssimpImporter importer = new AssimpImporter(); LogStream logstream = new LogStream(delegate(String msg, String userData) { Console.WriteLine(msg); }); importer.AttachLogStream(logstream); importer.Scale = 0; importer.XAxisRotation = 0; importer.YAxisRotation = 0; importer.ZAxisRotation = 0; importer.VerboseLoggingEnabled = true; importer.RemoveConfigs(); Scene model = importer.ImportFile(fileName, PostProcessSteps.CalculateTangentSpace // calculate tangents and bitangents if possible | PostProcessSteps.JoinIdenticalVertices // join identical vertices/ optimize indexing CAUSES A PROBLEM //| PostProcessSteps.ValidateDataStructure // perform a full validation of the loader's output | PostProcessSteps.ImproveCacheLocality // improve the cache locality of the output vertices | PostProcessSteps.RemoveRedundantMaterials // remove redundant materials //| PostProcessSteps.FindDegenerates // remove degenerated polygons from the import CAUSES A PROBLEM //| PostProcessSteps.FindInvalidData // detect invalid model data, such as invalid normal vectors | PostProcessSteps.GenerateUVCoords // convert spherical, cylindrical, box and planar mapping to proper UVs | PostProcessSteps.TransformUVCoords // preprocess UV transformations (scaling, translation ...) //| PostProcessSteps.FindInstances // search for instanced meshes and remove them by references to one master //| PostProcessSteps.LimitBoneWeights // limit bone weights to 4 per vertex | PostProcessSteps.OptimizeMeshes // join small meshes, if possible; | PostProcessSteps.GenerateSmoothNormals // generate smooth normal vectors if not existing | PostProcessSteps.Triangulate // triangulate polygons with more than 3 edges | PostProcessSteps.SortByPrimitiveType // make 'clean' meshes which consist of a single typ of primitives | PostProcessSteps.FlipUVs // common DirectX issue (Xna also) | PostProcessSteps.FixInFacingNormals | PostProcessSteps.MakeLeftHanded | PostProcessSteps.FlipWindingOrder ); MeshHelper.BuildMeshTextures(d, model); Mesh3D m = MeshHelper.LoadFromFile(d, model, layout); importer.Dispose(); Stream stream = File.Open(ConfigurationSettings.AppSettings["ExportsFolder"] + name.Replace(".X", ".mesh"), FileMode.Create); BinaryFormatter bFormatter = new BinaryFormatter(); if (m != null) { bFormatter.Serialize(stream, m); } stream.Close(); }
public override NodeContent Import(string filename, ContentImporterContext context) { var identity = new ContentIdentity(filename, GetType().Name); var importer = new AssimpImporter(); importer.AttachLogStream(new LogStream((msg, userData) => context.Logger.LogMessage(msg))); var scene = importer.ImportFile(filename, PostProcessSteps.FlipUVs | // So far appears necessary PostProcessSteps.JoinIdenticalVertices | PostProcessSteps.Triangulate | PostProcessSteps.SortByPrimitiveType | PostProcessSteps.FindInvalidData ); var rootNode = new NodeContent { Name = scene.RootNode.Name, Identity = identity, Transform = ToXna(scene.RootNode.Transform) }; // TODO: Materials var materials = new List <MaterialContent>(); foreach (var sceneMaterial in scene.Materials) { var diffuse = sceneMaterial.GetTexture(TextureType.Diffuse, 0); materials.Add(new BasicMaterialContent() { Name = sceneMaterial.Name, Identity = identity, Texture = new ExternalReference <TextureContent>(diffuse.FilePath, identity) }); } // Meshes var meshes = new Dictionary <Mesh, MeshContent>(); foreach (var sceneMesh in scene.Meshes) { if (!sceneMesh.HasVertices) { continue; } var mesh = new MeshContent { Name = sceneMesh.Name }; // Position vertices are shared at the mesh level foreach (var vert in sceneMesh.Vertices) { mesh.Positions.Add(new Vector3(vert.X, vert.Y, vert.Z)); } var geom = new GeometryContent { Name = string.Empty, //Material = materials[sceneMesh.MaterialIndex] }; // Geometry vertices reference 1:1 with the MeshContent parent, // no indirection is necessary. geom.Vertices.Positions.AddRange(mesh.Positions); geom.Vertices.AddRange(Enumerable.Range(0, sceneMesh.VertexCount)); geom.Indices.AddRange(sceneMesh.GetIntIndices()); // Individual channels go here if (sceneMesh.HasNormals) { geom.Vertices.Channels.Add(VertexChannelNames.Normal(), ToXna(sceneMesh.Normals)); } for (var i = 0; i < sceneMesh.TextureCoordsChannelCount; i++) { geom.Vertices.Channels.Add(VertexChannelNames.TextureCoordinate(i), ToXnaVector2(sceneMesh.GetTextureCoords(i))); } mesh.Geometry.Add(geom); rootNode.Children.Add(mesh); meshes.Add(sceneMesh, mesh); } // Bones var bones = new Dictionary <Node, BoneContent>(); var hierarchyNodes = scene.RootNode.Children.SelectDeep(n => n.Children).ToList(); foreach (var node in hierarchyNodes) { var bone = new BoneContent { Name = node.Name, Transform = Matrix.Transpose(ToXna(node.Transform)) }; if (node.Parent == scene.RootNode) { rootNode.Children.Add(bone); } else { var parent = bones[node.Parent]; parent.Children.Add(bone); } // Copy the bone's name to the MeshContent - this appears to be // the way it comes out of XNA's FBXImporter. foreach (var meshIndex in node.MeshIndices) { meshes[scene.Meshes[meshIndex]].Name = node.Name; } bones.Add(node, bone); } return(rootNode); }
public BasicModel(Device device, TextureManager texMgr, string filename, string texturePath, bool flipUV = false) { var importer = new AssimpImporter(); if (!importer.IsImportFormatSupported(Path.GetExtension(filename))) { throw new ArgumentException("Model format " + Path.GetExtension(filename) + " is not supported! Cannot load {1}", "filename"); } #if DEBUG importer.AttachLogStream(new ConsoleLogStream()); importer.VerboseLoggingEnabled = true; #endif var postProcessFlags = PostProcessSteps.GenerateSmoothNormals | PostProcessSteps.CalculateTangentSpace; if (flipUV) { postProcessFlags |= PostProcessSteps.FlipUVs; } var model = importer.ImportFile(filename, postProcessFlags); var min = new Vector3(float.MaxValue); var max = new Vector3(float.MinValue); foreach (var mesh in model.Meshes) { var verts = new List <PosNormalTexTan>(); var subset = new MeshGeometry.Subset { VertexCount = mesh.VertexCount, VertexStart = Vertices.Count, FaceStart = Indices.Count / 3, FaceCount = mesh.FaceCount }; Subsets.Add(subset); // bounding box corners for (var i = 0; i < mesh.VertexCount; i++) { var pos = mesh.HasVertices ? mesh.Vertices[i].ToVector3() : new Vector3(); min = Vector3.Minimize(min, pos); max = Vector3.Maximize(max, pos); var norm = mesh.HasNormals ? mesh.Normals[i] : new Vector3D(); var texC = mesh.HasTextureCoords(0) ? mesh.GetTextureCoords(0)[i] : new Vector3D(); var tan = mesh.HasTangentBasis ? mesh.Tangents[i] : new Vector3D(); var v = new PosNormalTexTan(pos, norm.ToVector3(), texC.ToVector2(), tan.ToVector3()); verts.Add(v); } Vertices.AddRange(verts); var indices = mesh.GetIndices().Select(i => (short)(i + (uint)subset.VertexStart)).ToList(); Indices.AddRange(indices); var mat = model.Materials[mesh.MaterialIndex]; var material = mat.ToMaterial(); Materials.Add(material); var diffusePath = mat.GetTexture(TextureType.Diffuse, 0).FilePath; if (Path.GetExtension(diffusePath) == ".tga") { // DirectX doesn't like to load tgas, so you will need to convert them to pngs yourself with an image editor diffusePath = diffusePath.Replace(".tga", ".png"); } if (!string.IsNullOrEmpty(diffusePath)) { DiffuseMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, diffusePath))); } var normalPath = mat.GetTexture(TextureType.Normals, 0).FilePath; if (!string.IsNullOrEmpty(normalPath)) { NormalMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, normalPath))); } else { var normalExt = Path.GetExtension(diffusePath); normalPath = Path.GetFileNameWithoutExtension(diffusePath) + "_nmap" + normalExt; NormalMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, normalPath))); } } BoundingBox = new BoundingBox(min, max); ModelMesh.SetSubsetTable(Subsets); ModelMesh.SetVertices(device, Vertices); ModelMesh.SetIndices(device, Indices); }
protected override void OnLoad(EventArgs e) { GraphicsDevice graphicsDevice = new GraphicsDevice(this); VSync = VSyncMode.On; GL.ClearColor(0.1f, 0.2f, 0.5f, 0.0f); GL.Enable(EnableCap.DepthTest); float aspectRatio = ClientSize.Width / (float)(ClientSize.Height); Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspectRatio, 1, 100, out projectionMatrix); modelviewMatrix = Matrix4.LookAt(new Vector3(0, 3, 5), new Vector3(0, 0, 0), new Vector3(0, 1, 0)); Matrix4 scale = Matrix4.Scale(0.5f, 0.5f, 0.5f); Matrix4.Mult(ref scale, ref modelviewMatrix, out modelviewMatrix); Matrix4 translate = Matrix4.CreateTranslation(0f, -2.5f, 0f); Matrix4.Mult(ref translate, ref modelviewMatrix, out modelviewMatrix); shader = new Program(vertexShaderSource, fragmentShaderSource); shader.Bind(); shader.UniformMatrix4("camera", false, ref projectionMatrix); shader.UniformMatrix4("model", false, ref modelviewMatrix); shader.Unbind(); skeletonShader = new Program(skeletonVertexShaderSource, skeletonFragmentShaderSource); skeletonShader.Bind(); skeletonShader.UniformMatrix4("camera", false, ref projectionMatrix); skeletonShader.UniformMatrix4("model", false, ref modelviewMatrix); skeletonShader.Unbind(); // load model with ASSIMP.NET AssimpImporter importer = new AssimpImporter(); Scene scene = importer.ImportFile(@"..\..\..\Resources\dwarf2.x", PostProcessPreset.TargetRealTimeMaximumQuality); List <ModelMeshPart> meshParts = new List <ModelMeshPart>(); foreach (Mesh mesh in scene.Meshes) { ModelMeshPart part = new ModelMeshPart(); List <VertexPositionNormalTexture> vertices = new List <VertexPositionNormalTexture>(); List <int> indices = new List <int>(); for (int i = 0; i < mesh.VertexCount; i++) { vertices.Add(new VertexPositionNormalTexture(mesh.Vertices[i].X, mesh.Vertices[i].Y, mesh.Vertices[i].Z, mesh.Normals[i].X, mesh.Normals[i].Y, mesh.Normals[i].Z, mesh.GetTextureCoords(0)[i].X, 1 - mesh.GetTextureCoords(0)[i].Y)); } foreach (Face face in mesh.Faces) { foreach (uint i in face.Indices) { indices.Add((int)i); } } part.VertexArray = new VertexArray(VertexBuffer.Create(VertexFormat.PositionNormalTexture, vertices.ToArray()), IndexBuffer.Create(indices.ToArray())); part.NumVertices = (uint)mesh.VertexCount; part.PrimitiveCount = (uint)mesh.FaceCount; meshParts.Add(part); } // create skeleton List <Minotaur.Graphics.Bone> bones = new List <Minotaur.Graphics.Bone>(); CreateSkeleton(bones, scene.RootNode); ModelMesh modelMesh = new ModelMesh(meshParts); dwarf = new Model(new Skeleton(bones), new List <ModelMesh>() { modelMesh }); Bitmap bmp = new Bitmap(@"..\..\..\Resources\dwarf.jpg"); texture1 = Texture2D.Create(bmp, TextureMinFilter.Linear, TextureMagFilter.Linear); bmp = new Bitmap(@"..\..\..\Resources\axe.jpg"); texture2 = Texture2D.Create(bmp, TextureMinFilter.Linear, TextureMagFilter.Linear); }
private static IModel LoadModelFromAssimp <VertexFormat, IndexFormat>(FileInfo fi, string modelName, Device device) where VertexFormat : IModelMeshComponents, new() where IndexFormat : struct { //Get Assimp Scene Scene scene; using (AssimpImporter importer = new AssimpImporter()) { //is imported, loaded into managed memory. Then the unmanaged memory is released, and everything is reset. scene = importer.ImportFile(fi.FullName, PostProcessPreset.TargetRealTimeMaximumQuality | PostProcessPreset.ConvertToLeftHanded); } //Get components var components = ((IModelMeshComponents) new VertexFormat()).Components; //Build custom buffer format from passed in components bool isP = (components & ModelMesh.ModelMesh.ModelMeshComponents.P) == ModelMesh.ModelMesh.ModelMeshComponents.P; bool isN = (components & ModelMesh.ModelMesh.ModelMeshComponents.N) == ModelMesh.ModelMesh.ModelMeshComponents.N; bool isT = (components & ModelMesh.ModelMesh.ModelMeshComponents.T) == ModelMesh.ModelMesh.ModelMeshComponents.T; bool isC = (components & ModelMesh.ModelMesh.ModelMeshComponents.C) == ModelMesh.ModelMesh.ModelMeshComponents.C; //index Format TypeCode typeCode = Type.GetTypeCode(typeof(IndexFormat)); IModel model = null; if (isP && !(isN || isT || isC)) { if (typeCode == TypeCode.UInt16) { model = Generate_P_UINT16(scene, device); } if (typeCode == TypeCode.UInt32) { model = Generate_P_UINT32(scene, device); } } if (isP && isC && !(isN || isT)) { if (typeCode == TypeCode.UInt16) { model = Generate_PC_UINT16(scene, device); } if (typeCode == TypeCode.UInt32) { model = Generate_PC_UINT32(scene, device); } } if (isP && isN && !(isT || isC)) { if (typeCode == TypeCode.UInt16) { model = Generate_PN_UINT16(scene, device); } if (typeCode == TypeCode.UInt32) { model = Generate_PN_UINT32(scene, device); } } if (isP && isN && isC && !(isT)) { if (typeCode == TypeCode.UInt16) { model = Generate_PNC_UINT16(scene, device); } if (typeCode == TypeCode.UInt32) { model = Generate_PNC_UINT32(scene, device); } } if (isP && isN && isT && isC) { if (typeCode == TypeCode.UInt16) { model = Generate_PNTC_UINT16(scene, device); } if (typeCode == TypeCode.UInt32) { model = Generate_PNTC_UINT32(scene, device); } } if (model == null) { return(null); } model.ModelFilePath = fi.FullName; model.Name = modelName; return(model); }
private void LoadSceneA() { Console.WriteLine("Thread A: Starting import."); AssimpImporter importer = new AssimpImporter(); String path = Path.Combine(TestHelper.RootPath, "TestFiles\\Bob.md5mesh"); importer.AttachLogStream(new ConsoleLogStream("Thread A:")); Console.WriteLine("Thread A: Importing"); Scene scene = importer.ImportFile(path); Console.WriteLine("Thread A: Done importing"); }
public SkinnedModel(Device device, TextureManager texMgr, string filename, string texturePath, bool flipTexY = false) { var importer = new AssimpImporter(); #if DEBUG importer.AttachLogStream(new ConsoleLogStream()); importer.VerboseLoggingEnabled = true; #endif var model = importer.ImportFile(filename, PostProcessSteps.GenerateSmoothNormals | PostProcessSteps.CalculateTangentSpace); // Load animation data Animator = new SceneAnimator(); Animator.Init(model); // create our vertex-to-boneweights lookup var vertToBoneWeight = new Dictionary <uint, List <VertexWeight> >(); // create bounding box extents _min = new Vector3(float.MaxValue); _max = new Vector3(float.MinValue); foreach (var mesh in model.Meshes) { ExtractBoneWeightsFromMesh(mesh, vertToBoneWeight); var subset = new MeshGeometry.Subset { VertexCount = mesh.VertexCount, VertexStart = Vertices.Count, FaceStart = Indices.Count / 3, FaceCount = mesh.FaceCount }; Subsets.Add(subset); var verts = ExtractVertices(mesh, vertToBoneWeight, flipTexY); Vertices.AddRange(verts); // extract indices and shift them to the proper offset into the combined vertex buffer var indices = mesh.GetIndices().Select(i => (short)(i + (uint)subset.VertexStart)).ToList(); Indices.AddRange(indices); // extract materials var mat = model.Materials[mesh.MaterialIndex]; var material = mat.ToMaterial(); Materials.Add(material); // extract material textures var diffusePath = mat.GetTexture(TextureType.Diffuse, 0).FilePath; if (!string.IsNullOrEmpty(diffusePath)) { DiffuseMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, diffusePath))); } var normalPath = mat.GetTexture(TextureType.Normals, 0).FilePath; if (!string.IsNullOrEmpty(normalPath)) { NormalMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, normalPath))); } else { // for models created without a normal map baked, we'll check for a texture with the same // filename as the diffure texture, and _nmap suffixed // this lets us add our own normal maps easily var normalExt = Path.GetExtension(diffusePath); normalPath = Path.GetFileNameWithoutExtension(diffusePath) + "_nmap" + normalExt; if (File.Exists(Path.Combine(texturePath, normalPath))) { NormalMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, normalPath))); } } } BoundingBox = new BoundingBox(_min, _max); ModelMesh.SetSubsetTable(Subsets); ModelMesh.SetVertices(device, Vertices); ModelMesh.SetIndices(device, Indices); }
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"); }
public static void MeshToStaticModel(string file) { AssimpImporter importer = new AssimpImporter(); try { Scene scene = importer.ImportFile(file, PostProcessSteps.Triangulate); if (scene.MeshCount == 1) { Vector3D[] vertices = scene.Meshes[0].Vertices; Vector3D[] uvCoords = scene.Meshes[0].GetTextureCoords(0); Vector3D[] normals = null; short[] indices = scene.Meshes[0].GetShortIndices(); if (!scene.Meshes[0].HasNormals) { MessageBox.Show("Mesh doesn't have normals. Check if the mesh has been exported correctly.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); } normals = scene.Meshes[0].Normals; // 4 byte floats * 3 dimensions byte[] vertexData = new byte[12 * vertices.Length]; // 4 byte floats * 2 dimensions byte[] uvData = new byte[8 * uvCoords.Length]; // 4 byte normals * 3 dimensions byte[] normalData = new byte[12 * normals.Length]; int vertexOffset = 0, uvOffset = 0, normalOffset = 0; // Extract vertex data for (int i = 0; i < vertices.Length; ++i) { byte[] x, y, z; x = BitConverter.GetBytes(vertices[i].X); y = BitConverter.GetBytes(vertices[i].Y); z = BitConverter.GetBytes(vertices[i].Z); Buffer.BlockCopy(x, 0, vertexData, vertexOffset, 4); Buffer.BlockCopy(y, 0, vertexData, vertexOffset + 4, 4); Buffer.BlockCopy(z, 0, vertexData, vertexOffset + 8, 4); vertexOffset += 12; } // Extract UV coordinates data for (int i = 0; i < uvCoords.Length; ++i) { byte[] s, t; s = BitConverter.GetBytes(uvCoords[i].X); t = BitConverter.GetBytes(uvCoords[i].Y); Buffer.BlockCopy(s, 0, uvData, uvOffset, 4); Buffer.BlockCopy(t, 0, uvData, uvOffset + 4, 4); uvOffset += 8; } // Extract normal data for (int i = 0; i < normals.Length; ++i) { byte[] x, y, z; x = BitConverter.GetBytes(normals[i].X); y = BitConverter.GetBytes(normals[i].Y); z = BitConverter.GetBytes(normals[i].Z); Buffer.BlockCopy(x, 0, normalData, normalOffset, 4); Buffer.BlockCopy(y, 0, normalData, normalOffset + 4, 4); Buffer.BlockCopy(z, 0, normalData, normalOffset + 8, 4); normalOffset += 12; } // Save the raw mesh file byte[] binary = new byte[MESH_HEADER_LENGTH + vertexData.Length + uvData.Length + normalData.Length + 2 * indices.Length]; // Set the vertex count binary[0] = BitConverter.GetBytes((UInt16)vertices.Length)[0]; binary[1] = BitConverter.GetBytes((UInt16)vertices.Length)[1]; // Copy the vertices Buffer.BlockCopy(vertexData, 0, binary, MESH_HEADER_LENGTH, vertexData.Length); // Copy the UV coordinates Buffer.BlockCopy(uvData, 0, binary, MESH_HEADER_LENGTH + vertexData.Length, uvData.Length); // Copy the normals Buffer.BlockCopy(normalData, 0, binary, MESH_HEADER_LENGTH + vertexData.Length + uvData.Length, normalData.Length); // Copy the indices Buffer.BlockCopy(indices, 0, binary, MESH_HEADER_LENGTH + vertexData.Length + uvData.Length + normalData.Length, 2 * indices.Length); // Save the converted file File.WriteAllBytes(file.Split('.')[0] + ".mesh", binary); } else { MessageBox.Show("Model has " + scene.MeshCount + " submeshes. Only models with one submesh can be processed", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } catch (AssimpException assExp) { MessageBox.Show(assExp.Message, "Error converting mesh", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
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 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); }
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); }