Skip to content

Commit

Permalink
Don't need asset loaders.
Browse files Browse the repository at this point in the history
  • Loading branch information
GlennFolker committed Mar 30, 2024
1 parent 6e2ce33 commit 687d5e2
Show file tree
Hide file tree
Showing 3 changed files with 283 additions and 249 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
projectVersion = v146.0.0
entVersion = v146.0.2
entVersion = v146.0.3
arcVersion = v146
javapoetVersion = 1.13.0

Expand Down
255 changes: 7 additions & 248 deletions src/gltfrenzy/loader/Scenes3DLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,32 @@
import arc.assets.loaders.*;
import arc.files.*;
import arc.graphics.*;
import arc.graphics.Mesh;
import arc.struct.*;
import arc.util.*;
import gltfrenzy.data.*;
import gltfrenzy.loader.Scenes3DLoader.*;
import gltfrenzy.loader.Scenes3DLoader.MeshContainerQueue.*;
import gltfrenzy.loader.Scenes3DReader.*;
import gltfrenzy.model.*;
import gltfrenzy.model.MeshSet.*;
import gltfrenzy.model.Node;

import java.io.*;
import java.net.*;
import java.nio.*;
import java.util.*;

/**
* Asynchronous asset loader implementation to load {@link Scenes3D} assets from either {@code .gltf} or {@code .glb} files.
* @author GlennFolker
*/
public class Scenes3DLoader extends AsynchronousAssetLoader<Scenes3D, Scenes3DParameter>{
public class Scenes3DLoader extends AsynchronousAssetLoader<Scenes3D, Scenes3DParameter> implements FileHandleResolver{
protected final Scenes3DReader reader;
protected Scenes3D asset;
protected MeshContainerQueue[] meshes;
protected int[] nodeMeshes;
protected Runnable sync;

public Scenes3DLoader(FileHandleResolver resolver, Scenes3DReader reader){
super(resolver);
this.reader = reader;
}

@Override
public void loadAsync(AssetManager manager, String fileName, Fi file, Scenes3DParameter parameter){
public void loadAsync(AssetManager manager, String fileName, Fi file, @Nullable Scenes3DParameter parameter){
if(parameter == null) parameter = new Scenes3DParameter();
asset = parameter.asset != null ? parameter.asset : new Scenes3D();
asset = parameter.asset != null ? parameter.asset : (parameter.asset = new Scenes3D());

Scenes3DData data;
try{
Expand All @@ -47,237 +38,16 @@ public void loadAsync(AssetManager manager, String fileName, Fi file, Scenes3DPa
throw new RuntimeException(e);
}

var spec = data.spec;
var buffers = data.buffers;

for(int i = 0; i < spec.buffers.length; i++){
var buffer = spec.buffers[i];

var uri = URI.create(buffer.uri);
var scheme = uri.getScheme();
if(scheme == null){
var bufFile = resolve(file.parent().child(buffer.uri).path());
var output = buffers[i] = ByteBuffer.wrap(bufFile.readBytes());
output.order(ByteOrder.LITTLE_ENDIAN);
}else{
//TODO Base-64 buffers.
}
}

var bufferViews = new ByteBuffer[spec.bufferViews.length];
for(int i = 0; i < bufferViews.length; i++){
var view = spec.bufferViews[i];

var buffer = buffers[view.buffer];
buffer.limit(view.byteOffset + view.byteLength);
buffer.position(view.byteOffset);

bufferViews[i] = buffer.slice();
bufferViews[i].order(ByteOrder.LITTLE_ENDIAN);
buffer.clear();
}

// TODO Handle morph targets.
meshes = new MeshContainerQueue[spec.meshes.length];
for(int i = 0; i < meshes.length; i++){
var mesh = spec.meshes[i];
var cont = meshes[i] = new MeshContainerQueue();
cont.name = mesh.name;

cont.containers = new MeshQueue[mesh.primitives.length];
for(int m = 0; m < mesh.primitives.length; m++){
var primitives = mesh.primitives[m];
var attrs = primitives.attributes;

int verticesLen = 0, verticesCount = -1;
Seq<VertexAttribute> attributes = new Seq<>(true, attrs.size, VertexAttribute.class);

for(int j = 0; j < attrs.size; j++){
var alias = attrs.getKeyAt(j);
alias = parameter.attributeAlias.get(alias, alias);
if(mesh.name != null && parameter.skipAttribute.get(mesh.name, ObjectSet::new).contains(alias)){
attributes.add((VertexAttribute)null);
continue;
}

var accessor = spec.accessors[attrs.getValueAt(j).asInt()];
if(verticesCount != -1 && accessor.count != verticesCount){
throw new IllegalArgumentException("Vertices count mismatch, found accessor with count " + accessor.count + " instead of " + verticesCount);
}else{
verticesCount = accessor.count;
}

var attr = new VertexAttribute(switch(accessor.type){
case scalar -> 1;
case vec2 -> 2;
case vec3 -> 3;
case vec4, mat2 -> 4;
case mat3 -> 9;
case mat4 -> 16;
}, accessor.componentType, accessor.normalized, alias);
verticesLen += verticesCount * attr.size;

attributes.add(attr);
}

var vertexBuffer = Buffers.newUnsafeByteBuffer(verticesLen);
vertexBuffer.order(ByteOrder.LITTLE_ENDIAN);
for(int j = 0; j < verticesCount; j++){
for(int k = 0; k < attrs.size; k++){
var attr = attributes.get(k);
if(attr == null) continue;

var accessor = spec.accessors[attrs.getValueAt(k).asInt()];
if(accessor.bufferView == -1){
// TODO Handle sparse accessors.
vertexBuffer.put(new byte[attr.size]);
}else{
var view = bufferViews[accessor.bufferView];
view.clear();
view.limit(accessor.byteOffset + (j + 1) * attr.size);
view.position(accessor.byteOffset + j * attr.size);
vertexBuffer.put(view);
}
}
}

int indicesCount = 0;
ByteBuffer indexBuffer = null;
if(primitives.indices != -1){
var accessor = spec.accessors[primitives.indices];
if(accessor.type != AccessorType.scalar) throw new IllegalArgumentException("Indices accessor must be scalar.");

indexBuffer = Buffers.newUnsafeByteBuffer((indicesCount = accessor.count) * Short.BYTES);
indexBuffer.order(ByteOrder.LITTLE_ENDIAN);
if(accessor.bufferView == -1){
indexBuffer.put(new byte[indicesCount * Short.BYTES]);
}else{
var view = bufferViews[accessor.bufferView];
switch(accessor.componentType){
case Gl.byteV, Gl.unsignedByte -> {
byte[] indices = new byte[indicesCount];
view.clear();
view.limit(accessor.byteOffset + indicesCount * Byte.BYTES);
view.position(accessor.byteOffset);
view.get(indices);

var dst = indexBuffer.asShortBuffer();
for(byte index : indices) dst.put(index);
}
case Gl.shortV, Gl.unsignedShort -> {
view.clear();
view.limit(accessor.byteOffset + indicesCount * Short.BYTES);
view.position(accessor.byteOffset);

indexBuffer.asShortBuffer().put(view.asShortBuffer());
}
case Gl.unsignedInt -> {
int[] indices = new int[indicesCount];
view.clear();
view.limit(accessor.byteOffset + indicesCount * Integer.BYTES);
view.position(accessor.byteOffset);
view.asIntBuffer().get(indices);

var dst = indexBuffer.asShortBuffer();
for(int index : indices) dst.put((short)index);
}
default -> throw new IllegalArgumentException("Indices accessor component type must be integer.");
}
}
}

var queue = cont.containers[m] = new MeshQueue();
queue.vertices = vertexBuffer;
queue.vertices.clear();
queue.maxVertices = verticesCount;

queue.indices = indexBuffer;
queue.indices.clear();
queue.maxIndices = indicesCount;

queue.attributes = attributes.retainAll(Objects::nonNull).toArray();
queue.mode = primitives.mode;
}
}

// TODO Handle skin and bone weights.
nodeMeshes = new int[spec.nodes.length];
for(int i = 0; i < spec.nodes.length; i++){
var out = new Node();
var node = spec.nodes[i];

out.name = node.name;
nodeMeshes[i] = node.mesh;

if(node.matrix == null){
out.localTrns.translation.set(node.translation);
out.localTrns.rotation.set(node.rotation);
out.localTrns.scale.set(node.scale);
}else{
node.matrix.getTranslation(out.localTrns.translation);
node.matrix.getRotation(out.localTrns.rotation);
node.matrix.getScale(out.localTrns.scale);
}

asset.nodes.add(out);
if(!out.name.isEmpty()) asset.nodeNames.put(out.name, out);
}

for(int i = 0; i < asset.nodes.size; i++){
var node = asset.nodes.get(i);
for(int child : spec.nodes[i].children){
var c = asset.nodes.get(child);
c.parent = node;
node.children.add(c);
}
}

asset.nodes.each(Node::update);
sync = asset.load(file, data, this, parameter);
}

@Override
public Scenes3D loadSync(AssetManager manager, String fileName, Fi file, Scenes3DParameter parameter){
var out = asset;
for(var cont : meshes){
var set = new MeshSet();
set.name = cont.name;

for(var queue : cont.containers){
var mesh = new Mesh(true, queue.maxVertices, queue.maxIndices, queue.attributes);
{
FloatBuffer src = queue.vertices.asFloatBuffer(), dst = mesh.getVerticesBuffer();
src.clear();
dst.clear();

dst.put(src);
dst.clear();
}

{
ShortBuffer src = queue.indices.asShortBuffer(), dst = mesh.getIndicesBuffer();
src.clear();
dst.clear();

dst.put(src);
dst.clear();
}

Buffers.disposeUnsafeByteBuffer(queue.vertices);
Buffers.disposeUnsafeByteBuffer(queue.indices);
set.containers.add(new MeshContainer(mesh, queue.mode));
}

out.meshes.add(set);
if(!set.name.isEmpty()) out.meshNames.put(set.name, set);
}

for(int i = 0; i < nodeMeshes.length; i++){
out.nodes.get(i).mesh = out.meshes.get(i);
}
sync.run();

asset = null;
meshes = null;
nodeMeshes = null;
sync = null;
return out;
}

Expand Down Expand Up @@ -315,15 +85,4 @@ public Scenes3DParameter skip(String mesh, String attribute){
return this;
}
}

protected static class MeshContainerQueue{
public String name;
public MeshQueue[] containers;

public static class MeshQueue{
public ByteBuffer vertices, indices;
public VertexAttribute[] attributes;
public int maxVertices, maxIndices, mode;
}
}
}
Loading

0 comments on commit 687d5e2

Please sign in to comment.