public void ImportModel() { OpenFileDialog dlg = new OpenFileDialog() { DefaultExt = "sa1mdl", Filter = "Model Files|*.sa1mdl;*.obj;*.objf", RestoreDirectory = true }; if (dlg.ShowDialog() == DialogResult.OK) { switch (Path.GetExtension(dlg.FileName).ToLowerInvariant()) { case ".obj": case ".fbx": case ".dae": case ".objf": Assimp.AssimpContext context = new Assimp.AssimpContext(); context.SetConfig(new Assimp.Configs.FBXPreservePivotsConfig(false)); Assimp.Scene scene = context.ImportFile(dlg.FileName, Assimp.PostProcessSteps.Triangulate | Assimp.PostProcessSteps.JoinIdenticalVertices | Assimp.PostProcessSteps.FlipUVs); NJS_OBJECT newmodel = SAEditorCommon.Import.AssimpStuff.AssimpImport(scene, scene.RootNode, ModelFormat.BasicDX, LevelData.TextureBitmaps[LevelData.leveltexs].Select(a => a.Name).ToArray(), true); Model.Attach = newmodel.Attach; Model.ProcessVertexData(); Mesh = Model.Attach.CreateD3DMesh(); break; case ".sa1mdl": ModelFile mf = new ModelFile(dlg.FileName); Model.Attach = mf.Model.Attach; Model.ProcessVertexData(); Mesh = Model.Attach.CreateD3DMesh(); break; } } }
private bool loadFile(string path) { Assimp.AssimpContext importer = new Assimp.AssimpContext(); importer.SetConfig(new NormalSmoothingAngleConfig(66f)); //TODO check which other post processes we need m_scene = importer.ImportFile(path, Assimp.PostProcessSteps.CalculateTangentSpace | Assimp.PostProcessSteps.GenerateNormals | Assimp.PostProcessSteps.Triangulate | Assimp.PostProcessSteps.JoinIdenticalVertices | Assimp.PostProcessSteps.OptimizeMeshes); //failed loading :( if (!m_scene.HasMeshes) { textBoxInfo.Text = "No Valid Meshes found."; return(false); } //display some info string msg = "Mesh Count: " + m_scene.MeshCount.ToString() + Environment.NewLine + "Material count: " + m_scene.MaterialCount.ToString() + " (Maximum material count is 32)"; textBoxInfo.Text = msg; buttonSave.Enabled = (m_scene.MeshCount > 0 && m_scene.MaterialCount <= maxMaterials); return(true); }
private void exportToAssimp(object sender, EventArgs e) { Debug.WriteLine("Exporting to assimp"); if (RenderState.rootObject != null) { Assimp.AssimpContext ctx = new Assimp.AssimpContext(); Dictionary <int, int> meshImportStatus = new Dictionary <int, int>(); Assimp.Scene aScene = new Assimp.Scene(); Assimp.Node rootNode = RenderState.rootObject.assimpExport(ref aScene, ref meshImportStatus); aScene.RootNode = rootNode; //add a single material for now Assimp.Material aMat = new Assimp.Material(); aMat.Name = "testMaterial"; aScene.Materials.Add(aMat); Assimp.ExportFormatDescription[] supported_formats = ctx.GetSupportedExportFormats(); //Assimp.Scene blenderScene = ctx.ImportFile("SimpleSkin.gltf"); //ctx.ExportFile(blenderScene, "SimpleSkin.glb", "glb2"); try { ctx.ExportFile(aScene, "test.glb", "glb2"); //ctx.ExportFile(aScene, "test.fbx", "fbx"); } catch (Exception ex) { Console.WriteLine(ex.Message); } } }
private LoadedModel LoadModelOfd() { OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { if (ofd.CheckFileExists) { string dirName = Path.GetDirectoryName(ofd.FileName); try { using (Assimp.AssimpContext importer = new Assimp.AssimpContext()) { importer.SetConfig(new NormalSmoothingAngleConfig(66.0f)); Assimp.Scene model = importer.ImportFile(ofd.FileName, Assimp.PostProcessPreset.TargetRealTimeMaximumQuality); LoadedModel loadedModel = new LoadedModel(model, dirName); loadedModel.Name = Path.GetFileName(ofd.FileName); return(loadedModel); } } catch { System.Windows.MessageBox.Show("Unsupported file type.", "Error"); } } } return(null); }
public void ImportModel(string filePath, bool legacyImport = false) { NJS_OBJECT newmodel; // Old OBJ import (with vcolor face) for NodeTable and legacy import if (legacyImport) { newmodel = new NJS_OBJECT { Attach = SAModel.Direct3D.Extensions.obj2nj(filePath, LevelData.TextureBitmaps != null ? LevelData.TextureBitmaps[LevelData.leveltexs].Select(a => a.Name).ToArray() : null), }; COL.Model.Attach = newmodel.Attach; COL.Model.ProcessVertexData(); Visible = true; Solid = true; mesh = COL.Model.Attach.CreateD3DMesh(); return; } Assimp.AssimpContext context = new Assimp.AssimpContext(); context.SetConfig(new Assimp.Configs.FBXPreservePivotsConfig(false)); Assimp.Scene scene = context.ImportFile(filePath, Assimp.PostProcessSteps.Triangulate | Assimp.PostProcessSteps.JoinIdenticalVertices | Assimp.PostProcessSteps.FlipUVs); newmodel = SAEditorCommon.Import.AssimpStuff.AssimpImport(scene, scene.RootNode, ModelFormat.BasicDX, LevelData.TextureBitmaps[LevelData.leveltexs].Select(a => a.Name).ToArray(), true); COL.Model.Attach = newmodel.Attach; COL.Model.ProcessVertexData(); Visible = true; Solid = true; mesh = COL.Model.Attach.CreateD3DMesh(); }
private void OnSetFileAssociations(object sender, EventArgs e) { using (var imp = new Assimp.AssimpContext()) { var list = imp.GetSupportedImportFormats(); // do not associate .xml - it is too generic var filteredList = list.Where(s => s != ".xml").ToArray(); var listString = string.Join(", ", filteredList); if (DialogResult.OK == MessageBox.Show(this, "The following file extensions will be associated with open3mod: " + listString, "Set file associations", MessageBoxButtons.OKCancel)) { if (!FileAssociations.SetAssociations(list)) { MessageBox.Show(this, "Failed to set file extensions", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { MessageBox.Show(this, "File extensions have been successfully associated", "open3mod", MessageBoxButtons.OK, MessageBoxIcon.Information); } } } }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); AssimpContext = new Assimp.AssimpContext(); RebuildSurfaceList(); UpdateSurfaceComboBox(); //FillModelsGridView(); HasInitialized = true; }
static Assimp.Scene LoadAssimpScene(string fileName) { Assimp.AssimpContext cont = new Assimp.AssimpContext(); // AssImp adds dummy nodes for pivots from FBX, so we'll force them off cont.SetConfig(new Assimp.Configs.FBXPreservePivotsConfig(false)); cont.ZAxisRotation = -90.0f; return(cont.ImportFile(fileName, Assimp.PostProcessSteps.Triangulate)); }
public void Load() { BoneAnimations = new List <BoneAnimation>(); var importer = new Assimp.AssimpContext(); var aScene = importer.ImportFile(FilePath, Assimp.PostProcessPreset.TargetRealTimeMaximumQuality); RootBoneAnimation = LoadBoneAnimation(aScene, aScene.RootNode, null); }
public DeviceModelCollection LoadModel(string filePath) { var context = new Assimp.AssimpContext(); var pp = Assimp.PostProcessSteps.FindInvalidData | Assimp.PostProcessSteps.OptimizeGraph; var scene = context.ImportFile(filePath, pp); return(ReadModel(scene)); }
public static Assimp.Scene GetResourceModel(string resourceName, string format) { if (AssimpContext == null) { AssimpContext = new Assimp.AssimpContext(); } var stream = GetResourceStream(resourceName); return(AssimpContext.ImportFileFromStream(stream, format)); }
public void SetUp() { var assimpNetimporter = new Assimp.AssimpContext(); Assimp.LogStream.IsVerboseLoggingEnabled = true; var logger = new Assimp.ConsoleLogStream(); logger.Attach(); assimpNetScene = assimpNetimporter.ImportFile(filename); logger.Detach(); var assimpSharpImporter = new AssimpSharp.FBX.FBXImporter(); assimpSharpScene = new AssimpSharp.Scene(); assimpSharpScene = assimpSharpImporter.ReadFile(filename); }
public static void SaveToCollada(RwAnimationNode animation, RwFrameListNode frameList, string path) { var aiScene = ToAssimpScene(animation, frameList); using (var aiContext = new Assimp.AssimpContext()) { if (!aiContext.ExportFile(aiScene, path, "collada")) { throw new Exception("Failed to export"); } } }
public static MeshGroup FromFbx(string filePath) { const float Scale = 1.0f; var assimp = new Assimp.AssimpContext(); var scene = assimp.ImportFile(filePath, Assimp.PostProcessSteps.PreTransformVertices); var baseFilePath = Path.GetDirectoryName(filePath); TexList = new List <string>(); TextureData = new List <Tm2>(); foreach (Assimp.Material mat in scene.Materials) { TexList.Add(Path.GetFileName(mat.TextureDiffuse.FilePath)); Stream str = File.OpenRead(TexList[TexList.Count - 1]); PngImage png = new PngImage(str); Tm2 tmImage = Tm2.Create(png); TextureData.Add(tmImage); } int childCount = scene.RootNode.ChildCount; return(new MeshGroup() { MeshDescriptors = scene.Meshes .Select(x => { var vertices = new PositionColoredTextured[x.Vertices.Count]; for (var i = 0; i < vertices.Length; i++) { vertices[i].X = x.Vertices[i].X * Scale; vertices[i].Y = x.Vertices[i].Y * Scale; vertices[i].Z = x.Vertices[i].Z * Scale; vertices[i].Tu = x.TextureCoordinateChannels[0][i].X; vertices[i].Tv = 1.0f - x.TextureCoordinateChannels[0][i].Y; vertices[i].R = 1.0f; vertices[i].G = 1.0f; vertices[i].B = 1.0f; vertices[i].A = 1.0f; } return new MeshDescriptor { Vertices = vertices, Indices = x.GetIndices(), IsOpaque = true, TextureIndex = x.MaterialIndex }; }).ToList() }); }
public static void AssimpPRMConvert(string initialFilePath, string finalFilePath) { Assimp.AssimpContext context = new Assimp.AssimpContext(); context.SetConfig(new Assimp.Configs.FBXPreservePivotsConfig(false)); Assimp.Scene aiScene = context.ImportFile(initialFilePath, Assimp.PostProcessSteps.Triangulate | Assimp.PostProcessSteps.JoinIdenticalVertices | Assimp.PostProcessSteps.FlipUVs); PRMModel prm = new PRMModel(); int totalVerts = 0; //Iterate through and combine meshes. PRMs can only have a single mesh IterateAiNodesPRM(prm, ref totalVerts, aiScene, aiScene.RootNode, Matrix4x4.Transpose(GetMat4FromAssimpMat4(aiScene.RootNode.Transform))); AquaUtil.WritePRMToFile(prm, finalFilePath, 4); }
public static Assimp.Scene ImportScene(string path, bool allowWeights) { using (var aiContext = new Assimp.AssimpContext()) { aiContext.SetConfig(new Assimp.Configs.VertexBoneWeightLimitConfig(allowWeights ? 3 : 1)); aiContext.SetConfig(new Assimp.Configs.FBXPreservePivotsConfig(false)); return(aiContext.ImportFile(path, Assimp.PostProcessSteps.FindDegenerates | Assimp.PostProcessSteps.FindInvalidData | Assimp.PostProcessSteps.FlipUVs | Assimp.PostProcessSteps.ImproveCacheLocality | Assimp.PostProcessSteps.JoinIdenticalVertices | Assimp.PostProcessSteps.LimitBoneWeights | Assimp.PostProcessSteps.SplitByBoneCount | Assimp.PostProcessSteps.Triangulate | Assimp.PostProcessSteps.ValidateDataStructure | Assimp.PostProcessSteps.GenerateUVCoords)); } }
public void ExportModel() { using (System.Windows.Forms.SaveFileDialog a = new System.Windows.Forms.SaveFileDialog { DefaultExt = "dae", Filter = "SAModel Files|*.sa1mdl|Collada|*.dae|Wavefront|*.obj" }) { if (a.ShowDialog() == System.Windows.Forms.DialogResult.OK) { string ftype = "collada"; switch (System.IO.Path.GetExtension(a.FileName).ToLowerInvariant()) { case ".sa1mdl": ModelFile.CreateFile(a.FileName, COL.Model, null, null, null, null, COL.Model.GetModelFormat()); return; case ".fbx": ftype = "fbx"; break; case ".obj": ftype = "obj"; break; } Assimp.AssimpContext context = new Assimp.AssimpContext(); Assimp.Scene scene = new Assimp.Scene(); scene.Materials.Add(new Assimp.Material()); Assimp.Node n = new Assimp.Node(); n.Name = "RootNode"; scene.RootNode = n; string rootPath = System.IO.Path.GetDirectoryName(a.FileName); List <string> texturePaths = new List <string>(); int numSteps = 0; if (LevelData.TextureBitmaps != null && LevelData.TextureBitmaps.Count > 0) { numSteps = LevelData.TextureBitmaps[LevelData.leveltexs].Length; } for (int i = 0; i < numSteps; i++) { BMPInfo bmp = LevelData.TextureBitmaps[LevelData.leveltexs][i]; texturePaths.Add(System.IO.Path.Combine(rootPath, bmp.Name + ".png")); bmp.Image.Save(System.IO.Path.Combine(rootPath, bmp.Name + ".png")); } SAEditorCommon.Import.AssimpStuff.AssimpExport(COL.Model, scene, Matrix.Identity, texturePaths.Count > 0 ? texturePaths.ToArray() : null, scene.RootNode); context.ExportFile(scene, a.FileName, ftype, Assimp.PostProcessSteps.ValidateDataStructure | Assimp.PostProcessSteps.Triangulate | Assimp.PostProcessSteps.FlipUVs); // } } }
public override Assimp.Scene Import(string filename, ContentImporterContext context) { if (dllLoadExc != null) { context.RaiseBuildMessage("FBXIMPORT", dllLoadExc.Message, BuildMessageEventArgs.BuildMessageType.Error); } try { Assimp.AssimpContext c = new Assimp.AssimpContext(); return(c.ImportFile(filename, Assimp.PostProcessSteps.Triangulate | Assimp.PostProcessSteps.OptimizeMeshes | Assimp.PostProcessSteps.OptimizeGraph)); } catch (Exception ex) { context.RaiseBuildMessage(filename, ex.Message, BuildMessageEventArgs.BuildMessageType.Error); } return(null); }
internal static Engine_MeshInfo LoadFilePro(string _fileName) { var a = new Assimp.AssimpContext(); var s = a.ImportFile(_fileName); Engine_MeshInfo obj = new Engine_MeshInfo(); obj.vertices = new List <Engine_Vertex>(); obj.indices = new List <ushort>(); foreach (var mesh in s.Meshes) { for (int i = 0; i < mesh.VertexCount; i++) { obj.vertices.Add(new Engine_Vertex( mesh.Vertices[i].X, mesh.Vertices[i].Y, mesh.Vertices[i].Z, mesh.TextureCoordinateChannels[0][i].X, mesh.TextureCoordinateChannels[0][i].Y, mesh.Normals[i].X, mesh.Normals[i].Y, mesh.Normals[i].Z)); } foreach (var item in mesh.Faces) { var rangeIndices = new ushort[] { (ushort)(item.Indices[0]), (ushort)(item.Indices[1]), (ushort)(item.Indices[2]) }; obj.indices.AddRange(rangeIndices); if (item.IndexCount == 4) { rangeIndices = new ushort[] { (ushort)(item.Indices[0]), (ushort)(item.Indices[2]), (ushort)(item.Indices[3]) }; obj.indices.AddRange(rangeIndices); } } } return(obj); }
public static MeshGroup FromFbx(GraphicsDevice graphics, string filePath) { const float Scale = 96.0f; var assimp = new Assimp.AssimpContext(); var scene = assimp.ImportFile(filePath, Assimp.PostProcessSteps.PreTransformVertices); var baseFilePath = Path.GetDirectoryName(filePath); return(new MeshGroup() { MeshDescriptors = scene.Meshes .Select(x => { var vertices = new PositionColoredTextured[x.Vertices.Count]; for (var i = 0; i < vertices.Length; i++) { vertices[i].X = x.Vertices[i].X * Scale; vertices[i].Y = x.Vertices[i].Y * Scale; vertices[i].Z = x.Vertices[i].Z * Scale; vertices[i].Tu = x.TextureCoordinateChannels[0][i].X; vertices[i].Tv = 1.0f - x.TextureCoordinateChannels[0][i].Y; vertices[i].R = 0xFF; vertices[i].G = 0xFF; vertices[i].B = 0xFF; vertices[i].A = 0xFF; } return new MeshDescriptor { Vertices = vertices, Indices = x.Faces.SelectMany(f => f.Indices).ToArray(), IsOpaque = true, TextureIndex = x.MaterialIndex }; }).ToList(), Textures = scene.Materials.Select(x => { var path = Path.Join(baseFilePath, $"{x.Name}.png"); return new PngKingdomTexture(path, graphics); }).ToArray(), }); }
private void ASSIMPExportToolStripMenuItem_Click(object sender, EventArgs e) { using (SaveFileDialog a = new SaveFileDialog { DefaultExt = "dae", Filter = "Model Files|*.obj;*.fbx;*.dae", FileName = "test" }) { if (a.ShowDialog() == DialogResult.OK) { Assimp.AssimpContext context = new Assimp.AssimpContext(); Assimp.Scene scene = new Assimp.Scene(); scene.Materials.Add(new Assimp.Material()); Assimp.Node n = new Assimp.Node(); n.Name = "RootNode"; scene.RootNode = n; string rootPath = Path.GetDirectoryName(a.FileName); List <string> texturePaths = new List <string>(); if (LevelData.TextureBitmaps != null) { foreach (BMPInfo[] bmp_ in LevelData.TextureBitmaps.Values) //??????? { foreach (BMPInfo bmp in bmp_) { texturePaths.Add(Path.Combine(rootPath, bmp.Name + ".png")); bmp.Image.Save(Path.Combine(rootPath, bmp.Name + ".png")); } } } foreach (COL col in LevelData.geo.COL) { SAEditorCommon.Import.AssimpStuff.AssimpExport(col.Model, scene, Matrix.Identity, texturePaths.Count > 0 ? texturePaths.ToArray() : null, scene.RootNode); } context.ExportFile(scene, a.FileName, "collada", Assimp.PostProcessSteps.ValidateDataStructure | Assimp.PostProcessSteps.Triangulate | Assimp.PostProcessSteps.FlipUVs); // } } }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); if (!LDDEnvironment.HasInitialized) { LDDEnvironment.Initialize(); } AssimpContext = new Assimp.AssimpContext(); bool isProjectOpen = (CurrentProject != null); CurrentProjectRb.Enabled = isProjectOpen; (isProjectOpen ? CurrentProjectRb : SelectPartRb).Checked = true; PartBrowseTextBox.Enabled = SelectPartRb.Checked; if (SelectPartRb.Checked) { ValidateSelectedPartID(); } }
public static void WriteModelFile(IGeometryModel model, string fileName, string formatId) { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (string.IsNullOrWhiteSpace(fileName)) { throw new ArgumentNullException(nameof(fileName)); } formatId = (formatId ?? Settings.DefaultSaveFormat).ToLower(); if (!ExportFormats.Any(f => f.FormatId == formatId)) { throw new ArgumentException($"{formatId} is not a supported format.", nameof(formatId)); } var ext = "." + GetFormatExtension(formatId); if (!fileName.EndsWith(ext, StringComparison.OrdinalIgnoreCase)) { fileName += ext; } var format = ExportFormats.First(f => f.FormatId == formatId); if (format.ExportFunction != null) { format.ExportFunction(model, fileName); } else { using (var context = new Assimp.AssimpContext()) { var scene = model.CreateAssimpScene(context, formatId); context.ExportFile(scene, fileName, formatId); } } }
private async Task <Assimp.Scene> ImportAssimpFile(string fileName) { Assimp.Scene aScene = null; await Task <Assimp.Scene> .Run(() => { try { Assimp.AssimpContext ctx = new Assimp.AssimpContext(); aScene = ctx.ImportFile(fileName, Assimp.PostProcessSteps.Triangulate | Assimp.PostProcessSteps.GenerateNormals | Assimp.PostProcessSteps.GenerateUVCoords); } catch (Assimp.AssimpException e) { Debug.LogError(e.Message); aScene = null; } }); return(aScene); }
public void Import(string fileName, Transform root, bool synchronous = false) { blocking = synchronous; if (synchronous) { Assimp.AssimpContext ctx = new Assimp.AssimpContext(); var aScene = ctx.ImportFile(fileName, Assimp.PostProcessSteps.Triangulate | Assimp.PostProcessSteps.GenerateNormals | Assimp.PostProcessSteps.GenerateUVCoords); CreateUnityDataFromAssimp(fileName, aScene, root).MoveNext(); Clear(); progress = 1.0f; } else { unityDataInCoroutineCreated = false; ImportTaskData d = new ImportTaskData(); d.fileName = fileName; d.root = root; taskData.Add(d); } }
public void ExportModel() { using (System.Windows.Forms.SaveFileDialog a = new System.Windows.Forms.SaveFileDialog { DefaultExt = "dae", Filter = "SAModel Files|*.sa1mdl|Collada|*.dae|Wavefront|*.obj" }) { if (a.ShowDialog() == System.Windows.Forms.DialogResult.OK) { string ftype = "collada"; switch (System.IO.Path.GetExtension(a.FileName).ToLowerInvariant()) { case ".sa1mdl": ModelFile.CreateFile(a.FileName, Model, null, null, null, null, Model.GetModelFormat()); return; case ".fbx": ftype = "fbx"; break; case ".obj": ftype = "obj"; break; } Assimp.AssimpContext context = new Assimp.AssimpContext(); Assimp.Scene scene = new Assimp.Scene(); scene.Materials.Add(new Assimp.Material()); Assimp.Node n = new Assimp.Node(); n.Name = "RootNode"; scene.RootNode = n; string rootPath = System.IO.Path.GetDirectoryName(a.FileName); SAEditorCommon.Import.AssimpStuff.AssimpExport(Model, scene, Matrix.Identity, null, scene.RootNode); context.ExportFile(scene, a.FileName, ftype, Assimp.PostProcessSteps.ValidateDataStructure | Assimp.PostProcessSteps.Triangulate | Assimp.PostProcessSteps.FlipUVs); // } } }
public static UnityEngine.Mesh ToUnityMesh(File file) { if (file.FileType != File.Type.Model) { return(null); } Assimp.AssimpContext ctx = new Assimp.AssimpContext(); Assimp.Scene s = ctx.ImportFileFromStream(file.StreamData, Assimp.PostProcessSteps.Triangulate); if (!s.HasMeshes) { return(null); } var mesh = s.Meshes[0]; var newMesh = new UnityEngine.Mesh(); newMesh.vertices = mesh.Vertices.ConvertAll(v => v.ToV3()).ToArray(); //int[] indicies = mesh.GetIndices(); List <int> indicies = new List <int>(); foreach (var face in mesh.Faces) { indicies.AddRange(face.Indices); } newMesh.triangles = indicies.ToArray(); for (int i = 0; i < mesh.TextureCoordinateChannelCount; ++i) { newMesh.SetUVs(i, mesh.TextureCoordinateChannels[i].ConvertAll(v => v.ToV2())); } return(newMesh); }
private void ConvertModelIntoMapModel(string modelFile, MapGenConfig config) { logger.Debug($"Loading 3D model file \"{modelFile}\" using Assimp."); var assimp = new Assimp.AssimpContext(); var scene = assimp.ImportFile(modelFile, Assimp.PostProcessSteps.PreTransformVertices); bigMeshContainer = new BigMeshContainer(); var scale = config.scale; Matrix4x4 matrix = Matrix4x4.Identity; if (config.applyMatrix != null) { var m = config.applyMatrix; if (m.Length == 16) { matrix = new Matrix4x4( m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15] ); logger.Debug($"Apply matrix: {matrix}"); } } else { matrix *= scale; } logger.Debug($"Starting triangle strip conversion for {scene.Meshes.Count} meshes."); foreach (var inputMesh in scene.Meshes) { logger.Debug($"Mesh: {inputMesh.Name} ({inputMesh.FaceCount:#,##0} faces, {inputMesh.VertexCount:#,##0} vertices)"); var modelMat = scene.Materials[inputMesh.MaterialIndex]; var matDef = config.FindMaterial(modelMat.Name ?? "default") ?? MaterialDef.CreateFallbackFor(modelMat.Name); if (matDef.ignore) { logger.Info($"This mesh \"{inputMesh.Name}\" is not rendered due to ignore flag of material \"{modelMat.Name}\"."); continue; } var kh2Mesh = bigMeshContainer.AllocateBigMeshForMaterial(matDef); var diffuseTextureFile = modelMat.TextureDiffuse.FilePath; if (!string.IsNullOrEmpty(diffuseTextureFile)) { if (config.reuseImd) { logger.Debug($"The mesh \"{inputMesh.Name}\" material \"{matDef.name}\" has filepath \"{diffuseTextureFile}\" for diffuse texture. It will be associated with material's fromFile3. Setting preferable imd file to fromFile2 due to reuseImd flag."); matDef.fromFile2 = Path.ChangeExtension(diffuseTextureFile, ".imd"); matDef.fromFile3 = diffuseTextureFile; } else { logger.Debug($"The mesh \"{inputMesh.Name}\" material \"{matDef.name}\" has filepath \"{diffuseTextureFile}\" for diffuse texture. It will be associated with material's fromFile2."); matDef.fromFile3 = diffuseTextureFile; } } var kh2BaseVert = kh2Mesh.vertexList.Count; List <int> vertexToLocal = new List <int>(); foreach (var inputVertex in inputMesh.Vertices) { var vertex = Vector3.Transform( new Vector3(inputVertex.X, inputVertex.Y, inputVertex.Z), matrix ); var index = kh2Mesh.vertexList.IndexOf(vertex); if (index < 0) { index = kh2Mesh.vertexList.Count; kh2Mesh.vertexList.Add(vertex); } vertexToLocal.Add(index); } var localFaces = inputMesh.Faces .Select( set => set.Indices .Select(index => new VertPair { uvColorIndex = index, vertexIndex = vertexToLocal[index] }) .ToArray() ) .ToArray(); var inputTexCoords = inputMesh.TextureCoordinateChannels.First(); var inputVertexColorList = inputMesh.VertexColorChannels.First(); var hasVertexColor = inputMesh.VertexColorChannelCount >= 1; var maxIntensity = matDef.maxColorIntensity ?? config.maxColorIntensity ?? 128; var maxAlpha = matDef.maxAlpha ?? config.maxAlpha ?? 128; var triConverter = config.disableTriangleStripsOptimization ? (TriangleFansToTriangleStripsConverter)TriangleFansToTriangleStripsNoOpts : (TriangleFansToTriangleStripsConverter)TriangleFansToTriangleStripsOptimized; foreach (var triStripInput in triConverter(localFaces)) { var triStripOut = new BigMesh.TriangleStrip(); foreach (var vertPair in triStripInput) { triStripOut.vertexIndices.Add(kh2BaseVert + vertPair.vertexIndex); triStripOut.uvList.Add(Get2DCoord(inputTexCoords[vertPair.uvColorIndex])); if (hasVertexColor) { triStripOut.vertexColorList.Add(ConvertVertexColor(inputVertexColorList[vertPair.uvColorIndex], maxIntensity, maxAlpha)); } else { triStripOut.vertexColorList.Add(new Color(maxIntensity, maxIntensity, maxIntensity, maxAlpha)); } } kh2Mesh.triangleStripList.Add(triStripOut); } logger.Debug($"Output: {kh2Mesh.vertexList.Count:#,##0} vertices, {kh2Mesh.triangleStripList.Count:#,##0} triangle strips."); } logger.Debug($"The conversion has done."); logger.Debug($"Starting mesh splitter and vif packets builder."); mapModel = new Mdlx.M4 { VifPackets = new List <Mdlx.VifPacketDescriptor>(), }; foreach (var bigMesh in bigMeshContainer.MeshList .Where(it => it.textureIndex != -1) ) { foreach (var smallMesh in BigMeshSplitter.Split(bigMesh)) { var dmaPack = new MapVifPacketBuilder(smallMesh); smallMeshList.Add(smallMesh); bigMesh.vifPacketIndices.Add(Convert.ToUInt16(mapModel.VifPackets.Count)); smallMesh.vifPacketIndices.Add(Convert.ToUInt16(mapModel.VifPackets.Count)); mapModel.VifPackets.Add( new Mdlx.VifPacketDescriptor { VifPacket = dmaPack.vifPacket.ToArray(), TextureId = smallMesh.textureIndex, DmaPerVif = new ushort[] { dmaPack.firstVifPacketQwc, 0, }, IsTransparentFlag = smallMesh.matDef.transparentFlag ?? 0, } ); } } logger.Debug($"Output: {mapModel.VifPackets.Count:#,##0} vif packets."); logger.Debug($"The builder has done."); logger.Debug($"Starting vifPacketRenderingGroup builder."); // first group: render all mapModel.vifPacketRenderingGroup = new List <ushort[]>( new ushort[][] { Enumerable.Range(0, mapModel.VifPackets.Count) .Select(it => Convert.ToUInt16(it)) .ToArray() } ); logger.Debug($"Output: {mapModel.vifPacketRenderingGroup.Count:#,##0} groups."); mapModel.DmaChainIndexRemapTable = new List <ushort>( Enumerable.Range(0, mapModel.VifPackets.Count) .Select(it => Convert.ToUInt16(it)) .ToArray() ); }
void LoadAssimpNetScene(string file) { var importer = new Assimp.AssimpContext(); var assimpNetScene = importer.ImportFile(file); }
public static Assimp.Scene CreateAssimpScene(this IGeometryModel model, Assimp.AssimpContext context, string formatId) { var scale = ModelViewerPlugin.Settings.GeometryScale; //either Assimp or collada has issues when there is a name conflict const string bonePrefix = "~"; const string geomPrefix = "-"; const string scenPrefix = "$"; var scene = new Assimp.Scene(); scene.RootNode = new Assimp.Node($"{scenPrefix}{model.Name}"); //Assimp is Y-up in inches by default - this forces it to export as Z-up in meters scene.RootNode.Transform = (CoordinateSystem.HaloCEX * ModelViewerPlugin.Settings.AssimpScale).ToAssimp4x4(); #region Nodes var allNodes = new List <Assimp.Node>(); foreach (var node in model.Nodes) { var result = new Assimp.Node($"{bonePrefix}{node.Name}"); var q = new System.Numerics.Quaternion(node.Rotation.X, node.Rotation.Y, node.Rotation.Z, node.Rotation.W); var mat = System.Numerics.Matrix4x4.CreateFromQuaternion(q); mat.Translation = new System.Numerics.Vector3(node.Position.X * scale, node.Position.Y * scale, node.Position.Z * scale); result.Transform = mat.ToAssimp4x4(); allNodes.Add(result); } for (int i = 0; i < model.Nodes.Count; i++) { var node = model.Nodes[i]; if (node.ParentIndex >= 0) { allNodes[node.ParentIndex].Children.Add(allNodes[i]); } else { scene.RootNode.Children.Add(allNodes[i]); } } #endregion var meshLookup = new List <int>(); #region Meshes for (int i = 0; i < model.Meshes.Count; i++) { var geom = model.Meshes[i]; if (geom.Submeshes.Count == 0) { meshLookup.Add(-1); continue; } meshLookup.Add(scene.MeshCount); foreach (var sub in geom.Submeshes) { var m = new Assimp.Mesh($"mesh{i:D3}"); var indices = geom.Indicies.Skip(sub.IndexStart).Take(sub.IndexLength); var minIndex = indices.Min(); var maxIndex = indices.Max(); var vertCount = maxIndex - minIndex + 1; if (geom.IndexFormat == IndexFormat.TriangleStrip) { indices = indices.Unstrip(); } indices = indices.Select(x => x - minIndex); var vertices = geom.Vertices.Skip(minIndex).Take(vertCount); if (geom.BoundsIndex >= 0) { vertices = vertices.Select(v => (IVertex) new CompressedVertex(v, model.Bounds[geom.BoundsIndex.Value])); } int vIndex = -1; var boneLookup = new Dictionary <int, Assimp.Bone>(); foreach (var v in vertices) { vIndex++; if (v.Position.Count > 0) { m.Vertices.Add(v.Position[0].ToAssimp3D(scale)); //some Halo shaders use position W as the colour alpha - add it to a colour channel to preserve it //also assimp appears to have issues exporting obj when a colour channel exists so only do this for collada if (formatId == "collada" && v.Color.Count == 0 && !float.IsNaN(v.Position[0].W)) { m.VertexColorChannels[0].Add(new Assimp.Color4D { R = v.Position[0].W }); } } if (v.Normal.Count > 0) { m.Normals.Add(v.Normal[0].ToAssimp3D()); } if (v.TexCoords.Count > 0) { m.TextureCoordinateChannels[0].Add(v.TexCoords[0].ToAssimpUV()); } if (geom.VertexWeights == VertexWeights.None && !geom.NodeIndex.HasValue) { continue; } #region Vertex Weights var weights = new List <Tuple <int, float> >(4); if (geom.NodeIndex.HasValue) { weights.Add(Tuple.Create <int, float>(geom.NodeIndex.Value, 1)); } else if (geom.VertexWeights == VertexWeights.Skinned) { var ind = v.BlendIndices[0]; var wt = v.BlendWeight[0]; if (wt.X > 0) { weights.Add(Tuple.Create((int)ind.X, wt.X)); } if (wt.Y > 0) { weights.Add(Tuple.Create((int)ind.Y, wt.Y)); } if (wt.Z > 0) { weights.Add(Tuple.Create((int)ind.Z, wt.Z)); } if (wt.W > 0) { weights.Add(Tuple.Create((int)ind.W, wt.W)); } } foreach (var val in weights) { Assimp.Bone b; if (boneLookup.ContainsKey(val.Item1)) { b = boneLookup[val.Item1]; } else { var t = model.Nodes[val.Item1].OffsetTransform; t.M41 *= scale; t.M42 *= scale; t.M43 *= scale; b = new Assimp.Bone { Name = bonePrefix + model.Nodes[val.Item1].Name, OffsetMatrix = t.ToAssimp4x4() }; m.Bones.Add(b); boneLookup.Add(val.Item1, b); } b.VertexWeights.Add(new Assimp.VertexWeight(vIndex, val.Item2)); } #endregion } m.SetIndices(indices.ToArray(), 3); m.MaterialIndex = sub.MaterialIndex; scene.Meshes.Add(m); } } #endregion #region Regions foreach (var reg in model.Regions) { var regNode = new Assimp.Node($"{geomPrefix}{reg.Name}"); foreach (var perm in reg.Permutations) { var meshStart = meshLookup[perm.MeshIndex]; if (meshStart < 0) { continue; } var permNode = new Assimp.Node($"{geomPrefix}{perm.Name}"); if (perm.TransformScale != 1 || !perm.Transform.IsIdentity) { permNode.Transform = Assimp.Matrix4x4.FromScaling(new Assimp.Vector3D(perm.TransformScale)) * perm.Transform.ToAssimp4x4(scale); } var meshCount = Enumerable.Range(perm.MeshIndex, perm.MeshCount).Sum(i => model.Meshes[i].Submeshes.Count); permNode.MeshIndices.AddRange(Enumerable.Range(meshStart, meshCount)); regNode.Children.Add(permNode); } if (regNode.ChildCount > 0) { scene.RootNode.Children.Add(regNode); } } #endregion #region Materials foreach (var mat in model.Materials) { var m = new Assimp.Material { Name = mat?.Name ?? "unused" }; //prevent max from making every material super shiny m.ColorEmissive = m.ColorReflective = m.ColorSpecular = new Assimp.Color4D(0, 0, 0, 1); m.ColorDiffuse = m.ColorTransparent = new Assimp.Color4D(1); //max only seems to care about diffuse var dif = mat?.Submaterials.FirstOrDefault(s => s.Usage == MaterialUsage.Diffuse); if (dif != null) { var suffix = dif.Bitmap.SubmapCount > 1 ? "[0]" : string.Empty; var filePath = $"{dif.Bitmap.Name}{suffix}.{ModelViewerPlugin.Settings.MaterialExtension}"; //collada spec says it requires URI formatting, and Assimp doesn't do it for us //for some reason "new Uri(filePath, UriKind.Relative)" doesnt change the slashes, have to use absolute uri if (formatId == FormatId.Collada) { filePath = new Uri("X:\\", UriKind.Absolute).MakeRelativeUri(new Uri(System.IO.Path.Combine("X:\\", filePath))).ToString(); } m.TextureDiffuse = new Assimp.TextureSlot { BlendFactor = 1, FilePath = filePath, TextureType = Assimp.TextureType.Diffuse }; } scene.Materials.Add(m); } #endregion return(scene); }
public static List <Item> ImportFromFile(string filePath, EditorCamera camera, out bool errorFlag, out string errorMsg, EditorItemSelection selectionManager, OnScreenDisplay osd, bool multiple = false) { List <Item> createdItems = new List <Item>(); if (!File.Exists(filePath)) { errorFlag = true; errorMsg = "File does not exist!"; return(null); } DirectoryInfo filePathInfo = new DirectoryInfo(filePath); bool importError = false; string importErrorMsg = ""; Vector3 pos = camera.Position + (-20 * camera.Look); switch (filePathInfo.Extension) { case ".sa1mdl": ModelFile mf = new ModelFile(filePath); NJS_OBJECT objm = mf.Model; osd.ClearMessageList(); osd.AddMessage("Importing models, please wait...", 3000); osd.ClearMessageList(); createdItems.AddRange(ImportFromHierarchy(objm, selectionManager, osd, multiple)); osd.AddMessage("Stage import complete!", 100); break; case ".obj": case ".objf": LevelItem item = new LevelItem(filePath, new Vertex(pos.X, pos.Y, pos.Z), new Rotation(), levelItems.Count, selectionManager) { Visible = true }; createdItems.Add(item); break; case ".txt": NodeTable.ImportFromFile(filePath, out importError, out importErrorMsg, selectionManager); break; case ".dae": case ".fbx": Assimp.AssimpContext context = new Assimp.AssimpContext(); Assimp.Configs.FBXPreservePivotsConfig conf = new Assimp.Configs.FBXPreservePivotsConfig(false); context.SetConfig(conf); Assimp.Scene scene = context.ImportFile(filePath, Assimp.PostProcessSteps.Triangulate); for (int i = 0; i < scene.RootNode.ChildCount; i++) { osd.ClearMessageList(); osd.AddMessage("Importing model " + i.ToString() + " of " + scene.RootNode.ChildCount.ToString() + "...", 3000); Assimp.Node child = scene.RootNode.Children[i]; List <Assimp.Mesh> meshes = new List <Assimp.Mesh>(); foreach (int j in child.MeshIndices) { meshes.Add(scene.Meshes[j]); } bool isVisible = true; for (int j = 0; j < child.MeshCount; j++) { if (scene.Materials[meshes[j].MaterialIndex].Name.Contains("Collision")) { isVisible = false; break; } } ModelFormat mfmt = ModelFormat.Basic; if (isVisible) { switch (geo.Format) { case LandTableFormat.SA2: mfmt = ModelFormat.Chunk; break; case LandTableFormat.SA2B: mfmt = ModelFormat.GC; break; } } NJS_OBJECT obj = AssimpStuff.AssimpImport(scene, child, mfmt, TextureBitmaps[leveltexs].Select(a => a.Name).ToArray(), !multiple); { //sa2 collision patch if (obj.Attach.GetType() == typeof(BasicAttach)) { BasicAttach ba = obj.Attach as BasicAttach; foreach (NJS_MATERIAL mats in ba.Material) { mats.DoubleSided = true; } } //cant check for transparent texture so i gotta force alpha for now, temporary else if (obj.Attach.GetType() == typeof(ChunkAttach)) { ChunkAttach ca = obj.Attach as ChunkAttach; foreach (PolyChunk polys in ca.Poly) { if (polys.GetType() == typeof(PolyChunkMaterial)) { PolyChunkMaterial mat = polys as PolyChunkMaterial; mat.SourceAlpha = AlphaInstruction.SourceAlpha; mat.DestinationAlpha = AlphaInstruction.InverseSourceAlpha; } else if (polys.GetType() == typeof(PolyChunkStrip)) { PolyChunkStrip str = polys as PolyChunkStrip; //str.UseAlpha = true; } } } } obj.Attach.ProcessVertexData(); LevelItem newLevelItem = new LevelItem(obj.Attach, new Vertex(obj.Position.X + pos.X, obj.Position.Y + pos.Y, obj.Position.Z + pos.Z), obj.Rotation, levelItems.Count, selectionManager) { Visible = isVisible }; createdItems.Add(newLevelItem); } osd.ClearMessageList(); osd.AddMessage("Stage import complete!", 100); break; default: errorFlag = true; errorMsg = "Invalid file format!"; return(null); } StateChanged(); errorFlag = importError; errorMsg = importErrorMsg; return(createdItems); }
protected unsafe override bool OnLoad(Model model, File stream) { var filePath = FileUtil.StandardlizeFile(stream.Name); filePath = FileUtil.GetPath(stream.Name); FileSystem.AddResourceDir(filePath); FileSystem.AddResourceDir(filePath + "textures"); var ctx = new Assimp.AssimpContext(); string ext = FileUtil.GetExtension(loadingFile); if (!ctx.IsImportFormatSupported(ext)) { ctx.Dispose(); return(false); } //Assimp.Scene scene = ctx.ImportFileFromStream(stream, assimpFlags, ext); Assimp.Scene scene = ctx.ImportFile(stream.Name, assimpFlags); BoundingBox boundingBox = new BoundingBox(); string path = FileUtil.GetPath(loadingFile); model.VertexBuffers = new List <Buffer>(); model.IndexBuffers = new List <Buffer>(); vertexBuffer.Clear(); indexBuffer.Clear(); vertexOffset = 0; indexOffset = 0; VertexLayout vertexLayout = new VertexLayout(vertexComponents); List <Geometry> geoList = new List <Geometry>(); // Iterate through all meshes in the file and extract the vertex components for (int m = 0; m < scene.MeshCount; m++) { Assimp.Mesh mesh = scene.Meshes[m]; if (mesh.MaterialIndex >= 0 && mesh.MaterialIndex < scene.MaterialCount) { Material mat = ConvertMaterial(path, scene.Materials[mesh.MaterialIndex], mesh.HasTangentBasis); if (mat == null) { continue; } model.Materials.Add(mat); } else { Log.Error("No material : " + mesh.Name); } var geometry = ConvertGeometry(mesh, scale, vertexLayout, vertexComponents, combineVB, combineIB, out var meshBoundingBox); geoList.Add(geometry); if (geometry.VertexBuffer != null) { model.VertexBuffers.Add(geometry.VertexBuffer); } if (geometry.IndexBuffer != null) { model.IndexBuffers.Add(geometry.IndexBuffer); } model.Geometries.Add(new [] { geometry }); model.GeometryCenters.Add(meshBoundingBox.Center); boundingBox.Merge(meshBoundingBox); } if (combineVB) { var vb = Buffer.Create(VkBufferUsageFlags.VertexBuffer, false, sizeof(float), vertexBuffer.Count, vertexBuffer.Data); model.VertexBuffers.Add(vb); foreach (var geo in geoList) { geo.VertexBuffer = vb; } } if (combineIB) { var ib = Buffer.Create(VkBufferUsageFlags.IndexBuffer, false, sizeof(uint), indexBuffer.Count, indexBuffer.Data); model.IndexBuffers.Add(ib); foreach (var geo in geoList) { geo.IndexBuffer = ib; } } model.BoundingBox = boundingBox; ctx.Dispose(); FileSystem.RemoveResourceDir(filePath); FileSystem.RemoveResourceDir(filePath + "textures"); return(true); }
private void OnSetFileAssociations(object sender, EventArgs e) { using (var imp = new Assimp.AssimpContext()) { var list = imp.GetSupportedImportFormats(); // do not associate .xml - it is too generic var filteredList = list.Where(s => s != ".xml").ToArray(); var listString = string.Join(", ", filteredList); if(DialogResult.OK == MessageBox.Show(this, "The following file extensions will be associated with open3mod: " + listString, "Set file associations", MessageBoxButtons.OKCancel)) { if (!FileAssociations.SetAssociations(list)) { MessageBox.Show(this, "Failed to set file extensions","Error",MessageBoxButtons.OK,MessageBoxIcon.Error); } else { MessageBox.Show(this, "File extensions have been successfully associated", "open3mod", MessageBoxButtons.OK, MessageBoxIcon.Information); } } } }
private void OnDrag(object sender, DragEventArgs e) { // code based on http://www.codeproject.com/Articles/3598/Drag-and-Drop try { var a = (Array)e.Data.GetData(DataFormats.FileDrop); if (a != null && a.GetLength(0) > 0) { for (int i = 0, count = a.GetLength(0); i < count; ++i) { var s = a.GetValue(i).ToString(); // check if the dragged file is a folder. In this case, // we load all applicable files in the folder. // TODO this means, files with no proper file extension // won't load this way. try { FileAttributes attr = File.GetAttributes(s); if (attr.HasFlag(FileAttributes.Directory)) { string[] formats; using (var tempImporter = new Assimp.AssimpContext()) { formats = tempImporter.GetSupportedImportFormats(); } string[] files = Directory.GetFiles(s); foreach (var file in files) { var ext = Path.GetExtension(file); if (ext == null) { continue; } var lowerExt = ext.ToLower(); if (formats.Any(format => lowerExt == format)) { AddTab(file); } } continue; } } // ReSharper disable EmptyGeneralCatchClause catch (Exception) // ReSharper restore EmptyGeneralCatchClause { // ignore this - AddTab() handles the failure } // Call OpenFile asynchronously. // Explorer instance from which file is dropped is not responding // all the time when DragDrop handler is active, so we need to return // immediately (of particular importance if OpenFile shows MessageBox). AddTab(s); } // in the case Explorer overlaps this form Activate(); } } catch (Exception ex) { Trace.WriteLine("Error in DragDrop function: " + ex.Message); } }
public override IDisposable Load(Type resourceType, string identifier) { using (var assimpContext = new Assimp.AssimpContext()) { var scene = assimpContext.ImportFile(identifier); var meshes = new List<Graphics.Mesh>(); foreach (var mesh in scene.Meshes) { var bytesPerVertex = 12; if (mesh.HasNormals) { bytesPerVertex += 12; } if (mesh.HasTextureCoords(0)) { bytesPerVertex += 8; } var vertexCount = mesh.VertexCount; var meshSizeInBytes = vertexCount * bytesPerVertex; using (var stream = new SlimDX.DataStream(meshSizeInBytes, true, true)) { for (var i = 0; i < vertexCount; ++i) { stream.Write(mesh.Vertices[i]); if (mesh.HasNormals) { stream.Write(mesh.Normals[i]); } if (mesh.HasTextureCoords(0)) { stream.Write(mesh.TextureCoordinateChannels[0][i].X); stream.Write(mesh.TextureCoordinateChannels[0][i].Y); } } var vertexBuffer = new Graphics.VertexBuffer(device.Handle, stream, bytesPerVertex, vertexCount, SlimDX.Direct3D11.PrimitiveTopology.TriangleList); var indices = mesh.GetIndices(); if (indices != null && indices.Count() > 0) { var indexBuffer = new Graphics.IndexBuffer(device.Handle, indices); return new Graphics.Mesh(vertexBuffer, indexBuffer); } var result = new Graphics.Mesh(vertexBuffer); if (resourceType.Equals(typeof(Graphics.Mesh))) { return result; } else { meshes.Add(result); } } } if (meshes.Count > 0) { return new Graphics.MeshGroup(meshes); } else { throw new KeyNotFoundException("Failed to load mesh: " + identifier); } } }
private static void ImportDAEFile(ResourceWrapper res, string path) { var ctx = new Assimp.AssimpContext(); res.WrappedObject = new RWScene(ctx.ImportFile(path)); }
private static void ExportOBJFile(ResourceWrapper res, string path) { var scene = (res as RWSceneWrapper).WrappedObject; var ctx = new Assimp.AssimpContext(); ctx.ExportFile(RWScene.ToAssimpScene(scene), path, "obj"); }