Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Texture implementation #163

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Xbim.Presentation/Extensions/Utility/GeomUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,13 @@ public static Point3DCollection GetPointCollection(List<XbimPoint3D> 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);
}
}
}
96 changes: 85 additions & 11 deletions Xbim.Presentation/LayerStyling/SurfaceLayerStyler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -11,6 +12,7 @@
using Xbim.Common.Geometry;
using Xbim.Ifc;
using Xbim.Ifc4.Interfaces;
using Xbim.Presentation.Texturing;

namespace Xbim.Presentation.LayerStyling
{
Expand Down Expand Up @@ -149,12 +151,31 @@ public XbimScene<WpfMeshGeometry3D, WpfMaterial> 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
Expand Down Expand Up @@ -182,12 +203,27 @@ public XbimScene<WpfMeshGeometry3D, WpfMaterial> 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);

}
}
}
Expand Down Expand Up @@ -227,7 +263,7 @@ protected IEnumerable<XbimShapeInstance> 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();
Expand All @@ -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;
}

Expand Down
25 changes: 25 additions & 0 deletions Xbim.Presentation/Texturing/ITextureMapping.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// returns the texture map for a given set of vertices
/// </summary>
/// <returns>a texture map for the related mesh</returns>
IEnumerable<Point> GetTextureMap(IEnumerable<Point3D> vertices, IEnumerable<Vector3D> normals, IEnumerable<int> triangles);

/// <summary>
/// Method for the Texturing
/// </summary>
TextureMapGenerationMethod TexturingMethod {get;}
}
}
62 changes: 62 additions & 0 deletions Xbim.Presentation/Texturing/ManualTriangularTextureMapping.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// Manual map for texture coordinates. The index of the several vectors are related to the vertice index provided at <a href="::GetTextureMap">GetTextureMap</a>
/// </summary>
private IIfcIndexedTriangleTextureMap _ifcTextMap;
private int _numberOfVertices;

public ManualTriangularTextureMapping(IIfcIndexedTriangleTextureMap textMap, int numberOfVertices)
{
_ifcTextMap = textMap;
_numberOfVertices = numberOfVertices;
}

/// <summary>
/// Used Method for Texturing
/// </summary>
public TextureMapGenerationMethod TexturingMethod
{
get
{
return TextureMapGenerationMethod.MANUALTRIANGULAR;
}
}

/// <summary>
/// returns the manual texture map
/// </summary>
/// <returns></returns>
public IEnumerable<Point> GetTextureMap(IEnumerable<Point3D> vertices, IEnumerable<Vector3D> normals, IEnumerable<int> 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;
}
}
}
81 changes: 81 additions & 0 deletions Xbim.Presentation/Texturing/SphericalTextureMap.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// Used Method for Texturing
/// </summary>
public TextureMapGenerationMethod TexturingMethod
{
get
{
return TextureMapGenerationMethod.SPHERE;
}
}

/// <summary>
/// Calculates the texture by using the algorithm of spherical texture mapping
/// </summary>
/// <returns>A spherical texture map. The indices of the texture map are related
/// to the indices of the given vertices</returns>
public IEnumerable<Point> GetTextureMap(IEnumerable<Point3D> vertices, IEnumerable<Vector3D> normals, IEnumerable<int> 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;
}
}
}
Loading