Ejemplo n.º 1
0
class I3DM:
    def __init__(self):
        self.batch_table = BatchTable()
        self.feature_table = InstanceFeatureTable()
        self.gltf_bin = bytearray()

    def loadJSONBatch(self, data_in, object_wise=True):
        self.batch_table.loadJSONBatch(data_in, object_wise)

    def loadJSONInstances(self, i3dm_json, object_wise=True):
        self.loadJSONFeatures(i3dm_json, object_wise)

    def loadJSONFeatures(self, data_in, object_wise=True):
        self.feature_table.loadJSONBatch(data_in, object_wise)

    # If embed_gltf is false, gltf_bin is a URI string instead of GLTF data
    def writeBinary(self,
                    gltf_bin,
                    embed_gltf=True,
                    num_batches=0,
                    num_feature_features=0):
        self.embed_gltf = embed_gltf

        # Add the required field BATCH_LENGTH to the feature table,
        # as well as any other required globals
        num_batch_features = max(num_batches,
                                 self.batch_table.getNumFeatures())
        self.feature_table.addGlobal('BATCH_LENGTH', num_batch_features)
        num_feature_features = max(num_feature_features,
                                   self.feature_table.getNumFeatures())
        self.feature_table.addGlobal('INSTANCES_LENGTH', num_feature_features)

        self.batch_table.finalize()
        self.feature_table.finalize()

        # Generate the header
        output = self.writeHeader(gltf_bin, num_batch_features,
                                  num_feature_features)

        # Add the feature table JSON to the output
        feature_json = self.feature_table.getFeatureJSON()
        output.extend(feature_json)

        # Add the feature table binary to the output
        feature_bin = self.feature_table.getFeatureBin()
        output.extend(feature_bin)

        # Add the batch table JSON to the output
        batch_json = self.batch_table.getBatchJSON()
        output.extend(batch_json)

        # Add the batch table binary to the output
        batch_bin = self.batch_table.getBatchBin()
        output.extend(batch_bin)

        # Add the GLTF model body to the output
        output.extend(gltf_bin)

        return output

    # If embed_gltf is false, gltf_bin is a URI string instead of GLTF data
    def writeHeader(self, gltf_bin, num_batch_features, num_feature_features):
        len_feature_json = len(self.feature_table.getFeatureJSON())
        len_feature_bin = len(self.feature_table.getFeatureBin())
        len_batch_json = len(self.batch_table.getBatchJSON())
        len_batch_bin = len(self.batch_table.getBatchBin())

        length = I3DM_HEADER_LEN + \
                 len_feature_json + len_feature_bin + \
                 len_batch_json   + len_batch_bin + \
                 len(gltf_bin)

        output = bytearray()
        output.extend(I3DM_MAGIC)
        output.extend(struct.pack('<I', I3DM_VERSION))
        output.extend(struct.pack('<I', length))
        output.extend(struct.pack('<I', len_feature_json))
        output.extend(struct.pack('<I', len_feature_bin))
        output.extend(struct.pack('<I', len_batch_json))
        output.extend(struct.pack('<I', len_batch_bin))
        output.extend(struct.pack('<I', 1 if self.embed_gltf else 0))

        # Sanity check
        if (len(output) != I3DM_HEADER_LEN):
            raise ValueError("Incorrect i3dm header length")

        return output

    def readBinary(self, data):
        self.offset = 0
        self.readHeader(data)  # What it says on the tin

        # Now grab the feature table, batch table, and GLB
        self.feature_json = self.unpackString(data, self.len_feature_json)
        self.feature_bin = self.unpackString(data, self.len_feature_bin)
        self.batch_json = self.unpackString(data, self.len_batch_json)
        self.batch_bin = self.unpackString(data, self.len_batch_bin)

        self.gltf_bin = self.unpackString(data, self.length - self.offset)

    def readHeader(self, data):
        self.magic = self.unpack('4s', data)
        self.version = self.unpack('<I', data)

        if self.magic != I3DM_MAGIC or self.version > I3DM_VERSION:
            raise IOError("Unrecognized magic %s or bad version %d" %
                          (self.magic, self.version))

        self.length = self.unpack('<I', data)
        self.len_feature_json = self.unpack('<I', data)
        self.len_feature_bin = self.unpack('<I', data)
        self.len_batch_json = self.unpack('<I', data)
        self.len_batch_bin = self.unpack('<I', data)
        self.embed_gltf = self.unpack('<I', data)

    def getGLTFBin(self):
        return self.gltf_bin

    def unpackString(self, data, length):
        self.offset += length
        return data[self.offset - length:self.offset]

    def unpack(self, fmt, data):
        calc_len = struct.calcsize(fmt)
        self.offset += calc_len
        return struct.unpack(fmt, data[self.offset - calc_len:self.offset])[0]
Ejemplo n.º 2
0
class B3DM:
    def __init__(self):
        self.batch_table = BatchTable()
        self.feature_table = FeatureTable()
        self.gltf_bin = bytearray()

    def loadJSONBatch(self, data_in, object_wise=True):
        self.batch_table.loadJSONBatch(data_in, object_wise)

    def loadJSONFeature(self, data_in, object_wise=True):
        self.feature_table.loadJSONBatch(data_in, object_wise)

    def writeBinary(self,
                    gltf_bin,
                    num_batch_features=0,
                    num_feature_features=0):

        # Add the required field BATCH_LENGTH to the feature table,
        # as well as any other required globals
        num_batch_features = max(num_batch_features,
                                 self.batch_table.getNumFeatures())
        self.feature_table.addGlobal('BATCH_LENGTH', num_batch_features)
        num_feature_features = max(num_feature_features,
                                   self.feature_table.getNumFeatures())

        self.batch_table.finalize()
        self.feature_table.finalize()

        # Generate the header
        output = self.writeHeader(gltf_bin, num_batch_features,
                                  num_feature_features)

        # Add the feature table JSON to the output
        feature_json = self.feature_table.getBatchJSON()
        output.extend(feature_json)

        # Add the batch table binary to the output
        feature_bin = self.feature_table.getBatchBin()
        output.extend(feature_bin)

        # Add the batch table JSON to the output
        batch_json = self.batch_table.getBatchJSON()
        output.extend(batch_json)

        # Add the batch table binary to the output
        batch_bin = self.batch_table.getBatchBin()
        output.extend(batch_bin)

        # Add the GLTF model body to the output
        output.extend(gltf_bin)

        return output

    def writeHeader(self, gltf_bin, num_feature_features, num_batch_features):
        len_feature_json = len(self.feature_table.getBatchJSON())
        len_feature_bin = len(self.feature_table.getBatchBin())
        len_batch_json = len(self.batch_table.getBatchJSON())
        len_batch_bin = len(self.batch_table.getBatchBin())

        length = B3DM_HEADER_LEN + \
                 len_feature_json + len_feature_bin + \
                 len_batch_json   + len_batch_bin + \
                 len(gltf_bin)

        output = bytearray()
        output.extend("b3dm")
        output.extend(struct.pack('<I', B3DM_VERSION))
        output.extend(struct.pack('<I', length))
        output.extend(struct.pack('<I', len_feature_json))
        output.extend(struct.pack('<I', len_feature_bin))
        output.extend(struct.pack('<I', len_batch_json))
        output.extend(struct.pack('<I', len_batch_bin))

        # Sanity check
        if (len(output) != B3DM_HEADER_LEN):
            raise ValueError("Incorrect b3dm header length")

        return output