private static void LoadLinkedMesh(this IObject3D item, CacheContext cacheContext, CancellationToken cancellationToken, Action <double, string> progress) { // Abort load if cancel requested cancellationToken.ThrowIfCancellationRequested(); // ************************************************************************* // TODO: Fix invalid use of Result // ************************************************************************* string filePath = item.ResolveFilePath(progress, cancellationToken).Result; if (string.Equals(Path.GetExtension(filePath), ".mcx", StringComparison.OrdinalIgnoreCase)) { var loadedItem = Object3D.Load(filePath, cancellationToken, cacheContext, progress); if (loadedItem != null) { item.SetMeshDirect(loadedItem.Mesh); // Copy loaded mcx children to source node // TODO: potentially needed for leaf mcx nodes, review and tests required item.Children = loadedItem.Children; } } else { Mesh mesh = null; try { if (!cacheContext.Meshes.TryGetValue(filePath, out mesh)) { mesh = Object3D.Load(filePath, cancellationToken).Mesh; cacheContext.Meshes[filePath] = mesh; } } catch { // Fall back to Missing mesh if available mesh = Object3D.FileMissingMesh; } item.SetMeshDirect(mesh); } }
public string StoreStream(Stream stream, string extension) { // Compute SHA1 string sha1 = Object3D.ComputeSHA1(stream); string fileName = $"{sha1}{extension}"; string assetPath = Path.Combine(Object3D.AssetsPath, fileName); // Load cache if (!File.Exists(assetPath)) { stream.Position = 0; using (var outstream = File.OpenWrite(assetPath)) { stream.CopyTo(outstream); } } return(fileName); }
public async Task <string> StoreFile(string filePath, bool publishAfterSave, CancellationToken cancellationToken, Action <double, string> progress) { // Compute SHA1 string sha1 = Object3D.ComputeFileSHA1(filePath); string sha1PlusExtension = sha1 + Path.GetExtension(filePath).ToLower(); string assetPath = Path.Combine(Object3D.AssetsPath, sha1PlusExtension); // Load cache if (!File.Exists(assetPath)) { File.Copy(filePath, assetPath); } await ConditionalPublish( sha1PlusExtension, publishAfterSave, cancellationToken, progress); return(sha1PlusExtension); }
public async Task <string> StoreMcx(IObject3D object3D, bool publishAfterSave) { // TODO: Track SHA1 of persisted asset // TODO: Skip if cached sha1 exists in assets // Serialize object3D to in memory mcx/json stream using (var memoryStream = new MemoryStream()) { // Write JSON object3D.SaveTo(memoryStream); // Reposition memoryStream.Position = 0; Directory.CreateDirectory(Object3D.AssetsPath); // Calculate string sha1 = Object3D.ComputeSHA1(memoryStream); string sha1PlusExtension = sha1 + ".mcx"; string assetPath = Path.Combine(Object3D.AssetsPath, sha1PlusExtension); if (!File.Exists(assetPath)) { memoryStream.Position = 0; using (var outStream = File.Create(assetPath)) { memoryStream.CopyTo(outStream); } } await ConditionalPublish( sha1PlusExtension, publishAfterSave, CancellationToken.None, null); return(assetPath); } }
public InteractiveScene() { SourceItem = new Object3D(); }
public static IObject3D Load(Stream fileStream, Action <double, string> reportProgress = null, IObject3D source = null) { IObject3D root = source ?? new Object3D(); var time = Stopwatch.StartNew(); // LOAD THE MESH DATA var objFile = new Obj(); objFile.LoadObj(fileStream); IObject3D context = new Object3D(); root.Children.Add(context); var mesh = new Mesh(); context.SetMeshDirect(mesh); foreach (var vertex in objFile.VertexList) { mesh.Vertices.Add(new Vector3Float(vertex.X, vertex.Y, vertex.Z)); } foreach (var face in objFile.FaceList) { for (int i = 0; i < face.VertexIndexList.Length; i++) { if (face.VertexIndexList[i] >= objFile.TextureList.Count) { int a = 0; } } mesh.Faces.Add(face.VertexIndexList[0] - 1, face.VertexIndexList[1] - 1, face.VertexIndexList[2] - 1, mesh.Vertices); if (face.VertexIndexList.Length == 4) { // add the other side of the quad mesh.Faces.Add(face.VertexIndexList[0] - 1, face.VertexIndexList[2] - 1, face.VertexIndexList[3] - 1, mesh.Vertices); } } // load and apply any texture if (objFile.Material != "") { // TODO: have consideration for this being in a shared zip file string pathToObj = Path.GetDirectoryName(((FileStream)fileStream).Name); //Try-catch block for when objFile.Material is not found try { using (var materialsStream = File.OpenRead(Path.Combine(pathToObj, objFile.Material))) { var mtl = new Mtl(); mtl.LoadMtl(materialsStream); foreach (var material in mtl.MaterialList) { if (!string.IsNullOrEmpty(material.DiffuseTextureFileName)) { var pathToTexture = Path.Combine(pathToObj, material.DiffuseTextureFileName); if (File.Exists(pathToTexture)) { var diffuseTexture = new ImageBuffer(); // TODO: have consideration for this being in a shared zip file using (var imageStream = File.OpenRead(pathToTexture)) { if (Path.GetExtension(material.DiffuseTextureFileName).ToLower() == ".tga") { ImageTgaIO.LoadImageData(diffuseTexture, imageStream, 32); } else { ImageIO.LoadImageData(imageStream, diffuseTexture); } } if (diffuseTexture.Width > 0 && diffuseTexture.Height > 0) { int meshFace = 0; for (int objFace = 0; objFace < objFile.FaceList.Count; objFace++, meshFace++) { var face = mesh.Faces[meshFace]; var faceData = objFile.FaceList[objFace]; int textureIndex0 = faceData.TextureVertexIndexList[0] - 1; var uv0 = new Vector2Float(objFile.TextureList[textureIndex0].X, objFile.TextureList[textureIndex0].Y); int textureIndex1 = faceData.TextureVertexIndexList[1] - 1; var uv1 = new Vector2Float(objFile.TextureList[textureIndex1].X, objFile.TextureList[textureIndex1].Y); int textureIndex2 = faceData.TextureVertexIndexList[2] - 1; var uv2 = new Vector2Float(objFile.TextureList[textureIndex2].X, objFile.TextureList[textureIndex2].Y); mesh.FaceTextures.Add(meshFace, new FaceTextureData(diffuseTexture, uv0, uv1, uv2)); if (faceData.TextureVertexIndexList.Length == 4) { meshFace++; int textureIndex3 = faceData.TextureVertexIndexList[3] - 1; var uv3 = new Vector2Float(objFile.TextureList[textureIndex3].X, objFile.TextureList[textureIndex3].Y); mesh.FaceTextures.Add(meshFace, new FaceTextureData(diffuseTexture, uv0, uv2, uv3)); } } context.Color = Color.White; root.Color = Color.White; } } } } } } catch (FileNotFoundException) { // Just continue as if obj.Material == "" to show object } } time.Stop(); Debug.WriteLine(string.Format("OBJ Load in {0:0.00}s", time.Elapsed.TotalSeconds)); time.Restart(); bool hasValidMesh = root.Children.Where(item => item.Mesh.Faces.Count > 0).Any(); Debug.WriteLine("hasValidMesh: " + time.ElapsedMilliseconds); reportProgress?.Invoke(1, ""); return(hasValidMesh ? root : null); }
public static IObject3D Load(Stream fileStream, CancellationToken cancellationToken, Action <double, string> reportProgress = null, IObject3D source = null) { IObject3D root = source ?? new Object3D(); Stopwatch time = Stopwatch.StartNew(); // LOAD THE MESH DATA Obj objFile = new Obj(); objFile.LoadObj(fileStream); IObject3D context = new Object3D(); root.Children.Add(context); var mesh = new Mesh(); context.SetMeshDirect(mesh); foreach (var vertex in objFile.VertexList) { mesh.CreateVertex(vertex.X, vertex.Y, vertex.Z, CreateOption.CreateNew, SortOption.WillSortLater); } foreach (var face in objFile.FaceList) { List <int> zeroBased = new List <int>(face.VertexIndexList.Length); foreach (var index in face.VertexIndexList) { zeroBased.Add(index - 1); } mesh.CreateFace(zeroBased.ToArray(), CreateOption.CreateNew); } // load and apply any texture if (objFile.Material != "") { // TODO: have consideration for this being in a shared zip file string pathToObj = Path.GetDirectoryName(((FileStream)fileStream).Name); using (var materialsStream = File.OpenRead(Path.Combine(pathToObj, objFile.Material))) { var mtl = new Mtl(); mtl.LoadMtl(materialsStream); foreach (var material in mtl.MaterialList) { if (!string.IsNullOrEmpty(material.DiffuseTextureFileName)) { var pathToTexture = Path.Combine(pathToObj, material.DiffuseTextureFileName); if (File.Exists(pathToTexture)) { ImageBuffer diffuseTexture = new ImageBuffer(); // TODO: have consideration for this being in a shared zip file using (var ImageStream = File.OpenRead(pathToTexture)) { if (Path.GetExtension(material.DiffuseTextureFileName).ToLower() == ".tga") { ImageTgaIO.LoadImageData(diffuseTexture, ImageStream, 32); } else { AggContext.ImageIO.LoadImageData(ImageStream, diffuseTexture); } } if (diffuseTexture.Width > 0 && diffuseTexture.Height > 0) { for (int faceIndex = 0; faceIndex < objFile.FaceList.Count; faceIndex++) { var faceData = objFile.FaceList[faceIndex]; var polyFace = mesh.Faces[faceIndex]; polyFace.SetTexture(0, diffuseTexture); int edgeIndex = 0; foreach (FaceEdge faceEdge in polyFace.FaceEdges()) { int textureIndex = faceData.TextureVertexIndexList[edgeIndex] - 1; faceEdge.SetUv(0, new Vector2(objFile.TextureList[textureIndex].X, objFile.TextureList[textureIndex].Y)); edgeIndex++; } } context.Color = Color.White; root.Color = Color.White; } } } } } } time.Stop(); Debug.WriteLine(string.Format("OBJ Load in {0:0.00}s", time.Elapsed.TotalSeconds)); time.Restart(); bool hasValidMesh = root.Children.Where(item => item.Mesh.Faces.Count > 0).Any(); Debug.WriteLine("hasValidMesh: " + time.ElapsedMilliseconds); reportProgress?.Invoke(1, ""); return((hasValidMesh) ? root : null); }
public static IObject3D Load(Stream fileStream, CancellationToken cancellationToken, Action <double, string> reportProgress = null) { IObject3D root = new Object3D(); IObject3D context = null; int totalMeshes = 0; var time = Stopwatch.StartNew(); var materials = new Dictionary <int, (string name, Color color, int material, PrintOutputTypes output)>(); var itemPropertiesDictionary = new Dictionary <IObject3D, int>(); using (var decompressedStream = GetCompressedStreamIfRequired(fileStream)) { using (var reader = XmlReader.Create(decompressedStream)) { List <Vector3> vertices = null; Mesh mesh = null; var progressData = new ProgressData(fileStream, reportProgress); while (reader.Read()) { if (!reader.IsStartElement()) { continue; } switch (reader.Name) { case "object": break; case "mesh": break; case "vertices": vertices = ReadAllVertices(reader, progressData); break; case "volume": context = new Object3D(); root.Children.Add(context); mesh = new Mesh(); context.SetMeshDirect(mesh); totalMeshes += 1; string materialId; ReadVolume(reader, vertices, mesh, progressData, out materialId); int.TryParse(materialId, out int id); itemPropertiesDictionary.Add(context, id); break; case "material": ReadProperties(reader, materials); break; } } } fileStream.Dispose(); } foreach (var keyValue in itemPropertiesDictionary) { if (materials.TryGetValue(keyValue.Value, out (string name, Color color, int material, PrintOutputTypes output)data)) { keyValue.Key.Name = data.name; keyValue.Key.Color = data.color; keyValue.Key.MaterialIndex = data.material; keyValue.Key.OutputType = data.output; } } time.Stop(); Debug.WriteLine(string.Format("AMF Load in {0:0.00}s", time.Elapsed.TotalSeconds)); time.Restart(); bool hasValidMesh = root.Children.Where(item => item.Mesh.Faces.Count > 0).Any(); Debug.WriteLine("hasValidMesh: " + time.ElapsedMilliseconds); reportProgress?.Invoke(1, ""); return(hasValidMesh ? root : null); }
public static IObject3D Load(Stream fileStream, CancellationToken cancellationToken, Action <double, string> reportProgress = null) { IObject3D root = new Object3D(); IObject3D context = null; int totalMeshes = 0; Stopwatch time = Stopwatch.StartNew(); Dictionary <string, ColorF> materials = new Dictionary <string, ColorF>(); Dictionary <IObject3D, string> objectMaterialDictionary = new Dictionary <IObject3D, string>(); using (var decompressedStream = GetCompressedStreamIfRequired(fileStream)) { using (var reader = XmlReader.Create(decompressedStream)) { List <Vector3> vertices = null; Mesh mesh = null; ProgressData progressData = new ProgressData(fileStream, reportProgress); while (reader.Read()) { if (!reader.IsStartElement()) { continue; } switch (reader.Name) { case "object": break; case "mesh": break; case "vertices": vertices = ReadAllVertices(reader, progressData); break; case "volume": context = new Object3D(); root.Children.Add(context); mesh = new Mesh(); context.SetMeshDirect(mesh); totalMeshes += 1; string materialId; ReadVolume(reader, vertices, mesh, progressData, out materialId); objectMaterialDictionary.Add(context, materialId); break; case "material": ReadMaterial(reader, materials); break; } } } fileStream.Dispose(); } foreach (var keyValue in objectMaterialDictionary) { ColorF color = ColorF.White; if (keyValue.Value == null || !materials.TryGetValue(keyValue.Value, out color)) { color = ColorF.White; } keyValue.Key.Color = color.ToColor(); } time.Stop(); Debug.WriteLine(string.Format("AMF Load in {0:0.00}s", time.Elapsed.TotalSeconds)); time.Restart(); bool hasValidMesh = root.Children.Where(item => item.Mesh.Faces.Count > 0).Any(); Debug.WriteLine("hasValidMesh: " + time.ElapsedMilliseconds); reportProgress?.Invoke(1, ""); return((hasValidMesh) ? root : null); }