/
Edwar
/
cam-api-examples
Обзор
Документация
Войти
/
Edwar
/
cam-api-examples
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
Geometry/ExtensionUtilityGeomCustomImportNet/project/main/ExtensionImportObj.cs
209 строк
8 KB
Edwar
Несколько исправлений в импортер obj файлов
06 июл 2025, 13:17
06 июл 2025, 13:17
d599963
Код
Авторство
О чём код?
using CAMAPI.Application; using CAMAPI.DotnetHelper; using CAMAPI.Extensions; using CAMAPI.ResultStatus; using CAMAPI.Singletons; using CAMAPI.UIDialogs.DotnetHelper; using Geometry.VecMatrLib; using STGeomApiTypes; using STTypes; using System.Text.RegularExpressions; using System.Globalization; using System.Reflection.Metadata.Ecma335; using System.Runtime.CompilerServices; namespace ExtensionUtilityGeomCustomImportNet; /// <summary> /// Utility to import obj file /// </summary> public class ExtensionImportObj : IExtension, IExtensionUtility { /// <inheritdoc /> public IExtensionInfo? Info { get; set; } private static void AddMeshes(ISTGeomFiler geomFile, string objFileName) { try { //double scale = 1.0; string? str; int faceI = 0; IEnumerable<int> corners = []; int vertex_idx = 1; string meshName = "obj"; geomFile.StartMesh(meshName); bool meshStarted = true; using StreamReader reader = new(objFileName); while ((str = reader.ReadLine()) != null) { int current = 0; char[] output = new char[str.Length]; bool skipped = false; foreach (char c in str.ToCharArray()) { if (char.IsWhiteSpace(c)) { if (!skipped) { if (current > 0) output[current++] = ' '; skipped = true; } } else { skipped = false; output[current++] = c; } } str = new string(output, 0, current); string[] words = str.Split(' '); switch (words[0]) { case "mtllib": //material name //mtllib material.mtl break; case "o": //object name //o object_name if (meshStarted) { geomFile.CloseMesh(); geomFile.AddEntity(meshName, meshName); geomFile.StartMesh(words[1]); } meshName = words[1]; vertex_idx = 1; break; case "v": //vertex coordinates //v 0.100366 1.411534 -0.187347 TST3DPoint vertex = new() { X = double.Parse(words[1], System.Globalization.CultureInfo.InvariantCulture),// * scale, Y = double.Parse(words[2], System.Globalization.CultureInfo.InvariantCulture),// * scale, Z = double.Parse(words[3], System.Globalization.CultureInfo.InvariantCulture) //* scale }; geomFile.AddMeshVertex(vertex_idx, vertex); vertex_idx += 1; break; case "vn": //vertex normal //vn 0.9627 -0.2379 0.1293 break; case "vt": //vertex texture coordinates //vt 0.129600 0.924000 break; case "f": //triangle face data //f 994/1061/965 993/1060/964 1025/1095/996 //f vertexIndex/textureCoordinateIndex/normalIndex vertexIndex/textureCoordinateIndex/normalIndex vertexIndex/textureCoordinateIndex/normalIndex corners = []; faceI = 0; foreach (string word in words[1..]) { corners = corners.Append( Convert.ToInt32( word.Split('/')[0] ) ); if (faceI >= 2) { geomFile.AddMeshTriangle(corners.ElementAt(0), corners.ElementAt(faceI - 1), corners.ElementAt(faceI)); } faceI += 1; } break; default: break; } } geomFile.CloseMesh(); geomFile.AddEntity(meshName, meshName); reader.Close(); } catch (IOException e) { Console.WriteLine("The file could not be read:"); Console.WriteLine(e.Message); } } /// <inheritdoc /> public void Run(IExtensionUtilityContext context, out TResultStatus resultStatus) { resultStatus = default; try { using var helperCom = UIDialogs.CreateHelper(); var helper = helperCom.Instance ?? throw new Exception("Failed to create UIDialogs helper"); string objFileName = Path.Combine(Directory.GetCurrentDirectory()); objFileName = helper.SelectFileDialog("Select *.obj file", "*.obj", objFileName); if (string.IsNullOrEmpty(objFileName)) return; if (!File.Exists(objFileName)) throw new Exception("File not found: " + objFileName); var sgfFilePath = Path.Combine(Directory.GetCurrentDirectory(), Path.GetFileNameWithoutExtension(objFileName) + ".sgf"); // create object to write geometry using var wrapperFactoryGeomFiler = SystemExtensionFactory.GetSingletonExtension<ICamApiFactoryGeometryFile>("Extension.Global.Singletons.GeomFile"); var factoryGeomFiler = wrapperFactoryGeomFiler.Instance ?? throw new Exception("Can't get geometry filer singleton"); using var wrapperGeomFile = new ComWrapper<ISTGeomFiler>(factoryGeomFiler.CreateObject()); var geomFile = wrapperGeomFile.Instance ?? throw new Exception("Can't create geometry filer object"); // beginning of the file if (!geomFile.StartFile(sgfFilePath)) throw new Exception("Can't start file: " + sgfFilePath); geomFile.StartModel(); try { try { // set point, we are going to use it as a coordinate system geomFile.SetCurrentTransform(T3DMatrix.Unit.vT, T3DMatrix.Unit.vZ, T3DMatrix.Unit.vX); // item in geometry objects tree geomFile.StartGroupEntity("meshes"); try { AddMeshes(geomFile, objFileName); } finally { geomFile.CloseGroupEntity(); } } finally { geomFile.CloseModel(); } } finally { geomFile.CloseFile(); } ImportHelper.Import(context, sgfFilePath); } catch (Exception e) { resultStatus.Code = TResultStatusCode.rsError; resultStatus.Description = e.Message; } } }