Example #1
0
        void AddPositions(out Vector3 scale, out Vector3 offset, mesh mesh, ModelPrim prim, Matrix4 transform)
        {
            prim.Positions = new List <Vector3>();
            source posSrc = FindSource(mesh.source, mesh.vertices.input[0].source);

            double[] posVals = ((float_array)posSrc.Item).Values;

            for (int i = 0; i < posVals.Length / 3; i++)
            {
                Vector3 pos = new Vector3((float)posVals[i * 3], (float)posVals[i * 3 + 1], (float)posVals[i * 3 + 2]);
                pos = Vector3.Transform(pos, transform);
                prim.Positions.Add(pos);
            }

            prim.BoundMin = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
            prim.BoundMax = new Vector3(float.MinValue, float.MinValue, float.MinValue);

            foreach (var pos in prim.Positions)
            {
                if (pos.X > prim.BoundMax.X)
                {
                    prim.BoundMax.X = pos.X;
                }
                if (pos.Y > prim.BoundMax.Y)
                {
                    prim.BoundMax.Y = pos.Y;
                }
                if (pos.Z > prim.BoundMax.Z)
                {
                    prim.BoundMax.Z = pos.Z;
                }

                if (pos.X < prim.BoundMin.X)
                {
                    prim.BoundMin.X = pos.X;
                }
                if (pos.Y < prim.BoundMin.Y)
                {
                    prim.BoundMin.Y = pos.Y;
                }
                if (pos.Z < prim.BoundMin.Z)
                {
                    prim.BoundMin.Z = pos.Z;
                }
            }

            scale  = prim.BoundMax - prim.BoundMin;
            offset = prim.BoundMin + (scale / 2);

            // Fit vertex positions into identity cube -0.5 .. 0.5
            for (int i = 0; i < prim.Positions.Count; i++)
            {
                Vector3 pos = prim.Positions[i];
                pos = new Vector3(
                    scale.X == 0 ? 0 : ((pos.X - prim.BoundMin.X) / scale.X) - 0.5f,
                    scale.Y == 0 ? 0 : ((pos.Y - prim.BoundMin.Y) / scale.Y) - 0.5f,
                    scale.Z == 0 ? 0 : ((pos.Z - prim.BoundMin.Z) / scale.Z) - 0.5f
                    );
                prim.Positions[i] = pos;
            }
        }
Example #2
0
        void AddFacesFromPolyList(polylist list, mesh mesh, ModelPrim prim, Matrix4 transform)
        {
            string material  = list.material;
            source posSrc    = null;
            source normalSrc = null;
            source uvSrc     = null;

            ulong stride    = 0;
            int   posOffset = -1;
            int   norOffset = -1;
            int   uvOffset  = -1;

            foreach (var inp in list.input)
            {
                stride = Math.Max(stride, inp.offset);

                switch (inp.semantic)
                {
                case "VERTEX":
                    posSrc    = FindSource(mesh.source, mesh.vertices.input[0].source);
                    posOffset = (int)inp.offset;
                    break;

                case "NORMAL":
                    normalSrc = FindSource(mesh.source, inp.source);
                    norOffset = (int)inp.offset;
                    break;

                case "TEXCOORD":
                    uvSrc    = FindSource(mesh.source, inp.source);
                    uvOffset = (int)inp.offset;
                    break;
                }
            }

            stride += 1;

            if (posSrc == null)
            {
                return;
            }

            var vcount = StrToArray(list.vcount);
            var idx    = StrToArray(list.p);

            Vector3[] normals = null;
            if (normalSrc != null)
            {
                var norVal = ((float_array)normalSrc.Item).Values;
                normals = new Vector3[norVal.Length / 3];

                for (int i = 0; i < normals.Length; i++)
                {
                    normals[i] = new Vector3((float)norVal[i * 3 + 0], (float)norVal[i * 3 + 1], (float)norVal[i * 3 + 2]);
                    normals[i] = Vector3.TransformNormal(normals[i], transform);
                    normals[i].Normalize();
                }
            }

            Vector2[] uvs = null;
            if (uvSrc != null)
            {
                var uvVal = ((float_array)uvSrc.Item).Values;
                uvs = new Vector2[uvVal.Length / 2];

                for (int i = 0; i < uvs.Length; i++)
                {
                    uvs[i] = new Vector2((float)uvVal[i * 2 + 0], (float)uvVal[i * 2 + 1]);
                }
            }

            ModelFace face = new ModelFace {
                MaterialID = list.material
            };

            if (face.MaterialID != null)
            {
                if (MatSymTarget.ContainsKey(list.material))
                {
                    ModelMaterial mat = Materials.Find(m => m.ID == MatSymTarget[list.material]);
                    if (mat != null)
                    {
                        face.Material = mat;
                    }
                }
            }

            int curIdx = 0;

            foreach (var nvert in vcount)
            {
                if (nvert < 3 || nvert > 4)
                {
                    throw new InvalidDataException("Only triangles and quads supported");
                }

                Vertex[] verts = new Vertex[nvert];
                for (int j = 0; j < nvert; j++)
                {
                    verts[j].Position = prim.Positions[idx[curIdx + posOffset + (int)stride * j]];

                    if (normals != null)
                    {
                        verts[j].Normal = normals[idx[curIdx + norOffset + (int)stride * j]];
                    }

                    if (uvs != null)
                    {
                        verts[j].TexCoord = uvs[idx[curIdx + uvOffset + (int)stride * j]];
                    }
                }


                switch (nvert)
                {
                case 3:
                    face.AddVertex(verts[0]);
                    face.AddVertex(verts[1]);
                    face.AddVertex(verts[2]);
                    break;

                case 4:
                    face.AddVertex(verts[0]);
                    face.AddVertex(verts[1]);
                    face.AddVertex(verts[2]);

                    face.AddVertex(verts[0]);
                    face.AddVertex(verts[2]);
                    face.AddVertex(verts[3]);
                    break;
                }

                curIdx += (int)stride * nvert;
            }

            prim.Faces.Add(face);
        }
Example #3
0
        List <ModelPrim> Parse()
        {
            var Prims = new List <ModelPrim>();

            float DEG_TO_RAD = 0.017453292519943295769236907684886f;

            if (Model == null)
            {
                return(Prims);
            }

            Matrix4 transform = Matrix4.Identity;

            UpAxisType upAxis = UpAxisType.Y_UP;

            var asset = Model.asset;

            if (asset != null)
            {
                upAxis = asset.up_axis;
                if (asset.unit != null)
                {
                    float meter = (float)asset.unit.meter;
                    transform[0, 0] = meter;
                    transform[1, 1] = meter;
                    transform[2, 2] = meter;
                }
            }

            Matrix4 rotation = Matrix4.Identity;

            if (upAxis == UpAxisType.X_UP)
            {
                rotation = Matrix4.CreateFromEulers(0.0f, 90.0f * DEG_TO_RAD, 0.0f);
            }
            else if (upAxis == UpAxisType.Y_UP)
            {
                rotation = Matrix4.CreateFromEulers(90.0f * DEG_TO_RAD, 0.0f, 0.0f);
            }

            rotation  = rotation * transform;
            transform = rotation;

            ParseVisualScene();
            ParseMaterials();

            foreach (var item in Model.Items)
            {
                if (item is library_geometries)
                {
                    var geometries = (library_geometries)item;
                    foreach (var geo in geometries.geometry)
                    {
                        var mesh = geo.Item as mesh;
                        if (mesh == null)
                        {
                            continue;
                        }

                        var nodes = Nodes.FindAll(n => n.MeshID == geo.id);     // Find all instances of this geometry
                        if (nodes != null)
                        {
                            ModelPrim firstPrim = null;         // The first prim is actually calculated, the others are just copied from it.

                            Vector3 asset_scale  = new Vector3(1, 1, 1);
                            Vector3 asset_offset = new Vector3(0, 0, 0);            // Scale and offset between Collada and OS asset (Which is always in a unit cube)

                            foreach (var node in nodes)
                            {
                                var prim = new ModelPrim();
                                prim.ID = node.ID;
                                Prims.Add(prim);

                                // First node is used to create the asset. This is as the code to crate the byte array is somewhat
                                // erroneously placed in the ModelPrim class.
                                if (firstPrim == null)
                                {
                                    firstPrim = prim;
                                    AddPositions(out asset_scale, out asset_offset, mesh, prim, transform);     // transform is used only for inch -> meter and up axis transform.

                                    foreach (var mitem in mesh.Items)
                                    {
                                        if (mitem is triangles)
                                        {
                                            AddFacesFromPolyList(Triangles2Polylist((triangles)mitem), mesh, prim, transform);  // Transform is used to turn normals according to up axis
                                        }
                                        if (mitem is polylist)
                                        {
                                            AddFacesFromPolyList((polylist)mitem, mesh, prim, transform);
                                        }
                                    }

                                    prim.CreateAsset(UUID.Zero);
                                }
                                else
                                {
                                    // Copy the values set by Addpositions and AddFacesFromPolyList as these are the same as long as the mesh is the same
                                    prim.Asset     = firstPrim.Asset;
                                    prim.BoundMin  = firstPrim.BoundMin;
                                    prim.BoundMax  = firstPrim.BoundMax;
                                    prim.Positions = firstPrim.Positions;
                                    prim.Faces     = firstPrim.Faces;
                                }

                                // Note: This ignores any shear or similar non-linear effects. This can cause some problems but it
                                // is unlikely that authoring software can generate such matrices.
                                node.Transform.Decompose(out prim.Scale, out prim.Rotation, out prim.Position);
                                float roll, pitch, yaw;
                                node.Transform.GetEulerAngles(out roll, out pitch, out yaw);

                                // The offset created when normalizing the mesh vertices into the OS unit cube must be rotated
                                // before being added to the position part of the Collada transform.
                                Matrix4 rot    = Matrix4.CreateFromQuaternion(prim.Rotation);           // Convert rotation to matrix for for Transform
                                Vector3 offset = Vector3.Transform(asset_offset * prim.Scale, rot);     // The offset must be rotated and mutiplied by the Collada file's scale as the offset is added during rendering with the unit cube mesh already multiplied by the compound scale.
                                prim.Position += offset;
                                prim.Scale    *= asset_scale;                                           // Modify scale from Collada instance by the rescaling done in AddPositions()
                            }
                        }
                    }
                }
            }

            return(Prims);
        }
        void AddFacesFromPolyList(polylist list, mesh mesh, ModelPrim prim, Matrix4 transform)
        {
            string material = list.material;
            source posSrc = null;
            source normalSrc = null;
            source uvSrc = null;

            ulong stride = 0;
            int posOffset = -1;
            int norOffset = -1;
            int uvOffset = -1;

            foreach (var inp in list.input)
            {
                stride = Math.Max(stride, inp.offset);

                if (inp.semantic == "VERTEX")
                {
                    posSrc = FindSource(mesh.source, mesh.vertices.input[0].source);
                    posOffset = (int)inp.offset;
                }
                else if (inp.semantic == "NORMAL")
                {
                    normalSrc = FindSource(mesh.source, inp.source);
                    norOffset = (int)inp.offset;
                }
                else if (inp.semantic == "TEXCOORD")
                {
                    uvSrc = FindSource(mesh.source, inp.source);
                    uvOffset = (int)inp.offset;
                }
            }

            stride += 1;

            if (posSrc == null) return;

            var vcount = StrToArray(list.vcount);
            var idx = StrToArray(list.p);

            Vector3[] normals = null;
            if (normalSrc != null)
            {
                var norVal = ((float_array)normalSrc.Item).Values;
                normals = new Vector3[norVal.Length / 3];

                for (int i = 0; i < normals.Length; i++)
                {
                    normals[i] = new Vector3((float)norVal[i * 3 + 0], (float)norVal[i * 3 + 1], (float)norVal[i * 3 + 2]);
                    normals[i] = Vector3.TransformNormal(normals[i], transform);
                    normals[i].Normalize();
                }
            }

            Vector2[] uvs = null;
            if (uvSrc != null)
            {
                var uvVal = ((float_array)uvSrc.Item).Values;
                uvs = new Vector2[uvVal.Length / 2];

                for (int i = 0; i < uvs.Length; i++)
                {
                    uvs[i] = new Vector2((float)uvVal[i * 2 + 0], (float)uvVal[i * 2 + 1]);
                }

            }

            ModelFace face = new ModelFace();
            face.MaterialID = list.material;
            if (face.MaterialID != null)
            {
                if (MatSymTarget.ContainsKey(list.material))
                {
                    ModelMaterial mat = Materials.Find(m => m.ID == MatSymTarget[list.material]);
                    if (mat != null)
                    {
                        face.Material = mat;
                    }
                }
            }

            int curIdx = 0;

            for (int i = 0; i < vcount.Length; i++)
            {
                var nvert = vcount[i];
                if (nvert < 3 || nvert > 4)
                {
                    throw new InvalidDataException("Only triangles and quads supported");
                }

                Vertex[] verts = new Vertex[nvert];
                for (int j = 0; j < nvert; j++)
                {
                    verts[j].Position = prim.Positions[idx[curIdx + posOffset + (int)stride * j]];

                    if (normals != null)
                    {
                        verts[j].Normal = normals[idx[curIdx + norOffset + (int)stride * j]];
                    }

                    if (uvs != null)
                    {
                        verts[j].TexCoord = uvs[idx[curIdx + uvOffset + (int)stride * j]];
                    }
                }


                if (nvert == 3) // add the triangle
                {
                    face.AddVertex(verts[0]);
                    face.AddVertex(verts[1]);
                    face.AddVertex(verts[2]);
                }
                else if (nvert == 4) // quad, add two triangles
                {
                    face.AddVertex(verts[0]);
                    face.AddVertex(verts[1]);
                    face.AddVertex(verts[2]);

                    face.AddVertex(verts[0]);
                    face.AddVertex(verts[2]);
                    face.AddVertex(verts[3]);
                }

                curIdx += (int)stride * nvert;
            }

            prim.Faces.Add(face);


        }
        void AddPositions(mesh mesh, ModelPrim prim, Matrix4 transform)
        {
            prim.Positions = new List<Vector3>();
            source posSrc = FindSource(mesh.source, mesh.vertices.input[0].source);
            double[] posVals = ((float_array)posSrc.Item).Values;

            for (int i = 0; i < posVals.Length / 3; i++)
            {
                Vector3 pos = new Vector3((float)posVals[i * 3], (float)posVals[i * 3 + 1], (float)posVals[i * 3 + 2]);
                pos = Vector3.Transform(pos, transform);
                prim.Positions.Add(pos);
            }

            prim.BoundMin = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
            prim.BoundMax = new Vector3(float.MinValue, float.MinValue, float.MinValue);

            foreach (var pos in prim.Positions)
            {
                if (pos.X > prim.BoundMax.X) prim.BoundMax.X = pos.X;
                if (pos.Y > prim.BoundMax.Y) prim.BoundMax.Y = pos.Y;
                if (pos.Z > prim.BoundMax.Z) prim.BoundMax.Z = pos.Z;

                if (pos.X < prim.BoundMin.X) prim.BoundMin.X = pos.X;
                if (pos.Y < prim.BoundMin.Y) prim.BoundMin.Y = pos.Y;
                if (pos.Z < prim.BoundMin.Z) prim.BoundMin.Z = pos.Z;
            }

            prim.Scale = prim.BoundMax - prim.BoundMin;
            prim.Position = prim.BoundMin + (prim.Scale / 2);

            // Fit vertex positions into identity cube -0.5 .. 0.5
            for (int i = 0; i < prim.Positions.Count; i++)
            {
                Vector3 pos = prim.Positions[i];
                pos = new Vector3(
                    prim.Scale.X == 0 ? 0 : ((pos.X - prim.BoundMin.X) / prim.Scale.X) - 0.5f,
                    prim.Scale.Y == 0 ? 0 : ((pos.Y - prim.BoundMin.Y) / prim.Scale.Y) - 0.5f,
                    prim.Scale.Z == 0 ? 0 : ((pos.Z - prim.BoundMin.Z) / prim.Scale.Z) - 0.5f
                    );
                prim.Positions[i] = pos;
            }

        }
        List<ModelPrim> Parse()
        {
            var Prims = new List<ModelPrim>();

            float DEG_TO_RAD = 0.017453292519943295769236907684886f;

            if (Model == null) return Prims;

            Matrix4 transform = Matrix4.Identity;

            UpAxisType upAxis = UpAxisType.Y_UP;

            var asset = Model.asset;
            if (asset != null)
            {
                upAxis = asset.up_axis;
                if (asset.unit != null)
                {
                    float meter = (float)asset.unit.meter;
                    transform[0, 0] = meter;
                    transform[1, 1] = meter;
                    transform[2, 2] = meter;
                }
            }

            Matrix4 rotation = Matrix4.Identity;

            if (upAxis == UpAxisType.X_UP)
            {
                rotation = Matrix4.CreateFromEulers(0.0f, 90.0f * DEG_TO_RAD, 0.0f);
            }
            else if (upAxis == UpAxisType.Y_UP)
            {
                rotation = Matrix4.CreateFromEulers(90.0f * DEG_TO_RAD, 0.0f, 0.0f);
            }

            rotation = rotation * transform;
            transform = rotation;

            ParseVisualScene();
            ParseMaterials();

            foreach (var item in Model.Items)
            {
                if (item is library_geometries)
                {
                    var geometries = (library_geometries)item;
                    foreach (var geo in geometries.geometry)
                    {
                        var mesh = geo.Item as mesh;
                        if (mesh == null) continue;

                        var nodes = Nodes.FindAll(n => n.MeshID == geo.id);
                        if (nodes != null)
                        {
                            byte[] mesh_asset = null;
                            foreach (var node in nodes)
                            {
                                var prim = new ModelPrim();
                                prim.ID = node.ID;
                                Prims.Add(prim);
                                Matrix4 primTransform = transform;
                                primTransform = primTransform * node.Transform;

                                AddPositions(mesh, prim, primTransform);

                                foreach (var mitem in mesh.Items)
                                {
                                    if (mitem is triangles)
                                    {
                                        AddFacesFromPolyList(Triangles2Polylist((triangles)mitem), mesh, prim, primTransform);
                                    }
                                    if (mitem is polylist)
                                    {
                                        AddFacesFromPolyList((polylist)mitem, mesh, prim, primTransform);
                                    }
                                }

                                if (mesh_asset == null)
                                {
                                    prim.CreateAsset(UUID.Zero);
                                    mesh_asset = prim.Asset;
                                }
                                else
                                    prim.Asset = mesh_asset;
                            }
                        }
                    }
                }
            }

            return Prims;
        }
Example #7
0
        List <ModelPrim> Parse()
        {
            var Prims = new List <ModelPrim>();

            float DEG_TO_RAD = 0.017453292519943295769236907684886f;

            if (Model == null)
            {
                return(Prims);
            }

            Matrix4 transform = Matrix4.Identity;

            UpAxisType upAxis = UpAxisType.Y_UP;

            var asset = Model.asset;

            if (asset != null)
            {
                upAxis = asset.up_axis;
                if (asset.unit != null)
                {
                    float meter = (float)asset.unit.meter;
                    transform[0, 0] = meter;
                    transform[1, 1] = meter;
                    transform[2, 2] = meter;
                }
            }

            Matrix4 rotation = Matrix4.Identity;

            if (upAxis == UpAxisType.X_UP)
            {
                rotation = Matrix4.CreateFromEulers(0.0f, 90.0f * DEG_TO_RAD, 0.0f);
            }
            else if (upAxis == UpAxisType.Y_UP)
            {
                rotation = Matrix4.CreateFromEulers(90.0f * DEG_TO_RAD, 0.0f, 0.0f);
            }

            rotation  = rotation * transform;
            transform = rotation;

            ParseVisualScene();
            ParseMaterials();

            foreach (var item in Model.Items)
            {
                if (item is library_geometries)
                {
                    var geometries = (library_geometries)item;
                    foreach (var geo in geometries.geometry)
                    {
                        var mesh = geo.Item as mesh;
                        if (mesh == null)
                        {
                            continue;
                        }

                        var nodes = Nodes.FindAll(n => n.MeshID == geo.id);
                        if (nodes != null)
                        {
                            byte[] mesh_asset = null;
                            foreach (var node in nodes)
                            {
                                var prim = new ModelPrim();
                                prim.ID = node.ID;
                                Prims.Add(prim);
                                Matrix4 primTransform = transform;
                                primTransform = primTransform * node.Transform;

                                AddPositions(mesh, prim, primTransform);

                                foreach (var mitem in mesh.Items)
                                {
                                    if (mitem is triangles)
                                    {
                                        AddFacesFromPolyList(Triangles2Polylist((triangles)mitem), mesh, prim, primTransform);
                                    }
                                    if (mitem is polylist)
                                    {
                                        AddFacesFromPolyList((polylist)mitem, mesh, prim, primTransform);
                                    }
                                }

                                if (mesh_asset == null)
                                {
                                    prim.CreateAsset(UUID.Zero);
                                    mesh_asset = prim.Asset;
                                }
                                else
                                {
                                    prim.Asset = mesh_asset;
                                }
                            }
                        }
                    }
                }
            }

            return(Prims);
        }