Esempio n. 1
0
        private void InitScene()
        {
            _scene       = new gltf.Scene();
            _scene.Nodes = new[] { 0 };

            _topNode        = new gltf.Node();
            _topNode.Name   = "Z_UP";
            _topNode.Matrix = new[]
            {
                1.0f, 0.0f, 0.0f, 0.0f,
                0.0f, 0.0f, -1.0f, 0.0f,
                0.0f, 1.0f, 0.0f, 0.0f,
                0.0f, 0.0f, 0.0f, 1.0f
            };
            _nodes.Add(_topNode);
        }
Esempio n. 2
0
		void loadNode (Node parentNode, GL.Node gltfNode) {
			Debug.WriteLine ("Loading node {0}", gltfNode.Name);

			Vector3 translation = new Vector3 ();
			Quaternion rotation = Quaternion.Identity;
			Vector3 scale = new Vector3 (1);
			Matrix4x4 localTransform = Matrix4x4.Identity;

			if (gltfNode.Matrix != null) {
				float[] M = gltfNode.Matrix;
				localTransform = new Matrix4x4 (
					M[0], M[1], M[2], M[3],
					M[4], M[5], M[6], M[7],
					M[8], M[9],M[10],M[11],
				   M[12],M[13],M[14],M[15]);
			}

			if (gltfNode.Translation != null) 
				FromFloatArray (ref translation, gltfNode.Translation);
			if (gltfNode.Translation != null) 
				FromFloatArray (ref rotation, gltfNode.Rotation);			
			if (gltfNode.Translation != null) 
				FromFloatArray (ref scale, gltfNode.Scale);

			localTransform *=
				Matrix4x4.CreateScale (scale) *
				Matrix4x4.CreateFromQuaternion (rotation) *
				Matrix4x4.CreateTranslation (translation);

			//localTransform = Matrix4x4.Identity;

			Node node = new Node {
				localMatrix = localTransform,
				Parent = parentNode,
                Name = gltfNode.Name
			};
			parentNode.Children.Add (node);

			if (gltfNode.Children != null) {
				node.Children = new List<Node> ();
				for (int i = 0; i < gltfNode.Children.Length; i++)
					loadNode (node, gltf.Nodes[gltfNode.Children[i]]);
			}

			if (gltfNode.Mesh != null)
				node.Mesh = meshes[(int)gltfNode.Mesh];
		}
Esempio n. 3
0
        /// <summary>
        /// We construct a new, recursively-structured 'ProtoNode' from the flat gltf node, and mutate its mesh indices to
        /// point to the correct mesh in the merged gltf.
        /// </summary>
        private static ProtoNode RecursivelyModifyMeshIndices(glTFLoader.Schema.Node node, List <int> meshIndices, glTFLoader.Schema.Node[] loadedNodes)
        {
            var protoNode = new ProtoNode();

            protoNode.Matrix = node.Matrix;
            if (node.Mesh != null)
            {
                protoNode.Mesh = meshIndices[node.Mesh.Value];
            }
            if (node.Children != null && node.Children.Count() > 0)
            {
                foreach (var child in node.Children)
                {
                    protoNode.Children.Add(RecursivelyModifyMeshIndices(loadedNodes[child], meshIndices, loadedNodes));
                }
            }
            return(protoNode);
        }
Esempio n. 4
0
        internal static void AddInstanceAsCopyOfNode(
            List <glTFLoader.Schema.Node> nodes,
            ProtoNode nodeToCopy,
            Transform transform,
            System.Guid instanceElementId)
        {
            // Two new nodes are created: a top-level node, which has the
            // element's Transform, and one just below that, which handles
            // flipping the orientation of the glb to have Z up. That node has
            // the node to copy as its only child.
            // We use the node to copy exactly as is, with an unmodified
            // transform.
            // We need the outermost node to be "purely" the element's
            // transform, so that the transform can be modified in explore at
            // runtime (e.g. by a transform override) and have the expected effect.
            float[] elementTransform = TransformToMatrix(transform);
            var     newNode          = new glTFLoader.Schema.Node();

            newNode.Name   = $"{instanceElementId}";
            newNode.Matrix = elementTransform;
            nodes.Add(newNode);
            newNode.Children = new[] { nodes.Count };

            var rootTransform = new Transform();

            // glb has Y up. transform it to have Z up so we
            // can create instances of it in a Z up world. It will get switched
            // back to Y up further up in the node hierarchy.
            rootTransform.Rotate(new Vector3(1, 0, 0), 90.0);
            float[] glbOrientationTransform = TransformToMatrix(rootTransform);
            var     elementOrientationNode  = new glTFLoader.Schema.Node();

            elementOrientationNode.Matrix = glbOrientationTransform;
            nodes.Add(elementOrientationNode);
            elementOrientationNode.Children = new[] { nodes.Count };

            nodes[0].Children = (nodes[0].Children ?? Array.Empty <int>()).Concat(new[] { nodes.Count - 2 }).ToArray();

            RecursivelyCopyNode(nodes, nodeToCopy);
        }
Esempio n. 5
0
        /// <summary>
        /// Exports a gltf file from a meshed model
        /// </summary>
        /// <param name="model">The model needs to have the geometry meshes already cached</param>
        /// <param name="exclude">The types of elements that are going to be omitted (e.g. ifcSpaces).</param>
        /// <param name="EntityLebels">Only entities in the collection are exported; if null exports the whole model</param>
        /// <returns></returns>
        public gltf.Gltf BuildInstancedScene(IModel model, List <Type> exclude = null, HashSet <int> EntityLebels = null)
        {
            Init();
            Dictionary <int, ShapeComponentIds> geometries = new Dictionary <int, ShapeComponentIds>();

            // this needs a previously meshed xbim file.
            //
            var s = new Stopwatch();

            s.Start();
            int    iCnt          = 0;
            Random r             = new Random();
            var    excludedTypes = DefaultExclusions(model, exclude);

            using (var geomStore = model.GeometryStore)
                using (var geomReader = geomStore.BeginRead())
                {
                    // process the materials and styles
                    var sstyleIds = geomReader.StyleIds;
                    foreach (var styleId in sstyleIds)
                    {
                        PrepareStyleMaterial(model, styleId);
                    }
                    int productLabel   = 0;
                    var shapeInstances = GetShapeInstancesToRender(geomReader, excludedTypes, EntityLebels);
                    // foreach (var shapeInstance in shapeInstances.OrderBy(x=>x.IfcProductLabel))
                    gltf.Mesh targetMesh = null;
                    foreach (var shapeInstance in shapeInstances.OrderBy(x => x.IfcProductLabel))
                    {
                        if (CustomFilter != null)
                        {
                            var skip = CustomFilter(shapeInstance.IfcProductLabel, model);
                            if (skip)
                            {
                                continue;
                            }
                        }

                        // we start with a shape instance and then load its geometry.

                        // a product (e.g. wall or window) in the scene returns:
                        // - a node
                        //   - pointing to a mesh, with a transform
                        // - 1 mesh
                        //   - with as many mesh primitives as needed to render the different parts
                        //   - pointers to the a material and accessors as needed
                        // - 3 accessors per primitive
                        //   - vertices, normals, indices
                        // - bufferviews can be reused by different accessors
                        // - data in the buffer, of course

                        if (productLabel != shapeInstance.IfcProductLabel)
                        {
                            // need new product

                            // create node
                            var nodeIndex = _nodes.Count;
                            var entity    = model.Instances[shapeInstance.IfcProductLabel] as IIfcProduct;
                            if (entity == null)
                            { // fire error here.
                            }
                            var tnode = new gltf.Node();
                            tnode.Name   = entity.Name + $" #{entity.EntityLabel}";
                            tnode.Matrix = GetTransformInMeters(model, shapeInstance);

                            // create mesh
                            var meshIndex = _meshes.Count;
                            targetMesh = new gltf.Mesh
                            {
                                Name = $"Instance {productLabel}"
                            };

                            // link node to mesh
                            tnode.Mesh = meshIndex;

                            // add all to lists
                            _nodes.Add(tnode);
                            _meshes.Add(targetMesh);
                        }

                        // now the geometry
                        //
                        IXbimShapeGeometryData shapeGeom = geomReader.ShapeGeometry(shapeInstance.ShapeGeometryLabel);
                        if (shapeGeom.Format != (byte)XbimGeometryType.PolyhedronBinary)
                        {
                            continue;
                        }

                        // work out colour id;
                        // the colour is associated with the instance, not the geometry.
                        // positives are styles, negatives are types
                        var colId = shapeInstance.StyleLabel > 0
                        ? shapeInstance.StyleLabel
                        : shapeInstance.IfcTypeId * -1;

                        int materialIndex;
                        if (!styleDic.TryGetValue(colId, out materialIndex))
                        {
                            // if the style is not available we build one by ExpressType
                            materialIndex = PrepareTypeMaterial(model, shapeInstance.IfcTypeId);
                            styleDic.Add(colId, materialIndex);
                        }

                        // note: at a first investigation it looks like the shapeInstance.Transformation is the same for all shapes of the same product

                        if (shapeGeom.ReferenceCount > 1)
                        {
                            // retain the information to reuse the map multiple times
                            //

                            // if g is not found in the dictionary then build it and add it
                            ShapeComponentIds components;
                            if (!geometries.TryGetValue(shapeGeom.ShapeLabel, out components))
                            {
                                // mesh
                                var xbimMesher = new XbimMesher();
                                xbimMesher.AddMesh(shapeGeom.ShapeData);

                                components = AddGeom(
                                    xbimMesher.PositionsAsSingleList(model.ModelFactors.OneMeter),
                                    xbimMesher.Indices,
                                    xbimMesher.NormalsAsSingleList()
                                    );
                                geometries.Add(shapeGeom.ShapeLabel, components);
                            }

                            if (components != null)
                            {
                                var arr = GetTransformInMeters(model, shapeInstance);
                                AddComponentsToMesh(targetMesh, components, materialIndex);
                            }
                        }
                        else
                        {
                            // repeat the geometry only once
                            //
                            var xbimMesher = new XbimMesher();
                            xbimMesher.AddMesh(shapeGeom.ShapeData);
                            var trsf       = GetTransformInMeters(model, shapeInstance);
                            var components = AddGeom(
                                xbimMesher.PositionsAsSingleList(model.ModelFactors.OneMeter),
                                xbimMesher.Indices,
                                xbimMesher.NormalsAsSingleList()
                                );
                            AddComponentsToMesh(targetMesh, components, materialIndex);
                        }
                        iCnt++;
                        if (iCnt % 100 == 0)
                        {
                            Debug.WriteLine($"added {iCnt} elements in {s.ElapsedMilliseconds}ms.");
                        }
                    }
                }
            Debug.WriteLine($"added {iCnt} elements in {s.ElapsedMilliseconds}ms.");

            return(Build());
        }
Esempio n. 6
0
        public Gltf ConvertToGltf()
        {
            dummy.Scene = 0;
            dummy.Scenes.Add(new gltfSchemaSceneDummy());

            dummy.Asset = new Asset()
            {
                Version = "2.0",
            };

            dummy.Samplers.Add(new Sampler()
            {
                MinFilter = Sampler.MinFilterEnum.LINEAR,
                MagFilter = Sampler.MagFilterEnum.LINEAR,
                WrapS     = Sampler.WrapSEnum.REPEAT,
                WrapT     = Sampler.WrapTEnum.REPEAT,
            });

            if (options.UseDracoCompression)
            {
                dummy.ExtensionsUsed.Add(glTFExtensions.KHR_draco_mesh_compression.Tag);
                dummy.ExtensionsRequired.Add(glTFExtensions.KHR_draco_mesh_compression.Tag);
            }

            dummy.ExtensionsUsed.Add(glTFExtensions.KHR_materials_transmission.Tag);
            dummy.ExtensionsUsed.Add(glTFExtensions.KHR_materials_clearcoat.Tag);
            dummy.ExtensionsUsed.Add(glTFExtensions.KHR_materials_ior.Tag);
            dummy.ExtensionsUsed.Add(glTFExtensions.KHR_materials_specular.Tag);

            var sanitized = SanitizeRhinoObjects(objects);

            foreach (ObjectExportData exportData in sanitized)
            {
                int?materialIndex = GetMaterial(exportData.RenderMaterial, exportData.Object);

                RhinoMeshGltfConverter meshConverter = new RhinoMeshGltfConverter(exportData, materialIndex, options, binary, dummy, binaryBuffer);
                int meshIndex = meshConverter.AddMesh();

                glTFLoader.Schema.Node node = new glTFLoader.Schema.Node()
                {
                    Mesh = meshIndex,
                    Name = GetObjectName(exportData.Object),
                };

                int nodeIndex = dummy.Nodes.AddAndReturnIndex(node);

                if (options.ExportLayers)
                {
                    AddToLayer(doc.Layers[exportData.Object.Attributes.LayerIndex], nodeIndex);
                }
                else
                {
                    dummy.Scenes[dummy.Scene].Nodes.Add(nodeIndex);
                }
            }

            if (binary && binaryBuffer.Count > 0)
            {
                //have to add the empty buffer for the binary file header
                dummy.Buffers.Add(new glTFLoader.Schema.Buffer()
                {
                    ByteLength = (int)binaryBuffer.Count,
                    Uri        = null,
                });
            }

            return(dummy.ToSchemaGltf());
        }