コード例 #1
0
        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);
            }
        }
コード例 #2
0
        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);
            }
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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
            }
        }
コード例 #5
0
        /// <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);
        }
コード例 #6
0
        /// <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);
            }
        }
コード例 #7
0
    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
    }