Ejemplo n.º 1
0
def encode_scene_primitives(scenes, export_settings):
    """
    Handles draco compression.
    Moves position, normal and texture coordinate attributes into a Draco encoded buffer.
    """

    # Load DLL and setup function signatures.
    dll = cdll.LoadLibrary(str(dll_path().resolve()))

    dll.encoderCreate.restype = c_void_p
    dll.encoderCreate.argtypes = [c_uint32]

    dll.encoderRelease.restype = None
    dll.encoderRelease.argtypes = [c_void_p]

    dll.encoderSetCompressionLevel.restype = None
    dll.encoderSetCompressionLevel.argtypes = [c_void_p, c_uint32]

    dll.encoderSetQuantizationBits.restype = None
    dll.encoderSetQuantizationBits.argtypes = [c_void_p, c_uint32, c_uint32, c_uint32, c_uint32, c_uint32]

    dll.encoderSetIndices.restype = None
    dll.encoderSetIndices.argtypes = [c_void_p, c_size_t, c_uint32, c_void_p]

    dll.encoderSetAttribute.restype = c_uint32
    dll.encoderSetAttribute.argtypes = [c_void_p, c_char_p, c_size_t, c_char_p, c_void_p]

    dll.encoderEncode.restype = c_bool
    dll.encoderEncode.argtypes = [c_void_p, c_uint8]

    dll.encoderGetEncodedVertexCount.restype = c_uint32
    dll.encoderGetEncodedVertexCount.argtypes = [c_void_p]

    dll.encoderGetEncodedIndexCount.restype = c_uint32
    dll.encoderGetEncodedIndexCount.argtypes = [c_void_p]

    dll.encoderGetByteLength.restype = c_uint64
    dll.encoderGetByteLength.argtypes = [c_void_p]

    dll.encoderCopy.restype = None
    dll.encoderCopy.argtypes = [c_void_p, c_void_p]

    # Don't encode the same primitive multiple times.
    encoded_primitives_cache = {}

    # Compress meshes into Draco buffers.
    for scene in scenes:
        for node in scene.nodes:
            __traverse_node(node, lambda node: __encode_node(node, dll, export_settings, encoded_primitives_cache))

    # Release uncompressed index and attribute buffers.
    # Since those buffers may be shared across nodes, this step must happen after all meshes have been compressed.
    for scene in scenes:
        for node in scene.nodes:
            __traverse_node(node, lambda node: __cleanup_node(node))
def encode_scene_primitives(scenes, export_settings):
    """
    Handles draco compression.
    Moves position, normal and texture coordinate attributes into a Draco encoded buffer.
    """

    # Load DLL and setup function signatures.
    dll = cdll.LoadLibrary(str(dll_path().resolve()))

    dll.encoderCreate.restype = c_void_p
    dll.encoderCreate.argtypes = [c_uint32]

    dll.encoderRelease.restype = None
    dll.encoderRelease.argtypes = [c_void_p]

    dll.encoderSetCompressionLevel.restype = None
    dll.encoderSetCompressionLevel.argtypes = [c_void_p, c_uint32]

    dll.encoderSetQuantizationBits.restype = None
    dll.encoderSetQuantizationBits.argtypes = [
        c_void_p, c_uint32, c_uint32, c_uint32, c_uint32, c_uint32
    ]

    dll.encoderSetIndices.restype = None
    dll.encoderSetIndices.argtypes = [c_void_p, c_size_t, c_uint32, c_void_p]

    dll.encoderSetAttribute.restype = c_uint32
    dll.encoderSetAttribute.argtypes = [
        c_void_p, c_char_p, c_size_t, c_char_p, c_void_p
    ]

    dll.encoderEncode.restype = c_bool
    dll.encoderEncode.argtypes = [c_void_p, c_uint8]

    dll.encoderGetEncodedVertexCount.restype = c_uint32
    dll.encoderGetEncodedVertexCount.argtypes = [c_void_p]

    dll.encoderGetEncodedIndexCount.restype = c_uint32
    dll.encoderGetEncodedIndexCount.argtypes = [c_void_p]

    dll.encoderGetByteLength.restype = c_uint64
    dll.encoderGetByteLength.argtypes = [c_void_p]

    dll.encoderCopy.restype = None
    dll.encoderCopy.argtypes = [c_void_p, c_void_p]

    for scene in scenes:
        for node in scene.nodes:
            __traverse_node(
                node, lambda node: __encode_node(node, dll, export_settings))
Ejemplo n.º 3
0
def decode_primitive(gltf, prim):
    """
    Handles draco compression.
    Moves decoded data into new buffers and buffer views held by the accessors of the given primitive.
    """

    # Load DLL and setup function signatures.
    dll = cdll.LoadLibrary(str(dll_path().resolve()))

    dll.decoderCreate.restype = c_void_p
    dll.decoderCreate.argtypes = []

    dll.decoderRelease.restype = None
    dll.decoderRelease.argtypes = [c_void_p]

    dll.decoderDecode.restype = c_bool
    dll.decoderDecode.argtypes = [c_void_p, c_void_p, c_size_t]

    dll.decoderReadAttribute.restype = c_bool
    dll.decoderReadAttribute.argtypes = [c_void_p, c_uint32, c_size_t, c_char_p]

    dll.decoderGetVertexCount.restype = c_uint32
    dll.decoderGetVertexCount.argtypes = [c_void_p]

    dll.decoderGetIndexCount.restype = c_uint32
    dll.decoderGetIndexCount.argtypes = [c_void_p]

    dll.decoderAttributeIsNormalized.restype = c_bool
    dll.decoderAttributeIsNormalized.argtypes = [c_void_p, c_uint32]

    dll.decoderGetAttributeByteLength.restype = c_size_t
    dll.decoderGetAttributeByteLength.argtypes = [c_void_p, c_uint32]

    dll.decoderCopyAttribute.restype = None
    dll.decoderCopyAttribute.argtypes = [c_void_p, c_uint32, c_void_p]

    dll.decoderReadIndices.restype = c_bool
    dll.decoderReadIndices.argtypes = [c_void_p, c_size_t]

    dll.decoderGetIndicesByteLength.restype = c_size_t
    dll.decoderGetIndicesByteLength.argtypes = [c_void_p]

    dll.decoderCopyIndices.restype = None
    dll.decoderCopyIndices.argtypes = [c_void_p, c_void_p]

    decoder = dll.decoderCreate()
    extension = prim.extensions['KHR_draco_mesh_compression']

    name = prim.name if hasattr(prim, 'name') else '[unnamed]'

    # Create Draco decoder.
    draco_buffer = bytes(BinaryData.get_buffer_view(gltf, extension['bufferView']))
    if not dll.decoderDecode(decoder, draco_buffer, len(draco_buffer)):
        print_console('ERROR', 'Draco Decoder: Unable to decode. Skipping primitive {}.'.format(name))
        return

    # Choose a buffer index which does not yet exist, skipping over existing glTF buffers yet to be loaded
    # and buffers which were generated and did not exist in the initial glTF file, like this decoder does.
    base_buffer_idx = len(gltf.data.buffers)
    for existing_buffer_idx in gltf.buffers:
        if base_buffer_idx <= existing_buffer_idx:
            base_buffer_idx = existing_buffer_idx + 1

    # Read indices.
    index_accessor = gltf.data.accessors[prim.indices]
    if dll.decoderGetIndexCount(decoder) != index_accessor.count:
        print_console('WARNING', 'Draco Decoder: Index count of accessor and decoded index count does not match. Updating accessor.')
        index_accessor.count = dll.decoderGetIndexCount(decoder)
    if not dll.decoderReadIndices(decoder, index_accessor.component_type):
        print_console('ERROR', 'Draco Decoder: Unable to decode indices. Skipping primitive {}.'.format(name))
        return

    indices_byte_length = dll.decoderGetIndicesByteLength(decoder)
    decoded_data = bytes(indices_byte_length)
    dll.decoderCopyIndices(decoder, decoded_data)

    # Generate a new buffer holding the decoded indices.
    gltf.buffers[base_buffer_idx] = decoded_data

    # Create a buffer view referencing the new buffer.
    gltf.data.buffer_views.append(BufferView.from_dict({
        'buffer': base_buffer_idx,
        'byteLength': indices_byte_length
    }))

    # Update accessor to point to the new buffer view.
    index_accessor.buffer_view = len(gltf.data.buffer_views) - 1

    # Read each attribute.
    for attr_idx, attr in enumerate(extension['attributes']):
        dracoId = extension['attributes'][attr]
        if attr not in prim.attributes:
            print_console('ERROR', 'Draco Decoder: Draco attribute {} not in primitive attributes. Skipping primitive {}.'.format(attr, name))
            return

        accessor = gltf.data.accessors[prim.attributes[attr]]
        if dll.decoderGetVertexCount(decoder) != accessor.count:
            print_console('WARNING', 'Draco Decoder: Vertex count of accessor and decoded vertex count does not match for attribute {}. Updating accessor.'.format(attr, name))
            accessor.count = dll.decoderGetVertexCount(decoder)
        if not dll.decoderReadAttribute(decoder, dracoId, accessor.component_type, accessor.type.encode()):
            print_console('ERROR', 'Draco Decoder: Could not decode attribute {}. Skipping primitive {}.'.format(attr, name))
            return

        byte_length = dll.decoderGetAttributeByteLength(decoder, dracoId)
        decoded_data = bytes(byte_length)
        dll.decoderCopyAttribute(decoder, dracoId, decoded_data)

        # Generate a new buffer holding the decoded vertex data.
        buffer_idx = base_buffer_idx + 1 + attr_idx
        gltf.buffers[buffer_idx] = decoded_data

        # Create a buffer view referencing the new buffer.
        gltf.data.buffer_views.append(BufferView.from_dict({
            'buffer': buffer_idx,
            'byteLength': byte_length
        }))

        # Update accessor to point to the new buffer view.
        accessor.buffer_view = len(gltf.data.buffer_views) - 1

    dll.decoderRelease(decoder)