Exemple #1
0
        public void OpenNode(Element elem, Transform xform = null, bool isInstance = false)
        {
            //// TODO: [RM] Commented out because this is likely to be very buggy and not the
            //// correct solution intent is to prevent creation of new nodes when a symbol
            //// is a child of an instance of the same type.
            //// Witness: parking spaces and stair railings for examples of two
            //// different issues with the behavior
            //if (isInstance == true && elem is FamilySymbol)
            //{
            //    FamilyInstance parentInstance = nodeDict[currentNodeId].element as FamilyInstance;
            //    if (
            //        parentInstance != null &&
            //        parentInstance.Symbol != null &&
            //        elem.Name == parentInstance.Symbol.Name
            //    )
            //    {
            //        nodeDict[currentNodeId].matrix = ManagerUtils.ConvertXForm(xform);
            //        return;
            //    }

            //    //nodeDict[currentNodeId].matrix = ManagerUtils.ConvertXForm(xform);
            //    //return;
            //}
            bool exportNodeProperties = _exportProperties;

            if (isInstance == true && elem is FamilySymbol)
            {
                exportNodeProperties = false;
            }

            Node node = new Node(elem, nodeDict.Count, exportNodeProperties, isInstance, formatDebugHeirarchy);

            if (parentStack.Count > 0)
            {
                string parentId   = parentStack.Peek();
                Node   parentNode = nodeDict[parentId];
                if (parentNode.children == null)
                {
                    parentNode.children = new List <int>();
                }
                nodeDict[parentId].children.Add(node.index);
            }

            parentStack.Push(node.id);
            if (xform != null)
            {
                node.matrix = ManagerUtils.ConvertXForm(xform);
            }

            nodeDict.Add(node.id, node);

            OpenGeometry();
            Debug.WriteLine(String.Format("{0}Node Open", formatDebugHeirarchy));
        }
Exemple #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>
        /// <returns></returns>
        private glTFBinaryData processGeometry(GeometryData geom, string name)
        {
            // TODO: rename this type to glTFBufferMeta ?
            glTFBinaryData           bufferData     = new glTFBinaryData();
            glTFBinaryBufferContents bufferContents = new glTFBinaryBufferContents();

            foreach (var coord in geom.vertices)
            {
                float vFloat = Convert.ToSingle(coord);
                bufferContents.vertexBuffer.Add(vFloat);
            }
            foreach (var index in geom.faces)
            {
                bufferContents.indexBuffer.Add(index);
            }

            // Prevent buffer duplication by hash checking
            string calculatedHash = ManagerUtils.GenerateSHA256Hash(bufferContents);

            ManagerUtils.HashSearch hs = new ManagerUtils.HashSearch(calculatedHash);
            var match = binaryFileData.Find(hs.EqualTo);

            if (match != null)
            {
                // return previously created buffer metadata
                bufferData.vertexAccessorIndex = match.vertexAccessorIndex;
                bufferData.indexAccessorIndex  = match.indexAccessorIndex;
                return(bufferData);
            }
            else
            {
                // add a buffer
                glTFBuffer buffer = new glTFBuffer();
                buffer.uri = name + ".bin";
                buffers.Add(buffer);
                int bufferIdx = buffers.Count - 1;

                /**
                 * Buffer Data
                 **/
                bufferData.name     = buffer.uri;
                bufferData.contents = bufferContents;
                // TODO: Uncomment for normals
                //foreach (var normal in geomData.normals)
                //{
                //    bufferData.normalBuffer.Add((float)normal);
                //}

                // Get max and min for vertex data
                float[] vertexMinMax = Util.GetVec3MinMax(bufferContents.vertexBuffer);
                // Get max and min for index data
                int[] faceMinMax = Util.GetScalarMinMax(bufferContents.indexBuffer);
                // TODO: Uncomment for normals
                // Get max and min for normal data
                //float[] normalMinMax = getVec3MinMax(bufferData.normalBuffer);

                /**
                 * BufferViews
                 **/
                // Add a vec3 buffer view
                int            elementsPerVertex = 3;
                int            bytesPerElement   = 4;
                int            bytesPerVertex    = elementsPerVertex * bytesPerElement;
                int            numVec3           = (geom.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;

                // TODO: Add a normals (vec3) buffer view

                // Add a faces / indexes buffer view
                int            elementsPerIndex     = 1;
                int            bytesPerIndexElement = 4;
                int            bytesPerIndex        = elementsPerIndex * bytesPerIndexElement;
                int            numIndexes           = geom.faces.Count;
                int            sizeOfIndexView      = numIndexes * bytesPerIndex;
                glTFBufferView facesView            = new glTFBufferView();
                facesView.buffer     = bufferIdx;
                facesView.byteOffset = vec3View.byteLength;
                facesView.byteLength = sizeOfIndexView;
                facesView.target     = Targets.ELEMENT_ARRAY_BUFFER;
                bufferViews.Add(facesView);
                int facesViewIdx = bufferViews.Count - 1;

                buffers[bufferIdx].byteLength = vec3View.byteLength + facesView.byteLength;

                /**
                 * Accessors
                 **/
                // add a position accessor
                glTFAccessor positionAccessor = new glTFAccessor();
                positionAccessor.bufferView    = vec3ViewIdx;
                positionAccessor.byteOffset    = 0;
                positionAccessor.componentType = ComponentType.FLOAT;
                positionAccessor.count         = geom.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]
                };
                accessors.Add(positionAccessor);
                bufferData.vertexAccessorIndex = accessors.Count - 1;

                // TODO: Uncomment for normals
                // add a normals accessor
                //glTFAccessor normalsAccessor = new glTFAccessor();
                //normalsAccessor.bufferView = vec3ViewIdx;
                //normalsAccessor.byteOffset = (positionAccessor.count) * bytesPerVertex;
                //normalsAccessor.componentType = ComponentType.FLOAT;
                //normalsAccessor.count = geom.data.normals.Count / elementsPerVertex;
                //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] };
                //this.accessors.Add(normalsAccessor);
                //bufferData.normalsAccessorIndex = this.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.type          = "SCALAR";
                faceAccessor.max           = new List <float>()
                {
                    faceMinMax[1]
                };
                faceAccessor.min = new List <float>()
                {
                    faceMinMax[0]
                };
                accessors.Add(faceAccessor);
                bufferData.indexAccessorIndex = accessors.Count - 1;

                bufferData.hashcode = calculatedHash;

                return(bufferData);
            }
        }
Exemple #3
0
        public void CloseGeometry()
        {
            Debug.WriteLine(String.Format("{0}  Closing Geometry", formatDebugHeirarchy));
            // Create the new mesh and populate the primitives with GeometryData
            glTFMesh mesh = new glTFMesh();

            mesh.primitives = new List <glTFMeshPrimitive>();

            // transfer ordered vertices from vertex dictionary to vertices list
            foreach (KeyValuePair <string, GeometryData> key_geom in currentGeom)
            {
                string       key  = key_geom.Key;
                GeometryData geom = key_geom.Value;
                foreach (KeyValuePair <PointInt, int> point_index in geom.vertDictionary)
                {
                    PointInt point = point_index.Key;
                    geom.vertices.Add(point.X);
                    geom.vertices.Add(point.Y);
                    geom.vertices.Add(point.Z);
                }

                // convert GeometryData objects into glTFMeshPrimitive
                string material_key = key.Split('_')[1];

                glTFBinaryData bufferMeta = processGeometry(geom, key);
                if (bufferMeta.hashcode != null)
                {
                    binaryFileData.Add(bufferMeta);
                }

                glTFMeshPrimitive primative = new glTFMeshPrimitive();

                primative.attributes.POSITION = bufferMeta.vertexAccessorIndex;
                primative.indices             = bufferMeta.indexAccessorIndex;
                primative.material            = materialDict.GetIndexFromUUID(material_key);
                // TODO: Add normal attribute accessor index here

                mesh.primitives.Add(primative);
            }

            // glTF entity can not be empty
            if (mesh.primitives.Count() > 0)
            {
                // Prevent mesh duplication by hash checking
                string meshHash            = ManagerUtils.GenerateSHA256Hash(mesh);
                ManagerUtils.HashSearch hs = new ManagerUtils.HashSearch(meshHash);
                int idx = meshContainers.FindIndex(hs.EqualTo);

                if (idx != -1)
                {
                    // set the current nodes mesh index to the already
                    // created mesh location.
                    nodeDict[currentNodeId].mesh = idx;
                }
                else
                {
                    // create new mesh and add it's index to the current node.
                    MeshContainer mc = new MeshContainer();
                    mc.hashcode = meshHash;
                    mc.contents = mesh;
                    meshContainers.Add(mc);
                    nodeDict[currentNodeId].mesh = meshContainers.Count - 1;
                }
            }

            geometryStack.Pop();
            return;
        }