public static RotateTransform3D GetRotateTransform3D(this XbimQuaternion xq)
        {
            RotateTransform3D r = new RotateTransform3D();

            r.Rotation = new QuaternionRotation3D(new Quaternion(xq.X, xq.Y, xq.Z, xq.W * (180.0 / Math.PI)));
            return(r);
        }
Exemple #2
0
        public void QuaternionVersusMatrixMovingTests()
        {
            XbimVector3D t = new XbimVector3D(2, 0, 0);
            XbimMatrix3D T = new XbimMatrix3D(t);

            T.RotateAroundZAxis(Math.PI / 2);
            XbimQuaternion q;

            XbimQuaternion.RotationMatrix(ref T, out q);

            // Do the quaternion approach
            XbimVector3D v = new XbimVector3D(1, 1, 0);
            XbimVector3D v1;

            XbimQuaternion.Transform(ref v, ref q, out v1);
            // Rotate and translate
            var p1Result = v1 + t;

            // Do the same with matrix approach
            XbimPoint3D p        = new XbimPoint3D(1, 1, 0);
            var         p2Result = T.Transform(p);

            Assert.AreEqual(p1Result, XbimPoint3D.Subtract(p2Result, XbimPoint3D.Zero));

            // Test quaternion and delta translation (relocating)
            XbimVector3D mt       = new XbimVector3D(2, 2, 0);
            var          dt       = t - mt;
            var          pMoved   = v1 + dt;
            var          p3Result = pMoved + mt;

            Assert.AreEqual(p1Result, p3Result);
        }
Exemple #3
0
        internal void AddMesh(byte[] mesh, XbimMatrix3D?transform = null)
        {
            int            indexBase      = Positions.Count;
            bool           needRotate     = false;
            bool           needTransform  = false;
            XbimQuaternion xq             = new XbimQuaternion(0.0, 0.0, 0.0, 1.0);
            XbimMatrix3D   transformValue = XbimMatrix3D.Identity;

            if (transform.HasValue)
            {
                transformValue = transform.Value;
                needTransform  = !transformValue.IsIdentity;
                xq             = transformValue.GetRotationQuaternion();
                // we have to build a rotation transform from the quaternion (to tranform normals later on)
                needRotate = !xq.IsIdentity();
            }
            using (var ms = new MemoryStream(mesh))
                using (var br = new BinaryReader(ms))
                {
                    var            t = br.ReadShapeTriangulation();
                    List <float[]> pts;
                    List <int>     idx;
                    t.ToPointsWithNormalsAndIndices(out pts, out idx);

                    // add to lists
                    //
                    // Commented because of https://github.com/xBimTeam/XbimGltf/issues/2
                    //Positions.Capacity += pts.Count;
                    //Normals.Capacity += pts.Count;
                    //Indices.Capacity += idx.Count;
                    foreach (var floatsArray in pts)
                    {
                        var tmpPosition = new XbimPoint3D(floatsArray[0], floatsArray[1], floatsArray[2]);
                        if (needTransform)
                        {
                            tmpPosition = transformValue.Transform(tmpPosition);
                        }
                        Positions.Add(tmpPosition);

                        var tmpNormal = new XbimVector3D(floatsArray[3], floatsArray[4], floatsArray[5]);
                        if (needRotate) //transform the normal if we have to
                        {
                            XbimQuaternion.Transform(ref tmpNormal, ref xq, out tmpNormal);
                        }
                        Normals.Add(tmpNormal);
                    }
                    foreach (var index in idx)
                    {
                        Indices.Add(index + indexBase);
                    }
                }
        }
        public void QuaternionTests()
        {
            var q = new XbimQuaternion();

            Assert.AreEqual(true, q.IsIdentity(), "Uninitialised quaternion should be identity.");

            q = new XbimQuaternion(0.0f, 0.0f, 0.0f, 1.0f);
            Assert.AreEqual(true, q.IsIdentity(), "Should be identity when initialised with floats.");

            var mat = new XbimMatrix3D();

            q = mat.GetRotationQuaternion();
            Assert.AreEqual(true, q.IsIdentity(), "Quaternion from identity matrix shold be identity.");
        }
Exemple #5
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))
            {
                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 char[] { ' ' }, 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);
                            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
                            Dictionary <int, int> writtenVertices = new Dictionary <int, int>();

                            for (int i = 1; i < tokens.Length; i++)
                            {
                                string[] indices = tokens[i].Split(new char[] { ',' }, 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 char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

                                    if (indexNormalPair.Length > 1)     //we have a normal defined
                                    {
                                        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;
                                        }
                                        if (matrix3D.HasValue)
                                        {
                                            currentNormal = qrd.Transform(currentNormal);
                                        }
                                    }

                                    //now add the index
                                    int index = int.Parse(indexNormalPair[0]);

                                    int alreadyWrittenAt = index;                                  //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
                                    {
                                        triangleIndices.Add(alreadyWrittenAt);
                                    }
                                }
                            }

                            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
            }
        }
 public static QuaternionRotation3D GetQuaternionRotation3D(this XbimQuaternion xq)
 {
     return(new QuaternionRotation3D(new Quaternion(xq.X, xq.Y, xq.Z, xq.W * (180.0 / Math.PI))));
 }
Exemple #7
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);
        }
        public static void Read(this XbimMeshGeometry3D m3D, byte[] mesh, XbimMatrix3D?transform = null)
        {
            var indexBase = m3D.Positions.Count;
            var qrd       = new XbimQuaternion();

            XbimMatrix3D?matrix3D = null;

            if (transform.HasValue)
            {
                qrd      = transform.Value.GetRotationQuaternion();
                matrix3D = transform.Value;
            }
            using (var ms = new MemoryStream(mesh))
            {
                using (var br = new BinaryReader(ms))
                {
                    // ReSharper disable once UnusedVariable
                    var version      = br.ReadByte(); //stream format version
                    var numVertices  = br.ReadInt32();
                    var numTriangles = br.ReadInt32();

                    var uniqueVertices  = new List <XbimPoint3D>(numVertices);
                    var vertices        = new List <XbimPoint3D>(numVertices * 4); //approx the size
                    var triangleIndices = new List <int>(numTriangles * 3);
                    var normals         = new List <XbimVector3D>(numVertices * 4);
                    for (var i = 0; i < numVertices; i++)
                    {
                        double x = br.ReadSingle();
                        double y = br.ReadSingle();
                        double z = br.ReadSingle();
                        var    p = new XbimPoint3D(x, y, z);
                        if (matrix3D.HasValue)
                        {
                            p = matrix3D.Value.Transform(p);
                        }
                        uniqueVertices.Add(p);
                    }
                    var numFaces = br.ReadInt32();

                    for (var i = 0; i < numFaces; i++)
                    {
                        var numTrianglesInFace = br.ReadInt32();
                        if (numTrianglesInFace == 0)
                        {
                            continue;
                        }
                        var isPlanar = numTrianglesInFace > 0;
                        numTrianglesInFace = Math.Abs(numTrianglesInFace);
                        if (isPlanar)
                        {
                            var normal = br.ReadPackedNormal().Normal;
                            if (!qrd.IsIdentity())
                            {
                                var baseVal = new XbimVector3D(normal.X, normal.Y, normal.Z);
                                XbimQuaternion.Transform(ref baseVal, ref qrd, out normal);
                            }
                            var uniqueIndices = new Dictionary <int, int>();
                            for (var j = 0; j < numTrianglesInFace; j++)
                            {
                                for (var k = 0; k < 3; k++)
                                {
                                    var idx = ReadIndex(br, numVertices);
                                    int writtenIdx;
                                    if (!uniqueIndices.TryGetValue(idx, out writtenIdx)) //we haven't got it, so add it
                                    {
                                        writtenIdx = vertices.Count;
                                        vertices.Add(uniqueVertices[idx]);
                                        uniqueIndices.Add(idx, writtenIdx);
                                        //add a matching normal
                                        normals.Add(normal);
                                    }
                                    triangleIndices.Add(indexBase + writtenIdx);
                                }
                            }
                        }
                        else
                        {
                            var uniqueIndices = new Dictionary <int, int>();
                            for (var j = 0; j < numTrianglesInFace; j++)
                            {
                                for (var k = 0; k < 3; k++)
                                {
                                    var idx    = ReadIndex(br, numVertices);
                                    var normal = br.ReadPackedNormal().Normal;
                                    int writtenIdx;
                                    if (!uniqueIndices.TryGetValue(idx, out writtenIdx)) //we haven't got it, so add it
                                    {
                                        writtenIdx = vertices.Count;
                                        vertices.Add(uniqueVertices[idx]);
                                        uniqueIndices.Add(idx, writtenIdx);

                                        if (!qrd.IsIdentity())
                                        {
                                            var baseVal = new XbimVector3D(normal.X, normal.Y, normal.Z);
                                            XbimQuaternion.Transform(ref baseVal, ref qrd, out normal);
                                        }
                                        normals.Add(normal);
                                    }
                                    triangleIndices.Add(indexBase + writtenIdx);
                                }
                            }
                        }
                    }

                    m3D.Positions       = m3D.Positions.Concat(vertices).ToList();
                    m3D.TriangleIndices = m3D.TriangleIndices.Concat(triangleIndices).ToList();
                    m3D.Normals         = m3D.Normals.Concat(normals).ToList();
                }
            }
        }