diff --git a/Xbim.Presentation/Extensions/Utility/GeomUtils.cs b/Xbim.Presentation/Extensions/Utility/GeomUtils.cs index b9c09e8b..5c7b0254 100644 --- a/Xbim.Presentation/Extensions/Utility/GeomUtils.cs +++ b/Xbim.Presentation/Extensions/Utility/GeomUtils.cs @@ -73,5 +73,13 @@ public static Point3DCollection GetPointCollection(List points) } return ret; } + + public static Vector3D VectorProduct (this Vector3D vector1, Vector3D vector2) + { + double nx = vector1.Y * vector2.Z - vector1.Z * vector2.Y; + double ny = vector1.Z * vector2.X - vector1.X * vector2.Z; + double nz = vector1.X * vector2.Y - vector1.Y * vector2.X; + return new Vector3D(nx, ny, nz); + } } } diff --git a/Xbim.Presentation/LayerStyling/SurfaceLayerStyler.cs b/Xbim.Presentation/LayerStyling/SurfaceLayerStyler.cs index 3e70c1a6..c92d2e24 100644 --- a/Xbim.Presentation/LayerStyling/SurfaceLayerStyler.cs +++ b/Xbim.Presentation/LayerStyling/SurfaceLayerStyler.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; +using System.IO; using System.Linq; using System.Windows; using System.Windows.Media.Media3D; @@ -11,6 +12,7 @@ using Xbim.Common.Geometry; using Xbim.Ifc; using Xbim.Ifc4.Interfaces; +using Xbim.Presentation.Texturing; namespace Xbim.Presentation.LayerStyling { @@ -149,12 +151,31 @@ public XbimScene BuildScene(IModel model, XbimMa wpfMesh.Read(((XbimShapeGeometry) shapeGeom).ShapeData); break; } + repeatedShapeGeometries.Add(shapeInstance.ShapeGeometryLabel, wpfMesh); var mg = new GeometryModel3D(wpfMesh, materialsByStyleId[styleId]); mg.SetValue(FrameworkElement.TagProperty, new XbimInstanceHandle(model, shapeInstance.IfcProductLabel, shapeInstance.IfcTypeId)); mg.BackMaterial = mg.Material; mg.Transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, modelTransform).ToMatrixTransform3D(); + + //manual Texturemapping + if (materialsByStyleId[styleId].HasTexture + && mg.Geometry is MeshGeometry3D mesh3D) + { + ITextureMapping tMapping; + if (materialsByStyleId[styleId].IfcTextureCoordinate != null) + { + tMapping = TextureMappingFactory.CreateTextureMapping(materialsByStyleId[styleId].IfcTextureCoordinate); + } + else + { + Logger.LogWarning(0, "No IfcTextureCoordinate is defined for style " + styleId + ". Spherical mapping is used."); + tMapping = new SphericalTextureMap(); + } + mesh3D.TextureCoordinates.Concat(tMapping.GetTextureMap(mesh3D.Positions, mesh3D.Normals, mesh3D.TriangleIndices)); + } + if (materialsByStyleId[styleId].IsTransparent) tmpTransparentsGroup.Children.Add(mg); else @@ -182,12 +203,27 @@ public XbimScene BuildScene(IModel model, XbimMa if (shapeGeom.Format != (byte) XbimGeometryType.PolyhedronBinary) continue; var transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, modelTransform); + ITextureMapping textureMethod = null; + if (materialsByStyleId[styleId].HasTexture) + { + if (materialsByStyleId[styleId].IfcTextureCoordinate != null) + { + textureMethod = TextureMappingFactory.CreateTextureMapping(materialsByStyleId[styleId].IfcTextureCoordinate); + } + else + { + Logger.LogWarning(0, "No texture mapping method defined for style " + styleId + ". Spherical mapping is used."); + textureMethod = new SphericalTextureMap(); + } + } targetMergeMeshByStyle.Add( shapeGeom.ShapeData, shapeInstance.IfcTypeId, shapeInstance.IfcProductLabel, shapeInstance.InstanceLabel, transform, - (short) model.UserDefinedId); + (short) model.UserDefinedId, + textureMethod); + } } } @@ -227,7 +263,7 @@ protected IEnumerable GetShapeInstancesToRender(IGeometryStor protected static WpfMeshGeometry3D GetNewStyleMesh(WpfMaterial wpfMaterial, Model3DGroup tmpTransparentsGroup, Model3DGroup tmpOpaquesGroup) { - var mg = new WpfMeshGeometry3D(wpfMaterial, wpfMaterial); + var mg = new WpfMeshGeometry3D(wpfMaterial, wpfMaterial, wpfMaterial.IfcTextureCoordinate); mg.WpfModel.SetValue(FrameworkElement.TagProperty, mg); mg.BeginUpdate(); @@ -241,19 +277,57 @@ protected static WpfMeshGeometry3D GetNewStyleMesh(WpfMaterial wpfMaterial, Mode protected WpfMaterial GetWpfMaterial(IModel model, int styleId) { var sStyle = model.Instances[styleId] as IIfcSurfaceStyle; - var texture = XbimTexture.Create(sStyle); - if(texture.ColourMap.Count > 0) - { - if (texture.ColourMap[0].Alpha <= 0) + var wpfMaterial = new WpfMaterial(); + + //The style contains a texture + bool isTexture = false; + if (sStyle.Styles.Any(x => x is IIfcSurfaceStyleWithTextures)) + { + IIfcSurfaceStyleWithTextures surfaceStyleWithTexture = (IIfcSurfaceStyleWithTextures)sStyle.Styles.First(x => x is IIfcSurfaceStyleWithTextures); + if (surfaceStyleWithTexture.Textures.Any(x => x is IIfcImageTexture)) { - texture.ColourMap[0].Alpha = 0.5f; - Logger.LogWarning("Fully transparent style #{styleId} forced to 50% opacity.", styleId); + IIfcImageTexture imageTexture = surfaceStyleWithTexture.Textures.First(x => x is IIfcImageTexture) as IIfcImageTexture; + //generate the correct path + Uri imageUri; + if (Uri.TryCreate(imageTexture.URLReference, UriKind.Absolute, out imageUri)) + { + wpfMaterial.WpfMaterialFromImageTexture(imageUri); + } + else if (Uri.TryCreate(imageTexture.URLReference, UriKind.Relative, out imageUri)) + { + Uri modelFileUri = new Uri(model.Header.FileName.Name); + Uri absolutFileUri = new Uri(modelFileUri, imageTexture.URLReference); + wpfMaterial.WpfMaterialFromImageTexture(absolutFileUri); + } + else + { + Logger.LogWarning(0, "Invalid Uri " + imageTexture.URLReference + " (bad formatted or file not found).", imageTexture); + } + + if (imageTexture.IsMappedBy != null) + { + wpfMaterial.IfcTextureCoordinate = imageTexture.IsMappedBy.FirstOrDefault(); + } + isTexture = true; } } + + //The style doesn't contain a texture + if (isTexture == false) + { + var texture = XbimTexture.Create(sStyle); + if (texture.ColourMap.Count > 0) + { + if (texture.ColourMap[0].Alpha <= 0) + { + texture.ColourMap[0].Alpha = 0.5f; + Logger.LogWarning("Fully transparent style #{styleId} forced to 50% opacity.", styleId); + } + } - texture.DefinedObjectId = styleId; - var wpfMaterial = new WpfMaterial(); - wpfMaterial.CreateMaterial(texture); + texture.DefinedObjectId = styleId; + wpfMaterial.CreateMaterial(texture); + } return wpfMaterial; } diff --git a/Xbim.Presentation/Texturing/ITextureMapping.cs b/Xbim.Presentation/Texturing/ITextureMapping.cs new file mode 100644 index 00000000..b8c78fec --- /dev/null +++ b/Xbim.Presentation/Texturing/ITextureMapping.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media.Media3D; +using Xbim.Common; + +namespace Xbim.Presentation.Texturing +{ + public interface ITextureMapping + { + /// + /// returns the texture map for a given set of vertices + /// + /// a texture map for the related mesh + IEnumerable GetTextureMap(IEnumerable vertices, IEnumerable normals, IEnumerable triangles); + + /// + /// Method for the Texturing + /// + TextureMapGenerationMethod TexturingMethod {get;} + } +} diff --git a/Xbim.Presentation/Texturing/ManualTriangularTextureMapping.cs b/Xbim.Presentation/Texturing/ManualTriangularTextureMapping.cs new file mode 100644 index 00000000..9087e361 --- /dev/null +++ b/Xbim.Presentation/Texturing/ManualTriangularTextureMapping.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media.Media3D; +using Xbim.Common; +using Xbim.Ifc4.Interfaces; +using Xbim.Ifc4.MeasureResource; + +namespace Xbim.Presentation.Texturing +{ + public class ManualTriangularTextureMapping : ITextureMapping + { + /// + /// Manual map for texture coordinates. The index of the several vectors are related to the vertice index provided at GetTextureMap + /// + private IIfcIndexedTriangleTextureMap _ifcTextMap; + private int _numberOfVertices; + + public ManualTriangularTextureMapping(IIfcIndexedTriangleTextureMap textMap, int numberOfVertices) + { + _ifcTextMap = textMap; + _numberOfVertices = numberOfVertices; + } + + /// + /// Used Method for Texturing + /// + public TextureMapGenerationMethod TexturingMethod + { + get + { + return TextureMapGenerationMethod.MANUALTRIANGULAR; + } + } + + /// + /// returns the manual texture map + /// + /// + public IEnumerable GetTextureMap(IEnumerable vertices, IEnumerable normals, IEnumerable triangles) + { + IIfcTriangulatedFaceSet faceSet = _ifcTextMap.MappedTo as IIfcTriangulatedFaceSet; + Point[] result = new Point[_numberOfVertices]; + for (int triangleIdx = 0; triangleIdx < _ifcTextMap.TexCoordIndex.Count; triangleIdx++) + { + var texCoordTriangle = _ifcTextMap.TexCoordIndex[triangleIdx]; + for (int verticeIdx = 0; verticeIdx < texCoordTriangle.Count; verticeIdx++) + { + int texCoordIdx = (int)texCoordTriangle[verticeIdx] - 1; //ifc indexing is one based + int verticeRefIdx = (int)faceSet.CoordIndex[triangleIdx][verticeIdx] - 1; //ifc indexing is one based + + result[verticeRefIdx] = new Point(_ifcTextMap.TexCoords.TexCoordsList[texCoordIdx][0], _ifcTextMap.TexCoords.TexCoordsList[texCoordIdx][1]); + } + } + + return result; + } + } +} diff --git a/Xbim.Presentation/Texturing/SphericalTextureMap.cs b/Xbim.Presentation/Texturing/SphericalTextureMap.cs new file mode 100644 index 00000000..9ca7fe83 --- /dev/null +++ b/Xbim.Presentation/Texturing/SphericalTextureMap.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media.Media3D; +using Xbim.Common; + +namespace Xbim.Presentation.Texturing +{ + public class SphericalTextureMap : ITextureMapping + { + /// + /// Used Method for Texturing + /// + public TextureMapGenerationMethod TexturingMethod + { + get + { + return TextureMapGenerationMethod.SPHERE; + } + } + + /// + /// Calculates the texture by using the algorithm of spherical texture mapping + /// + /// A spherical texture map. The indices of the texture map are related + /// to the indices of the given vertices + public IEnumerable GetTextureMap(IEnumerable vertices, IEnumerable normals, IEnumerable triangles) + { + Point[] textureCoordinates = new Point[vertices.Count()]; + //Spherical uv mapping + //calculate mid point of the shape + double minX, minY, minZ, maxX, maxY, maxZ; + minX = vertices.Select(x => x.X).Min(); + maxX = vertices.Select(x => x.X).Max(); + minY = vertices.Select(x => x.Y).Min(); + maxY = vertices.Select(x => x.Y).Max(); + minZ = vertices.Select(x => x.Z).Min(); + maxZ = vertices.Select(x => x.Z).Max(); + Vector3D midPoint = new Vector3D((minX + maxX) / 2, (minY + maxY) / 2, (minZ + maxZ) / 2); + + Parallel.For(0, textureCoordinates.Length, (verticeIndex) => + { + Point3D meshPoint = vertices.ElementAt(verticeIndex); + Vector3D direction = (Vector3D)(meshPoint - midPoint); + double theta = Math.Acos(direction.Z / direction.Length); + if (direction.Z < 0) + { + theta *= -1; + } + + double phi; + if (direction.X > 0) + { + phi = Math.Atan(direction.Y / direction.X); + } + else if (direction.X == 0) + { + phi = Math.Sign(direction.Y) * Math.PI / 2.0; + } + else if (direction.X < 0 && direction.Y >= 0) + { + phi = Math.Atan(direction.Y / direction.X) + Math.PI; + } + else + { + phi = Math.Atan(direction.Y / direction.X) - Math.PI; + } + + //double u = Math.Sin(theta) * Math.Cos(phi); + //double v = Math.Sin(theta) * Math.Sin(phi); + double u = phi; + double v = theta; + + textureCoordinates[verticeIndex] = new Point(u, v); + }); + return textureCoordinates; + } + } +} diff --git a/Xbim.Presentation/Texturing/TextureMapGenerationMethod.cs b/Xbim.Presentation/Texturing/TextureMapGenerationMethod.cs new file mode 100644 index 00000000..d481a6c5 --- /dev/null +++ b/Xbim.Presentation/Texturing/TextureMapGenerationMethod.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Xbim.Presentation.Texturing +{ + /// + /// Methods to generate a texture + /// + public enum TextureMapGenerationMethod + { + /// + /// Manual mapping + /// + MANUALTRIANGULAR, + + /// + /// direct mapping of vertices and coordinates + /// + MANUALDIRECT, + + /// + /// Spherical mapping + /// + SPHERE, + + /// + /// Camera space normal mapping + /// + CAMERASPACENORMAL, + + /// + /// camera space position normal mapping + /// + CAMERASPACEPOSITION, + + /// + /// camera space reflection vector mapping + /// + CAMERASPACEREFLECTIONVECTOR, + SPHERE_LOCAL, + + /// + /// + /// + COORD, + + /// + /// + /// + COORD_EYE, + + /// + /// + /// + NOISE, + + /// + /// + /// + NOISE_EYE, + + /// + /// + /// + SPHERE_REFLECT, + + /// + /// + /// + SPHERE_REFLECT_LOCAL + } +} diff --git a/Xbim.Presentation/Texturing/TextureMappingFactory.cs b/Xbim.Presentation/Texturing/TextureMappingFactory.cs new file mode 100644 index 00000000..0b59b930 --- /dev/null +++ b/Xbim.Presentation/Texturing/TextureMappingFactory.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Windows.Media.Media3D; +using Xbim.Ifc4.Interfaces; + +namespace Xbim.Presentation.Texturing +{ + public static class TextureMappingFactory + { + /// + /// Create a spherical texture mapping + /// + /// A spherical mapping object for the given vertices + public static ITextureMapping CreateSphericalTextureMapping() + { + return new SphericalTextureMap(); + } + + /// + /// create a new manual texture mapping + /// + /// + /// + /// + public static ITextureMapping CreateManualTextureMapping(IIfcIndexedTriangleTextureMap textMap, int numberOfVertices) + { + return new ManualTriangularTextureMapping(textMap, numberOfVertices); + } + + /// + /// create the corresponding Texturemapping to a related texture coordinate element + /// + /// + /// + public static ITextureMapping CreateTextureMapping(IIfcTextureCoordinate textureCoordinate) + { + if (textureCoordinate is IIfcTextureMap) + { + return null; + } + else if (textureCoordinate is IIfcTextureCoordinateGenerator generator) + { + TextureMapGenerationMethod method = (TextureMapGenerationMethod)Enum.Parse(typeof(TextureMapGenerationMethod), generator.Mode); + switch (method) + { + case TextureMapGenerationMethod.SPHERE: + return new SphericalTextureMap(); + default: + return null; + } + } + else if (textureCoordinate is IIfcIndexedTriangleTextureMap triTextureMap) + { + return new ManualTriangularTextureMapping(triTextureMap, triTextureMap.MappedTo.Coordinates.CoordList.Count); + } + else + { + return null; + } + } + } +} diff --git a/Xbim.Presentation/WpfMaterial.cs b/Xbim.Presentation/WpfMaterial.cs index b2974d8a..f824f652 100644 --- a/Xbim.Presentation/WpfMaterial.cs +++ b/Xbim.Presentation/WpfMaterial.cs @@ -1,8 +1,13 @@ using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Text; using System.Windows.Media; +using System.Windows.Media.Imaging; using System.Windows.Media.Media3D; using Xbim.Ifc; +using Xbim.Ifc4.Interfaces; using Xbim.ModelGeometry.Scene; namespace Xbim.Presentation @@ -12,6 +17,12 @@ public class WpfMaterial : IXbimRenderMaterial Material _material; string _description; public bool IsTransparent; + public IIfcTextureCoordinate IfcTextureCoordinate { get; set; } + + /// + /// Has the material a texture + /// + public bool HasTexture { get; private set; } = false; // empty constructor public WpfMaterial() @@ -56,6 +67,10 @@ public void CreateMaterial(XbimTexture texture) _description = "Texture " + colour; IsTransparent = colour.IsTransparent; } + else + { + _material = new MaterialGroup(); + } _material.Freeze(); } @@ -93,5 +108,24 @@ private static Material MaterialFromColour(XbimColour colour) public string Description => _description; public bool IsCreated => _material != null; + + /// + /// Create a Material from an image + /// + /// Absolut path to the image file + /// + public void WpfMaterialFromImageTexture(Uri imageUri) + { + BitmapImage imgSource = new BitmapImage(); + Stream imgStream = File.OpenRead(imageUri.LocalPath); + imgSource.BeginInit(); + imgSource.StreamSource = imgStream; + imgSource.EndInit(); + + Brush brush = new ImageBrush(imgSource); + _material = new DiffuseMaterial(brush); + HasTexture = true; + _material.Freeze(); + } } } diff --git a/Xbim.Presentation/WpfMeshGeometry3D.cs b/Xbim.Presentation/WpfMeshGeometry3D.cs index 7651cdff..74509d56 100644 --- a/Xbim.Presentation/WpfMeshGeometry3D.cs +++ b/Xbim.Presentation/WpfMeshGeometry3D.cs @@ -3,7 +3,9 @@ using System.Globalization; using System.IO; using System.Linq; +using System.Reflection; using System.Text; +using System.Windows; using System.Windows.Media; using System.Windows.Media.Media3D; using Xbim.Common; @@ -11,6 +13,8 @@ using Xbim.Common.XbimExtensions; using Xbim.Ifc4.Interfaces; using Xbim.ModelGeometry.Scene; +using Xbim.Presentation.Extensions.Utility; +using Xbim.Presentation.Texturing; namespace Xbim.Presentation { @@ -18,8 +22,9 @@ public class WpfMeshGeometry3D : IXbimMeshGeometry3D { public GeometryModel3D WpfModel; private List _unfrozenPositions; - private List _unfrozenIndices; + private List _unfrozenTriangleIndices; private List _unfrozenNormals; + private List _unfrozenTextureCoordinates; XbimMeshFragmentCollection _meshes = new XbimMeshFragmentCollection(); private TriangleType _meshType; @@ -184,6 +189,17 @@ public static WpfMeshGeometry3D GetGeometry(EntitySelection selection, XbimModel return tgt; } + static WpfMeshGeometry3D() + { + _brushProperties = new List(); + Type emType = typeof(EmissiveMaterial); + _brushProperties.Add(emType.GetProperty(nameof(EmissiveMaterial.Brush))); + Type dfType = typeof(DiffuseMaterial); + _brushProperties.Add(dfType.GetProperty(nameof(DiffuseMaterial.Brush))); + Type spType = typeof(SpecularMaterial); + _brushProperties.Add(spType.GetProperty(nameof(SpecularMaterial.Brush))); + } + public WpfMeshGeometry3D() { WpfModel = new GeometryModel3D {Geometry = new MeshGeometry3D()}; @@ -202,9 +218,10 @@ public WpfMeshGeometry3D(IXbimMeshGeometry3D mesh) _meshes = new XbimMeshFragmentCollection(mesh.Meshes); } - public WpfMeshGeometry3D(Material material, Material backMaterial = null) + public WpfMeshGeometry3D(Material material, Material backMaterial = null, IIfcTextureCoordinate ifcTextureCoordinates = null) { WpfModel = new GeometryModel3D(new MeshGeometry3D(), material); + IfcTextureCoordinates = ifcTextureCoordinates; if (backMaterial != null) WpfModel.BackMaterial = backMaterial; } @@ -234,6 +251,16 @@ public XbimMeshFragmentCollection Meshes } } + /// + /// IFC texture Coordinates + /// + public IIfcTextureCoordinate IfcTextureCoordinates; + + /// + /// for later Checking + /// + private static readonly List _brushProperties; + /// /// Do not use this rather create a XbimMeshGeometry3D first and construct this from it, appending WPF collections is slow /// @@ -287,7 +314,7 @@ public IList TriangleIndices { if (WpfModel?.Geometry == null) { - _unfrozenIndices = value.ToList(); + _unfrozenTriangleIndices = value.ToList(); } else Mesh.TriangleIndices = new Int32Collection(value); @@ -406,7 +433,7 @@ public int TriangleIndexCount { return 0; } - return Mesh == null ? _unfrozenIndices.Count : Mesh.TriangleIndices.Count; + return Mesh == null ? _unfrozenTriangleIndices.Count : Mesh.TriangleIndices.Count; } } @@ -678,7 +705,7 @@ public bool Read(string data, XbimMatrix3D? tr = null) //all vertices will be unique and have only one normal writtenVertices.Add(index, PositionCount); - _unfrozenIndices.Add(PositionCount); + _unfrozenTriangleIndices.Add(PositionCount); _unfrozenPositions.Add(vertexList[index]); _unfrozenNormals.Add(currentNormal); @@ -686,10 +713,10 @@ public bool Read(string data, XbimMatrix3D? tr = null) else //just add the index reference { if (_unfrozenNormals[alreadyWrittenAt] == currentNormal) - _unfrozenIndices.Add(alreadyWrittenAt); + _unfrozenTriangleIndices.Add(alreadyWrittenAt); else //we need another { - _unfrozenIndices.Add(PositionCount); + _unfrozenTriangleIndices.Add(PositionCount); _unfrozenPositions.Add(vertexList[index]); _unfrozenNormals.Add(currentNormal); } @@ -707,10 +734,15 @@ public bool Read(string data, XbimMatrix3D? tr = null) return true; } - public void Add(byte[] mesh, short productTypeId, int productLabel, int geometryLabel, XbimMatrix3D? transform = null, short modelId = 0) + public void Add(byte[] mesh, short productTypeId, int productLabel, int geometryLabel, XbimMatrix3D? transform = null, short modelId = 0, + ITextureMapping textureMappingMethod = null) { var frag = new XbimMeshFragment(PositionCount, TriangleIndexCount, productTypeId, productLabel, geometryLabel, modelId); Read(mesh, transform); + if (textureMappingMethod != null) + { + AddTextureMapping(textureMappingMethod.GetTextureMap(this._unfrozenPositions, this._unfrozenNormals, this._unfrozenTriangleIndices)); + } frag.EndPosition = PositionCount - 1; frag.EndTriangleIndex = TriangleIndexCount - 1; _meshes.Add(frag); @@ -750,7 +782,7 @@ public void Read(byte[] mesh, XbimMatrix3D? transform = null) // _unfrozenPositions.Capacity += pts.Count; _unfrozenNormals.Capacity += pts.Count; - _unfrozenIndices.Capacity += idx.Count; + _unfrozenTriangleIndices.Capacity += idx.Count; foreach (var floatsArray in pts) { var wpfPosition = new Point3D(floatsArray[0], floatsArray[1], floatsArray[2]); @@ -765,12 +797,17 @@ public void Read(byte[] mesh, XbimMatrix3D? transform = null) } foreach (var index in idx) { - _unfrozenIndices.Add(index + indexBase); + _unfrozenTriangleIndices.Add(index + indexBase); } } } } - + + public void AddTextureMapping(IEnumerable textureCoordinates) + { + this._unfrozenTextureCoordinates.AddRange(textureCoordinates); + } + /// /// Ends an update and freezes the geometry /// @@ -779,17 +816,20 @@ public void EndUpdate() WpfModel.Geometry = new MeshGeometry3D(); Mesh.Positions = new Point3DCollection(_unfrozenPositions); _unfrozenPositions = null; - Mesh.TriangleIndices = new Int32Collection(_unfrozenIndices); - _unfrozenIndices = null; + Mesh.TriangleIndices = new Int32Collection(_unfrozenTriangleIndices); + _unfrozenTriangleIndices = null; Mesh.Normals = new Vector3DCollection(_unfrozenNormals); _unfrozenNormals = null; + Mesh.TextureCoordinates = new PointCollection(_unfrozenTextureCoordinates); + _unfrozenTextureCoordinates = null; Mesh.Freeze(); } public void BeginUpdate() { _unfrozenPositions = new List(Mesh.Positions); - _unfrozenIndices = new List(Mesh.TriangleIndices); + _unfrozenTriangleIndices = new List(Mesh.TriangleIndices); _unfrozenNormals = new List(Mesh.Normals); + _unfrozenTextureCoordinates = new List(Mesh.TextureCoordinates); WpfModel.Geometry = null; }