Ejemplo n.º 1
0
        /// <summary>
        /// Runs at the end of an element being processed, after all other calls for that element.
        /// Here we compile all the "_current" variables (geometry and vertices) onto glTF buffers.
        /// We do this at OnElementEnd because it signals no more meshes or materials are
        /// coming for this element.
        /// </summary>
        /// <param name="elementId"></param>
        public void OnElementEnd(ElementId elementId)
        {
            Debug.WriteLine("  OnElementEnd");
            if (_skipElementFlag)
            {
                // Duplicate element, skip.
                _skipElementFlag = false;
                return;
            }

            if (_currentVertices.List.Count == 0)
            {
                return;
            }

            Element e = _doc.GetElement(elementId);

            // create a new mesh for the node (we're assuming 1 mesh per node w/ multiple primatives on mesh)
            glTFMesh newMesh = new glTFMesh();

            newMesh.primitives = new List <glTFMeshPrimitive>();
            Meshes.AddOrUpdateCurrent(e.UniqueId, newMesh);

            // add the index of this mesh to the current node.
            Nodes.CurrentItem.mesh = Meshes.CurrentIndex;

            // Add vertex data to _currentGeometry for each geometry/material pairing
            foreach (KeyValuePair <string, VertexLookupInt> kvp in _currentVertices.Dict)
            {
                string vertex_key = kvp.Key;
                foreach (KeyValuePair <PointInt, int> p in kvp.Value)
                {
                    _currentGeometry.GetElement(vertex_key).vertices.Add(p.Key.X);
                    _currentGeometry.GetElement(vertex_key).vertices.Add(p.Key.Y);
                    _currentGeometry.GetElement(vertex_key).vertices.Add(p.Key.Z);
                }
            }

            // Convert _currentGeometry objects into glTFMeshPrimitives
            foreach (KeyValuePair <string, GeometryData> kvp in _currentGeometry.Dict)
            {
                glTFBinaryData elementBinary = AddGeometryMeta(kvp.Value, kvp.Key, elementId.IntegerValue);
                binaryFileData.Add(elementBinary);

                string material_key = kvp.Key.Split('_')[1];

                glTFMeshPrimitive primitive = new glTFMeshPrimitive();
                primitive.attributes.POSITION = elementBinary.vertexAccessorIndex;
                //primitive.attributes.NORMAL = elementBinary.normalsAccessorIndex;
                primitive.attributes._BATCHID = elementBinary.batchIdAccessorIndex;
                primitive.indices             = elementBinary.indexAccessorIndex;
                primitive.material            = Materials.GetIndexFromUUID(material_key);

                Meshes.CurrentItem.primitives.Add(primitive);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Takes the intermediate geometry data and performs the calculations
        /// to convert that into glTF buffers, views, and accessors.
        /// </summary>
        /// <param name="geomData"></param>
        /// <param name="name">Unique name for the .bin file that will be produced.</param>
        /// <param name="elementId">Revit element's Element ID that will be used as the batchId value.</param>
        /// <returns></returns>
        public glTFBinaryData AddGeometryMeta(GeometryData geomData, string name, int elementId)
        {
            // add a buffer
            glTFBuffer buffer = new glTFBuffer();

            buffer.uri = name + ".bin";
            Buffers.Add(buffer);
            int bufferIdx = Buffers.Count - 1;

            /**
             * Buffer Data
             **/
            glTFBinaryData bufferData = new glTFBinaryData();

            bufferData.name = buffer.uri;
            foreach (var coord in geomData.vertices)
            {
                float vFloat = Convert.ToSingle(coord);
                bufferData.vertexBuffer.Add(vFloat);
            }
            //foreach (var normal in geomData.normals)
            //{
            //    bufferData.normalBuffer.Add((float)normal);
            //}
            foreach (var index in geomData.faces)
            {
                bufferData.indexBuffer.Add(index);
            }
            foreach (var coord in geomData.vertices)
            {
                bufferData.batchIdBuffer.Add(elementId);
            }

            // Get max and min for vertex data
            float[] vertexMinMax = Util.GetVec3MinMax(bufferData.vertexBuffer);
            // Get max and min for normal data
            //float[] normalMinMax = Util.GetVec3MinMax(bufferData.normalBuffer);
            // Get max and min for index data
            int[] faceMinMax = Util.GetScalarMinMax(bufferData.indexBuffer);
            // Get max and min for batchId data
            float[] batchIdMinMax = Util.GetVec3MinMax(bufferData.batchIdBuffer);

            /**
             * BufferViews
             **/
            // Add a vec3 buffer view
            int            elementsPerVertex = 3;
            int            bytesPerElement   = 4;
            int            bytesPerVertex    = elementsPerVertex * bytesPerElement;
            int            numVec3           = (geomData.vertices.Count) / elementsPerVertex;
            int            sizeOfVec3View    = numVec3 * bytesPerVertex;
            glTFBufferView vec3View          = new glTFBufferView();

            vec3View.buffer     = bufferIdx;
            vec3View.byteOffset = 0;
            vec3View.byteLength = sizeOfVec3View;
            vec3View.target     = Targets.ARRAY_BUFFER;
            BufferViews.Add(vec3View);
            int vec3ViewIdx = BufferViews.Count - 1;

            // Add a normals (vec3) buffer view
            //int elementsPerNormal = 3;
            //int bytesPerNormalElement = 4;
            //int bytesPerNormal = elementsPerNormal * bytesPerNormalElement;
            //int numVec3Normals = (geomData.normals.Count) / elementsPerNormal;
            //int sizeOfVec3ViewNormals = numVec3Normals * bytesPerNormal;
            //glTFBufferView vec3ViewNormals = new glTFBufferView();
            //vec3ViewNormals.buffer = bufferIdx;
            //vec3ViewNormals.byteOffset = vec3View.byteLength;
            //vec3ViewNormals.byteLength = sizeOfVec3ViewNormals;
            //vec3ViewNormals.target = Targets.ELEMENT_ARRAY_BUFFER;
            //BufferViews.Add(vec3ViewNormals);
            //int vec3ViewNormalsIdx = BufferViews.Count - 1;

            // Add a faces / indexes buffer view
            int            elementsPerIndex     = 1;
            int            bytesPerIndexElement = 4;
            int            bytesPerIndex        = elementsPerIndex * bytesPerIndexElement;
            int            numIndexes           = geomData.faces.Count;
            int            sizeOfIndexView      = numIndexes * bytesPerIndex;
            glTFBufferView facesView            = new glTFBufferView();

            facesView.buffer     = bufferIdx;
            facesView.byteOffset = vec3View.byteLength;
            //facesView.byteOffset = vec3ViewNormals.byteOffset + vec3ViewNormals.byteLength;
            facesView.byteLength = sizeOfIndexView;
            facesView.target     = Targets.ELEMENT_ARRAY_BUFFER;
            BufferViews.Add(facesView);
            int facesViewIdx = BufferViews.Count - 1;

            // Add a batchId buffer view
            glTFBufferView batchIdsView = new glTFBufferView();

            batchIdsView.buffer     = bufferIdx;
            batchIdsView.byteOffset = facesView.byteOffset + facesView.byteLength;
            batchIdsView.byteLength = sizeOfVec3View;
            batchIdsView.target     = Targets.ARRAY_BUFFER;
            BufferViews.Add(batchIdsView);
            int batchIdsViewIdx = BufferViews.Count - 1;

            //Buffers[bufferIdx].byteLength = vec3View.byteLength + vec3ViewNormals.byteLength + facesView.byteLength + batchIdsView.byteLength;
            Buffers[bufferIdx].byteLength = vec3View.byteLength + facesView.byteLength + batchIdsView.byteLength;

            /**
             * Accessors
             **/
            // add a position accessor
            glTFAccessor positionAccessor = new glTFAccessor();

            positionAccessor.bufferView    = vec3ViewIdx;
            positionAccessor.byteOffset    = 0;
            positionAccessor.componentType = ComponentType.FLOAT;
            positionAccessor.count         = geomData.vertices.Count / elementsPerVertex;
            positionAccessor.type          = "VEC3";
            positionAccessor.max           = new List <float>()
            {
                vertexMinMax[1], vertexMinMax[3], vertexMinMax[5]
            };
            positionAccessor.min = new List <float>()
            {
                vertexMinMax[0], vertexMinMax[2], vertexMinMax[4]
            };
            positionAccessor.name = "POSITION";
            Accessors.Add(positionAccessor);
            bufferData.vertexAccessorIndex = Accessors.Count - 1;

            //add a normals accessor
            //glTFAccessor normalsAccessor = new glTFAccessor();
            //normalsAccessor.bufferView = vec3ViewNormalsIdx;
            //normalsAccessor.byteOffset = 0;
            //normalsAccessor.componentType = ComponentType.FLOAT;
            //normalsAccessor.count = geomData.normals.Count / elementsPerNormal;
            //normalsAccessor.type = "VEC3";
            //normalsAccessor.max = new List<float>() { normalMinMax[1], normalMinMax[3], normalMinMax[5] };
            //normalsAccessor.min = new List<float>() { normalMinMax[0], normalMinMax[2], normalMinMax[4] };
            //normalsAccessor.name = "NORMALS";
            //Accessors.Add(normalsAccessor);
            //bufferData.normalsAccessorIndex = Accessors.Count - 1;

            // add a face accessor
            glTFAccessor faceAccessor = new glTFAccessor();

            faceAccessor.bufferView    = facesViewIdx;
            faceAccessor.byteOffset    = 0;
            faceAccessor.componentType = ComponentType.UNSIGNED_INT;
            //faceAccessor.count = numIndexes;
            faceAccessor.count = geomData.faces.Count / elementsPerIndex;
            faceAccessor.type  = "SCALAR";
            faceAccessor.max   = new List <float>()
            {
                faceMinMax[1]
            };
            faceAccessor.min = new List <float>()
            {
                faceMinMax[0]
            };
            faceAccessor.name = "FACE";
            Accessors.Add(faceAccessor);
            bufferData.indexAccessorIndex = Accessors.Count - 1;

            // add a batchId accessor
            glTFAccessor batchIdAccessor = new glTFAccessor();

            batchIdAccessor.bufferView    = batchIdsViewIdx;
            batchIdAccessor.byteOffset    = 0;
            batchIdAccessor.componentType = ComponentType.FLOAT;
            //batchIdAccessor.count = numIndexes;
            batchIdAccessor.count = geomData.vertices.Count / elementsPerVertex;
            batchIdAccessor.type  = "VEC3";
            //batchIdAccessor.max = new List<float>() { batchIdMinMax[1] };
            //batchIdAccessor.min = new List<float>() { batchIdMinMax[0] };
            batchIdAccessor.max = new List <float>()
            {
                batchIdMinMax[1], batchIdMinMax[3], batchIdMinMax[5]
            };
            batchIdAccessor.min = new List <float>()
            {
                batchIdMinMax[0], batchIdMinMax[2], batchIdMinMax[4]
            };
            batchIdAccessor.name = "BATCH_ID";
            Accessors.Add(batchIdAccessor);
            bufferData.batchIdAccessorIndex = Accessors.Count - 1;

            return(bufferData);
        }