java gltf转glb(小模型)

先介绍gltf的结构 创建java类

 private Assets assets;
 private Scene scene;
 private ScenesList scenes;
 private NodeListF node;
 private MaterialsF materials;
 private MeshesF meshes;
 private AccessorsF accessorsF;
 private BufferViewsF bufferViewsF;
 private BuffersF buffersF;

每一个类再创造小类

1.Accessor

    private int bufferView;
    private int componentType;
    private int count;
    private List<Double> max;
    private List<Double> min;
    private String type;

2.Buff

    private Integer byteLength;
    private String uri;

3.BufferViews

   private int buffer;
    private int byteLength;
    private int byteOffset;
    private int target;

4.Material

  private boolean doubleSided;
    private String name;
    private PbrMetallicRoughness pbrMetallicRoughness;

5.Mesh

    private String name;
    private List<Primitive> primitives;

6.Node

   private int mesh;
    private String name;

7.Scenes

    private String name;
    private  NodeList nodes;

主函数 

    private static byte[] convertGltfToGlb(String gltfString,Gltf gltf) throws IOException {
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

    // 解析GLTF字符串为JSON对象
    JSONObject gltfJson = new JSONObject(gltfString);

    // 提取所有的Buffers
    JSONArray buffersArray = gltfJson.getJSONArray("buffers");
    ByteArrayOutputStream combinedBufferStream = new ByteArrayOutputStream();

    for (int i = 0; i < buffersArray.length(); i++) {
        JSONObject bufferObj = buffersArray.getJSONObject(i);
        String base64Buffer = bufferObj.getString("uri");
        byte[] buffer = Base64.getDecoder().decode(base64Buffer.split(",")[1]);
        combinedBufferStream.write(buffer);
        bufferObj.remove("uri");
    }
    String str=gltf.toStringWithoutUri();
    byte[] combinedBuffer = combinedBufferStream.toByteArray();
    byte[] jsonBytes = gltf.toStringWithoutUri().getBytes(StandardCharsets.UTF_8);

    // 写入GLB头部
    outputStream.write("glTF".getBytes(StandardCharsets.UTF_8)); // Magic
    outputStream.write(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(2).array()); // Version

    // 占位符,稍后回填总长度
    outputStream.write(new byte[4]);

    // 写入JSON块长度和类型
    int jsonLength = jsonBytes.length;
    int jsonPadding = (4 - (jsonLength % 4)) % 4;
    outputStream.write(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(jsonLength + jsonPadding ).array());
    outputStream.write(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(0x4E4F534A).array()); // JSON块类型
    outputStream.write(jsonBytes);

    // 对齐到4字节
    for (int i = 0; i < jsonPadding; i++) {
        outputStream.write(0x20); // 使用空格进行填充
    }

    // 写入二进制块长度和类型
    int binLength = combinedBuffer.length;
    int binPadding = (4 - (binLength % 4)) % 4;
    outputStream.write(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(binLength + binPadding ).array());
    outputStream.write(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(0x004E4942).array()); // 二进制块类型
    outputStream.write(combinedBuffer);

    // 对齐到4字节
    for (int i = 0; i < binPadding; i++) {
        outputStream.write(0); // 使用0进行填充
    }

    // 回填总长度
    byte[] glbBytes = outputStream.toByteArray();
    ByteBuffer.wrap(glbBytes, 8, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(glbBytes.length);
    return glbBytes;
}

注意字节对齐其实很简单,可以先去了解下gltf和glb的格式标准,转换后的可以用glTF Viewer来检测是否成功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值