public glTF RecursivelyAddChilren(glTF gltf, Va3cObject obj, int parentIndex) { foreach (var child in obj.children) { glTFNode childNode = new glTFNode(); childNode.name = child.name; foreach (double coord in child.matrix) { childNode.matrix.Add((float)coord); } int childIndex = gltf.AddChildNode(childNode, parentIndex); if (child.geometry != null) { Va3cGeometry geom = _geometries[child.geometry]; // make an accessor, buffer, and bufferView glTFBinaryData dataContainer = gltf.AddGeometryMeta(geom, child.uuid); binaryFileData.Add(dataContainer); // add geometry to meshes array glTFMesh mesh = new glTFMesh(); glTFMeshPrimitive primative = new glTFMeshPrimitive(); primative.attributes.POSITION = dataContainer.vertexAccessorIndex; primative.attributes.NORMAL = dataContainer.normalsAccessorIndex; primative.indices = dataContainer.indexAccessorIndex; mesh.primitives = new List <glTFMeshPrimitive>() { primative }; int meshIndex = gltf.AddMesh(mesh); gltf.nodes[childIndex].mesh = meshIndex; } if (child.children != null && child.children.Count > 0) { return(RecursivelyAddChilren(gltf, child, childIndex)); } } return(gltf); }
public glTFBinaryData AddGeometryMeta(Va3cGeometry geom, string name) { // add a buffer glTFBuffer buffer = new glTFBuffer(); buffer.uri = name + ".bin"; this.buffers.Add(buffer); int bufferIdx = this.buffers.Count - 1; Va3cGeometryData geomData = geom.data; glTFBinaryData bufferData = new glTFBinaryData(); bufferData.name = buffer.uri; foreach (var coord in geomData.vertices) { bufferData.vertexBuffer.Add((float)coord); } foreach (var index in geomData.faces) { bufferData.indexBuffer.Add(index); } foreach (var normal in geomData.normals) { bufferData.normalBuffer.Add((float)normal); } // Get max and min for vertex data float[] vertexMinMax = getVec3MinMax(bufferData.vertexBuffer); // Get max and min for normal data float[] normalMinMax = getVec3MinMax(bufferData.normalBuffer); // Get max and min for index data int[] faceMinMax = getScalarMinMax(bufferData.indexBuffer); // Add a vec3 buffer view int elementsPerVertex = 3; int bytesPerElement = 4; int bytesPerVertex = elementsPerVertex * bytesPerElement; int numVec3 = (geom.data.normals.Count + geom.data.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; this.bufferViews.Add(vec3View); int vec3ViewIdx = this.bufferViews.Count - 1; // add a position buffer view //int elementsPerVertex = 3; //int bytesPerElement = 4; //int bytesPerVertex = elementsPerVertex * bytesPerElement; //int numVertices = geom.data.vertices.Count / elementsPerVertex; //int sizeOfView = numVertices * bytesPerVertex; //glTFBufferView positionView = new glTFBufferView(); //positionView.buffer = bufferIdx; //positionView.byteOffset = 0; //positionView.byteLength = sizeOfView; //positionView.target = Targets.ARRAY_BUFFER; //this.bufferViews.Add(positionView); //int positionViewIdx = this.bufferViews.Count - 1; // Add a faces / indexes buffer view int elementsPerIndex = 1; int bytesPerIndexElement = 4; int bytesPerIndex = elementsPerIndex * bytesPerIndexElement; int numIndexes = geom.data.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; this.bufferViews.Add(facesView); int facesViewIdx = this.bufferViews.Count - 1; this.buffers[bufferIdx].byteLength = vec3View.byteLength + facesView.byteLength; // add a position accessor glTFAccessor positionAccessor = new glTFAccessor(); positionAccessor.bufferView = vec3ViewIdx; positionAccessor.byteOffset = 0; positionAccessor.componentType = ComponentType.FLOAT; positionAccessor.count = geom.data.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] }; this.accessors.Add(positionAccessor); bufferData.vertexAccessorIndex = this.accessors.Count - 1; // 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] }; this.accessors.Add(faceAccessor); bufferData.indexAccessorIndex = this.accessors.Count - 1; return(bufferData); }