public void PackedNormalRoundTripTest() { var tests = new[] { new XbimVector3D(0.0749087609620539, 0.264167604633194, 0.961563390626687), new XbimVector3D(-0.0535755113215756, 0.316639902069201, 0.947031592400295), new XbimVector3D(-0.0403690470743153, -0.0845001599207948, 0.995605375142015), new XbimVector3D(-0.170389413996118, 0.321003309980549, 0.931624560957681) }; foreach (var vec in tests) { Trace.WriteLine(vec); var pack = new XbimPackedNormal(vec); var roundVec = pack.Normal; Trace.WriteLine(roundVec); var a = vec.CrossProduct(roundVec); var x = Math.Abs(a.Length); var y = vec.DotProduct(roundVec); var angle = Math.Atan2(x, y); if (angle > 0.1) { Trace.WriteLine($"vector: {vec}, angle: { angle * 180.0 / Math.PI:F3}"); } Assert.IsTrue(angle < 0.13); } }
public void PackedNormalTests() { var vectors = (List <XbimVector3D>)UniformPointsOnSphere(100); foreach (var v in vectors) { var packed = new XbimPackedNormal(v); var v2 = packed.Normal; var a = v.CrossProduct(v2); var x = Math.Abs(a.Length); var y = v.DotProduct(v2); var angle = Math.Atan2(x, y); if (angle > 0.1) { Debug.WriteLine("vector: {0}, angle: {1:F3}", v, angle); } Assert.IsTrue(angle < 0.13); } //text axis aligned normals (this should be much more precise) var vArray = new[] { new XbimVector3D(0, 0, 1), new XbimVector3D(0, 0, -1), new XbimVector3D(0, 1, 0), new XbimVector3D(0, -1, 0), new XbimVector3D(1, 0, 0), new XbimVector3D(-1, 0, 0) }; foreach (var v in vArray) { var packed = new XbimPackedNormal(v); var v2 = packed.Normal; var a = v.CrossProduct(v2); var x = Math.Abs(a.Length); var y = v.DotProduct(v2); var angle = Math.Atan2(x, y); Assert.IsTrue(angle < 1e-10); } }
public bool Read(string data, XbimMatrix3D?tr = null) { int version = 1; using (var sr = new StringReader(data)) { Matrix3D?m3D = null; var r = new RotateTransform3D(); if (tr.HasValue) //set up the windows media transforms { m3D = new Matrix3D(tr.Value.M11, tr.Value.M12, tr.Value.M13, tr.Value.M14, tr.Value.M21, tr.Value.M22, tr.Value.M23, tr.Value.M24, tr.Value.M31, tr.Value.M32, tr.Value.M33, tr.Value.M34, tr.Value.OffsetX, tr.Value.OffsetY, tr.Value.OffsetZ, tr.Value.M44); r = tr.Value.GetRotateTransform3D(); } var vertexList = new Point3DCollection(); //holds the actual positions of the vertices in this data set in the mesh var normalList = new Vector3DCollection(); //holds the actual normals of the vertices in this data set in the mesh string line; // Read and display lines from the data until the end of // the data is reached. while ((line = sr.ReadLine()) != null) { var tokens = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length <= 1) { continue; } var command = tokens[0].Trim().ToUpper(); switch (command) { case "P": var pointCount = 512; // ReSharper disable once NotAccessedVariable var faceCount = 128; // ReSharper disable once NotAccessedVariable var triangleCount = 256; var normalCount = 512; if (tokens.Length > 0) { version = Int32.Parse(tokens[1]); } if (tokens.Length > 1) { pointCount = Int32.Parse(tokens[2]); } // ReSharper disable once RedundantAssignment if (tokens.Length > 2) { faceCount = Int32.Parse(tokens[3]); } // ReSharper disable once RedundantAssignment if (tokens.Length > 3) { triangleCount = Int32.Parse(tokens[4]); } if (tokens.Length > 4) { normalCount = Math.Max(Int32.Parse(tokens[5]), pointCount); //can't really have less normals than points } vertexList = new Point3DCollection(pointCount); normalList = new Vector3DCollection(normalCount); //for efficienciency avoid continual regrowing //this.Mesh.Positions = this.Mesh.Positions.GrowBy(pointCount); //this.Mesh.Normals = this.Mesh.Normals.GrowBy(normalCount); //this.Mesh.TriangleIndices = this.Mesh.TriangleIndices.GrowBy(triangleCount*3); break; case "F": break; case "V": //process vertices for (int i = 1; i < tokens.Length; i++) { string[] xyz = tokens[i].Split(','); Point3D p = new Point3D(Convert.ToDouble(xyz[0], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[1], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[2], CultureInfo.InvariantCulture)); if (m3D.HasValue) { p = m3D.Value.Transform(p); } vertexList.Add(p); } break; case "N": //processes normals for (int i = 1; i < tokens.Length; i++) { string[] xyz = tokens[i].Split(','); Vector3D v = new Vector3D(Convert.ToDouble(xyz[0], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[1], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[2], CultureInfo.InvariantCulture)); normalList.Add(v); } break; case "T": //process triangulated meshes var currentNormal = new Vector3D(); //each time we start a new mesh face we have to duplicate the vertices to ensure that we get correct shading of planar and non planar faces var writtenVertices = new Dictionary <int, int>(); for (var i = 1; i < tokens.Length; i++) { var triangleIndices = tokens[i].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (triangleIndices.Length != 3) { throw new Exception("Invalid triangle definition"); } for (var t = 0; t < 3; t++) { var indexNormalPair = triangleIndices[t].Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); if (indexNormalPair.Length > 1) //we have a normal defined { if (version == 1) { var normalStr = indexNormalPair[1].Trim(); switch (normalStr) { case "F": //Front currentNormal = new Vector3D(0, -1, 0); break; case "B": //Back currentNormal = new Vector3D(0, 1, 0); break; case "L": //Left currentNormal = new Vector3D(-1, 0, 0); break; case "R": //Right currentNormal = new Vector3D(1, 0, 0); break; case "U": //Up currentNormal = new Vector3D(0, 0, 1); break; case "D": //Down currentNormal = new Vector3D(0, 0, -1); break; default: //it is an index number int normalIndex = int.Parse(indexNormalPair[1]); currentNormal = normalList[normalIndex]; break; } } else //we have support for packed normals { var packedNormal = new XbimPackedNormal(ushort.Parse(indexNormalPair[1])); var n = packedNormal.Normal; currentNormal = new Vector3D(n.X, n.Y, n.Z); } if (tr.HasValue) { currentNormal = r.Transform(currentNormal); } } //now add the index var index = int.Parse(indexNormalPair[0]); int alreadyWrittenAt; //in case it is the first mesh if (!writtenVertices.TryGetValue(index, out alreadyWrittenAt)) //if we haven't written it in this mesh pass, add it again unless it is the first one which we know has been written { //all vertices will be unique and have only one normal writtenVertices.Add(index, PositionCount); _unfrozenIndices.Add(PositionCount); _unfrozenPositions.Add(vertexList[index]); _unfrozenNormals.Add(currentNormal); } else //just add the index reference { if (_unfrozenNormals[alreadyWrittenAt] == currentNormal) { _unfrozenIndices.Add(alreadyWrittenAt); } else //we need another { _unfrozenIndices.Add(PositionCount); _unfrozenPositions.Add(vertexList[index]); _unfrozenNormals.Add(currentNormal); } } } } break; default: throw new Exception("Invalid Geometry Command"); } } } return(true); }
public static void Read(this MeshGeometry3D m3D, string shapeData, XbimMatrix3D?transform = null) { RotateTransform3D qrd = new RotateTransform3D(); Matrix3D? matrix3D = null; if (transform.HasValue) { XbimQuaternion xq = transform.Value.GetRotationQuaternion(); qrd.Rotation = new QuaternionRotation3D(new Quaternion(xq.X, xq.Y, xq.Z, xq.W)); matrix3D = transform.Value.ToMatrix3D(); } using (StringReader sr = new StringReader(shapeData)) { int version = 1; List <Point3D> vertexList = new List <Point3D>(512); //holds the actual unique positions of the vertices in this data set in the mesh List <Vector3D> normalList = new List <Vector3D>(512); //holds the actual unique normals of the vertices in this data set in the mesh List <Point3D> positions = new List <Point3D>(1024); //holds the actual positions of the vertices in this data set in the mesh List <Vector3D> normals = new List <Vector3D>(1024); //holds the actual normals of the vertices in this data set in the mesh List <int> triangleIndices = new List <int>(2048); String line; // Read and display lines from the data until the end of // the data is reached. while ((line = sr.ReadLine()) != null) { string[] tokens = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length > 0) //we need a command { string command = tokens[0].Trim().ToUpper(); switch (command) { case "P": vertexList = new List <Point3D>(512); normalList = new List <Vector3D>(512); if (tokens.Length > 0) { version = Int32.Parse(tokens[1]); } break; case "V": //process vertices for (int i = 1; i < tokens.Length; i++) { string[] xyz = tokens[i].Split(','); Point3D p = new Point3D(Convert.ToDouble(xyz[0], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[1], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[2], CultureInfo.InvariantCulture)); if (matrix3D.HasValue) { p = matrix3D.Value.Transform(p); } vertexList.Add(p); } break; case "N": //processes normals for (int i = 1; i < tokens.Length; i++) { string[] xyz = tokens[i].Split(','); Vector3D v = new Vector3D(Convert.ToDouble(xyz[0], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[1], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[2], CultureInfo.InvariantCulture)); normalList.Add(v); } break; case "T": //process triangulated meshes Vector3D currentNormal = new Vector3D(0, 0, 0); //each time we start a new mesh face we have to duplicate the vertices to ensure that we get correct shading of planar and non planar faces var writtenVertices = new Dictionary <int, int>(); for (int i = 1; i < tokens.Length; i++) { string[] indices = tokens[i].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (indices.Length != 3) { throw new Exception("Invalid triangle definition"); } for (int t = 0; t < 3; t++) { string[] indexNormalPair = indices[t].Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); if (indexNormalPair.Length > 1) //we have a normal defined { if (version == 1) { string normalStr = indexNormalPair[1].Trim(); switch (normalStr) { case "F": //Front currentNormal = new Vector3D(0, -1, 0); break; case "B": //Back currentNormal = new Vector3D(0, 1, 0); break; case "L": //Left currentNormal = new Vector3D(-1, 0, 0); break; case "R": //Right currentNormal = new Vector3D(1, 0, 0); break; case "U": //Up currentNormal = new Vector3D(0, 0, 1); break; case "D": //Down currentNormal = new Vector3D(0, 0, -1); break; default: //it is an index number int normalIndex = int.Parse(indexNormalPair[1]); currentNormal = normalList[normalIndex]; break; } } else //we have support for packed normals { var packedNormal = new XbimPackedNormal(ushort.Parse(indexNormalPair[1])); var n = packedNormal.Normal; currentNormal = new Vector3D(n.X, n.Y, n.Z); } if (matrix3D.HasValue) { currentNormal = qrd.Transform(currentNormal); } } //now add the index int index = int.Parse(indexNormalPair[0]); int alreadyWrittenAt; //in case it is the first mesh if (!writtenVertices.TryGetValue(index, out alreadyWrittenAt)) //if we haven't written it in this mesh pass, add it again unless it is the first one which we know has been written { //all vertices will be unique and have only one normal writtenVertices.Add(index, positions.Count); triangleIndices.Add(positions.Count + m3D.TriangleIndices.Count); positions.Add(vertexList[index]); normals.Add(currentNormal); } else //just add the index reference { if (normals[alreadyWrittenAt] == currentNormal) { triangleIndices.Add(alreadyWrittenAt); } else //we need another { triangleIndices.Add(positions.Count + m3D.TriangleIndices.Count); positions.Add(vertexList[index]); normals.Add(currentNormal); } } } } break; case "F": //skip faces for now, can be used to draw edges break; default: throw new Exception("Invalid Geometry Command"); } } } m3D.Positions = new Point3DCollection(m3D.Positions.Concat(positions)); //we do this for wpf performance issues m3D.Normals = new Vector3DCollection(m3D.Normals.Concat(normals)); //we do this for wpf performance issues m3D.TriangleIndices = new Int32Collection(m3D.TriangleIndices.Concat(triangleIndices)); //we do this for wpf performance issues } }
/// <summary> /// Reads an ascii string of Xbim mesh geometry data /// </summary> /// <param name="data"></param> /// <returns></returns> public bool Read(String data, XbimMatrix3D?trans = null) { var version = 2; //we are at at least verson 2 now var q = new XbimQuaternion(); if (trans.HasValue) { q = trans.Value.GetRotationQuaternion(); } using (var sr = new StringReader(data)) { var vertexList = new List <XbimPoint3D>(); //holds the actual positions of the vertices in this data set in the mesh var normalList = new List <XbimVector3D>(); //holds the actual normals of the vertices in this data set in the mesh String line; // Read and display lines from the data until the end of // the data is reached. while ((line = sr.ReadLine()) != null) { var tokens = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length > 1) //we need a command and some data { var command = tokens[0].Trim().ToUpper(); switch (command) { case "P": version = Int32.Parse(tokens[1]); var pointCount = 512; //var faceCount = 128; //var triangleCount = 256; var normalCount = 512; if (tokens.Length > 1) { pointCount = Int32.Parse(tokens[2]); } // if (tokens.Length > 2) faceCount = Int32.Parse(tokens[3]); // if (tokens.Length > 3) triangleCount = Int32.Parse(tokens[4]); //version 2 of the string format uses packed normals if (version < 2 && tokens.Length > 4) { normalCount = Int32.Parse(tokens[5]); } vertexList = new List <XbimPoint3D>(pointCount); normalList = new List <XbimVector3D>(normalCount); break; case "V": //process vertices for (var i = 1; i < tokens.Length; i++) { var xyz = tokens[i].Split(','); var p = new XbimPoint3D(Convert.ToDouble(xyz[0], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[1], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[2], CultureInfo.InvariantCulture)); if (trans.HasValue) { p = trans.Value.Transform(p); } vertexList.Add(p); } break; case "N": //processes normals for (var i = 1; i < tokens.Length; i++) { var xyz = tokens[i].Split(','); var v = new XbimVector3D(Convert.ToDouble(xyz[0], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[1], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[2], CultureInfo.InvariantCulture)); normalList.Add(v); } break; case "T": //process triangulated meshes var currentNormal = XbimVector3D.Zero; //each time we start a new mesh face we have to duplicate the vertices to ensure that we get correct shading of planar and non planar faces var writtenVertices = new Dictionary <int, int>(); for (var i = 1; i < tokens.Length; i++) { var triangleIndices = tokens[i].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (triangleIndices.Length != 3) { throw new Exception("Invalid triangle definition"); } for (var t = 0; t < 3; t++) { var indexNormalPair = triangleIndices[t].Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); if (indexNormalPair.Length > 1) //we have a normal defined { var normalStr = indexNormalPair[1].Trim(); if (version < 2) { switch (normalStr) { case "F": //Front currentNormal = new XbimVector3D(0, -1, 0); break; case "B": //Back currentNormal = new XbimVector3D(0, 1, 0); break; case "L": //Left currentNormal = new XbimVector3D(-1, 0, 0); break; case "R": //Right currentNormal = new XbimVector3D(1, 0, 0); break; case "U": //Up currentNormal = new XbimVector3D(0, 0, 1); break; case "D": //Down currentNormal = new XbimVector3D(0, 0, -1); break; default: //it is an index number var normalIndex = int.Parse(indexNormalPair[1]); currentNormal = normalList[normalIndex]; break; } } else { var normalIndex = ushort.Parse(indexNormalPair[1]); var packedNormal = new XbimPackedNormal(normalIndex); currentNormal = packedNormal.Normal; } if (trans.HasValue) { XbimVector3D v; XbimQuaternion.Transform(ref currentNormal, ref q, out v); currentNormal = v; } } //now add the index var index = int.Parse(indexNormalPair[0]); int alreadyWrittenAt; if (!writtenVertices.TryGetValue(index, out alreadyWrittenAt)) //if we haven't written it in this mesh pass, add it again unless it is the first one which we know has been written { //all vertices will be unique and have only one normal writtenVertices.Add(index, PositionCount); TriangleIndices.Add(PositionCount); Positions.Add(vertexList[index]); Normals.Add(currentNormal); } else //just add the index reference { TriangleIndices.Add(alreadyWrittenAt); } } } break; case "F": break; default: throw new Exception("Invalid Geometry Command"); } } } } return(true); }
/// <summary> /// this is just three triangles per boundinng box at the moment. /// </summary> /// <param name="BoundingBox"></param> /// <returns></returns> private byte[] GetSlicedBoxRepresentation(XbimRect3D BoundingBox) { var TriSize = 2; var pts = new List <XbimPoint3D>(4); pts.Add(new XbimPoint3D(BoundingBox.Min.X, BoundingBox.Min.Y, BoundingBox.Min.Z)); pts.Add(new XbimPoint3D(BoundingBox.Min.X + BoundingBox.SizeX / TriSize, BoundingBox.Min.Y, BoundingBox.Min.Z)); pts.Add(new XbimPoint3D(BoundingBox.Min.X, BoundingBox.Min.Y + BoundingBox.SizeY / TriSize, BoundingBox.Min.Z)); pts.Add(new XbimPoint3D(BoundingBox.Min.X, BoundingBox.Min.Y, BoundingBox.Min.Z + BoundingBox.SizeZ / TriSize)); pts.Add(new XbimPoint3D(BoundingBox.Max.X, BoundingBox.Max.Y, BoundingBox.Max.Z)); pts.Add(new XbimPoint3D(BoundingBox.Max.X - BoundingBox.SizeX / TriSize, BoundingBox.Max.Y, BoundingBox.Max.Z)); pts.Add(new XbimPoint3D(BoundingBox.Max.X, BoundingBox.Max.Y - BoundingBox.SizeY / TriSize, BoundingBox.Max.Z)); pts.Add(new XbimPoint3D(BoundingBox.Max.X, BoundingBox.Max.Y, BoundingBox.Max.Z - BoundingBox.SizeZ / TriSize)); var n1 = new XbimPackedNormal(0, 0, 1); var n2 = new XbimPackedNormal(0, 1, 0); var n3 = new XbimPackedNormal(1, 0, 0); var n4 = new XbimPackedNormal(0, 0, -1); var n5 = new XbimPackedNormal(0, -1, 0); var n6 = new XbimPackedNormal(-1, 0, 0); using (MemoryStream stream = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(stream)) { writer.Write((byte)1); // version writer.Write((int)pts.Count); // points writer.Write((int)6); // total triangles // write the points foreach (var pt in pts) { writer.Write((float)pt.X); writer.Write((float)pt.Y); writer.Write((float)pt.Z); } writer.Write((int)6); // faces // face 1 // writer.Write((int)1); // 1 triangle n1.Write(writer); // the normal writer.Write((byte)0); // small indices are stored in a single byte writer.Write((byte)1); writer.Write((byte)2); // face 2 // writer.Write((int)1); // 1 triangle n2.Write(writer); // the normal writer.Write((byte)0); // small indices are stored in a single byte writer.Write((byte)1); writer.Write((byte)3); // face 3 // writer.Write((int)1); // 1 triangle n3.Write(writer); // the normal writer.Write((byte)0); // small indices are stored in a single byte writer.Write((byte)2); writer.Write((byte)3); // face 4 // writer.Write((int)1); // 1 triangle n4.Write(writer); // the normal writer.Write((byte)4); // small indices are stored in a single byte writer.Write((byte)6); writer.Write((byte)5); // face 5 // writer.Write((int)1); // 1 triangle n5.Write(writer); // the normal writer.Write((byte)5); // small indices are stored in a single byte writer.Write((byte)4); writer.Write((byte)7); // face 6 // writer.Write((int)1); // 1 triangle n6.Write(writer); // the normal writer.Write((byte)6); // small indices are stored in a single byte writer.Write((byte)4); writer.Write((byte)7); } stream.Flush(); byte[] bytes = stream.GetBuffer(); return(bytes); } }
private void Load() { const string fileName = "Assets/ifc/Project1.xBIM"; Debug.Log("initializing model loading"); using (var model = IfcStore.Open(fileName, accessMode: Xbim.IO.Esent.XbimDBAccess.ReadWrite)) { Debug.Log("model loaded"); if (model.GeometryStore == null) { Debug.Log("Geometry Store is null. Model has no geometry information"); } else { Debug.Log("Geometry Store is ok. Starting geometry conversion"); using (var reader = model.GeometryStore.BeginRead()) { //var shapeGeometries = reader.ShapeGeometries; var shapeInstances = reader.ShapeInstances; int shapeInstancesCount = 0; foreach (XbimShapeInstance shape in shapeInstances) { XbimMatrix3D transformation = shape.Transformation; Matrix4x4 transf = new Matrix4x4(new Vector4((float)transformation.M11, (float)transformation.M12, (float)transformation.M13, (float)transformation.M14), new Vector4((float)transformation.M21, (float)transformation.M22, (float)transformation.M23, (float)transformation.M24), new Vector4((float)transformation.M31, (float)transformation.M32, (float)transformation.M33, (float)transformation.M34), new Vector4((float)transformation.OffsetX, (float)transformation.OffsetY, (float)transformation.OffsetZ, (float)transformation.M44)); if (!geometryInstancesMap.ContainsKey(shape.ShapeGeometryLabel)) { XbimShapeGeometry geometry = reader.ShapeGeometry(shape.ShapeGeometryLabel); if (geometry.ShapeData.Length <= 0) { continue; } Mesh mesh = new Mesh(); //List<Vector3> vertexList = new List<Vector3>(); List <int> triangleList = new List <int>(); var ms = new MemoryStream(((IXbimShapeGeometryData)geometry).ShapeData); var br = new BinaryReader(ms); var tr = br.ReadShapeTriangulation(); int size = tr.Vertices.Count; Vector3[] vertices = Point3DList_to_Vec3Array(tr.Vertices); //vertexList.AddRange(vertices); Vector3[] normals = new Vector3[vertices.Length]; int[] normsCount = new int[vertices.Length]; int normalCount = 0; int faceCount = 0; IList <XbimFaceTriangulation> facesList = tr.Faces; //Debug.Log("shape " + shapeInstancesCount + " has " + facesList.Count + " faces"); foreach (XbimFaceTriangulation face in facesList) { IList <int> indices = face.Indices; foreach (int index in indices) { triangleList.Add(index); } //Debug.Log("face " + faceCount + " has " + indices.Count + " indices"); int i = 0; if (face.IsPlanar) { //Debug.Log("face " + faceCount + " is planar "); XbimPackedNormal normal = face.Normals[0]; foreach (int index in indices) { normals[index] += new Vector3((float)normal.Normal.X, (float)normal.Normal.Y, (float)normal.Normal.Z); normsCount[index]++; normalCount++; } } else { foreach (XbimPackedNormal normal in face.Normals) { int index = face.Indices[i]; normals[index] += new Vector3((float)normal.Normal.X, (float)normal.Normal.Y, (float)normal.Normal.Z); normsCount[index]++; normalCount++; i++; } } faceCount++; } for (int i = 0; i < normals.Length; i++) { normals[i] = new Vector3(normals[i].x / (float)normsCount[i], normals[i].y / (float)normsCount[i], normals[i].z / (float)normsCount[i]).normalized; } //Debug.Log("shape " + shapeInstancesCount + " has " + size + " vertices"); //Debug.Log("shape " + shapeInstancesCount + " has " + XbimShapeTriangulation.TriangleCount(((IXbimShapeGeometryData)geometry).ShapeData) + " triangles"); //Debug.Log("shape " + shapeInstancesCount + " has " + normalCount + " normals"); mesh.vertices = vertices; mesh.triangles = triangleList.ToArray(); mesh.normals = normals; container.setMesh(mesh); triangleList.Clear(); geometryInstancesMap.Add(shape.ShapeGeometryLabel, mesh); } else { Mesh mesh; geometryInstancesMap.TryGetValue(shape.ShapeGeometryLabel, out mesh); if (mesh != null) { container.setMesh(mesh); } } MeshContainer obj = Instantiate(container, new Vector3((float)transformation.OffsetX * 0.1f, (float)transformation.OffsetY * 0.1f, (float)transformation.OffsetZ * 0.1f), transf.rotation); obj.transform.RotateAround(new Vector3(0, 0, 0), new Vector3(1, 0, 0), -90); obj.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); var products = model.Instances.Where <IfcProduct>(e => e.EntityLabel == shape.IfcProductLabel); int productCount = 0; foreach (var product in products) { obj.name = product.Name.ToString(); //Material mat = obj.GetComponent<MeshRenderer>().material; var isDefinedBy_inv = product.IsDefinedBy; foreach (var rel_def in isDefinedBy_inv) { IfcPropertySetDefinitionSelect relating_property_def_select = rel_def.RelatingPropertyDefinition; IfcPropertySetDefinition relating_property_def = (IfcPropertySetDefinition)relating_property_def_select; if (relating_property_def != null) { IfcPropertySet prop_set = (IfcPropertySet)relating_property_def; if (prop_set != null) { Material mat = readAppearanceFromPropertySet(prop_set); obj.GetComponent <Material>().color = mat.color; } continue; } IfcPropertySetDefinitionSet relating_property_def_set = (IfcPropertySetDefinitionSet)relating_property_def_select; if (relating_property_def_set != null) { var vec_property_def = relating_property_def_set.PropertySetDefinitions; foreach (IfcPropertySetDefinition property_def in vec_property_def) { if (property_def != null) { IfcPropertySet prop_set = (IfcPropertySet)property_def; if (prop_set != null) { Material mat = readAppearanceFromPropertySet(prop_set); obj.GetComponent <Material>().color = mat.color; } } } } } productCount++; } //Debug.Log("there is " + productCount + " products with label " + shape.IfcProductLabel); shapeInstancesCount++; //yield return null; } container.setMesh(null); } Debug.Log("Geometry loaded. Starting visualization."); } // Close Geometry Store } // Close File }