Added support for packed float data

fix-456
Nehon 8 years ago committed by Rémy Bouquet
parent 01b48e0357
commit cac51f542a
  1. 51
      jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
  2. 130
      jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfUtils.java

@ -285,7 +285,8 @@ public class GltfLoader implements AssetLoader {
for (int i = 0; i < tmpArray.length; i++) { for (int i = 0; i < tmpArray.length; i++) {
tmpArray[i] = matrix.get(i).getAsFloat(); tmpArray[i] = matrix.get(i).getAsFloat();
} }
Matrix4f mat = toRowMajor(tmpArray); //creates a row major matrix from color major data
Matrix4f mat = new Matrix4f(tmpArray);
transform.fromTransformMatrix(mat); transform.fromTransformMatrix(mat);
return transform; return transform;
} }
@ -446,19 +447,18 @@ public class GltfLoader implements AssetLoader {
assertNotNull(type, "No type attribute defined for accessor " + accessorIndex); assertNotNull(type, "No type attribute defined for accessor " + accessorIndex);
boolean normalized = getAsBoolean(accessor, "normalized", false); boolean normalized = getAsBoolean(accessor, "normalized", false);
//Some float data can be packed into short buffers, "normalized" means they have to be unpacked.
//TODO support packed data //TODO support packed data
//TODO min / max //TODO min / max
//TODO sparse //TODO sparse
//TODO extensions?
//TODO extras? //TODO extras?
R data = populator.populate(bufferViewIndex, componentType, type, count, byteOffset); R data = populator.populate(bufferViewIndex, componentType, type, count, byteOffset, normalized);
data = customContentManager.readExtension(accessor, data); data = customContentManager.readExtension(accessor, data);
return data; return data;
} }
public void readBuffer(Integer bufferViewIndex, int byteOffset, int bufferSize, Object store, int numComponents, int componentSize) throws IOException { public void readBuffer(Integer bufferViewIndex, int byteOffset, int bufferSize, Object store, int numComponents, VertexBuffer.Format format) throws IOException {
JsonObject bufferView = bufferViews.get(bufferViewIndex).getAsJsonObject(); JsonObject bufferView = bufferViews.get(bufferViewIndex).getAsJsonObject();
Integer bufferIndex = getAsInteger(bufferView, "buffer"); Integer bufferIndex = getAsInteger(bufferView, "buffer");
@ -476,7 +476,7 @@ public class GltfLoader implements AssetLoader {
data = customContentManager.readExtension(bufferView, data); data = customContentManager.readExtension(bufferView, data);
populateBuffer(store, data, bufferSize, byteOffset + bvByteOffset, byteStride, numComponents, componentSize); populateBuffer(store, data, bufferSize, byteOffset + bvByteOffset, byteStride, numComponents, format);
//TODO extras? //TODO extras?
@ -1219,7 +1219,7 @@ public class GltfLoader implements AssetLoader {
} }
private interface Populator<T> { private interface Populator<T> {
T populate(Integer bufferViewIndex, int componentType, String type, int count, int byteOffset) throws IOException; T populate(Integer bufferViewIndex, int componentType, String type, int count, int byteOffset, boolean normalized) throws IOException;
} }
private class VertexBufferPopulator implements Populator<VertexBuffer> { private class VertexBufferPopulator implements Populator<VertexBuffer> {
@ -1230,15 +1230,22 @@ public class GltfLoader implements AssetLoader {
} }
@Override @Override
public VertexBuffer populate(Integer bufferViewIndex, int componentType, String type, int count, int byteOffset) throws IOException { public VertexBuffer populate(Integer bufferViewIndex, int componentType, String type, int count, int byteOffset, boolean normalized) throws IOException {
if (bufferType == null) { if (bufferType == null) {
logger.log(Level.WARNING, "could not assign data to any VertexBuffer type for buffer view " + bufferViewIndex); logger.log(Level.WARNING, "could not assign data to any VertexBuffer type for buffer view " + bufferViewIndex);
return null; return null;
} }
VertexBuffer vb = new VertexBuffer(bufferType); VertexBuffer vb = new VertexBuffer(bufferType);
VertexBuffer.Format format = getVertexBufferFormat(componentType); VertexBuffer.Format format = getVertexBufferFormat(componentType);
VertexBuffer.Format originalFormat = format;
if (normalized) {
//Some float data can be packed into short buffers, "normalized" means they have to be unpacked.
//In that case the buffer is a FloatBuffer
format = VertexBuffer.Format.Float;
}
int numComponents = getNumberOfComponents(type); int numComponents = getNumberOfComponents(type);
Buffer buff = VertexBuffer.createBuffer(format, numComponents, count); Buffer buff = VertexBuffer.createBuffer(format, numComponents, count);
@ -1247,7 +1254,7 @@ public class GltfLoader implements AssetLoader {
//no referenced buffer, specs says to pad the buffer with zeros. //no referenced buffer, specs says to pad the buffer with zeros.
padBuffer(buff, bufferSize); padBuffer(buff, bufferSize);
} else { } else {
readBuffer(bufferViewIndex, byteOffset, bufferSize, buff, numComponents, format.getComponentSize()); readBuffer(bufferViewIndex, byteOffset, bufferSize, buff, numComponents, originalFormat);
} }
if (bufferType == VertexBuffer.Type.Index) { if (bufferType == VertexBuffer.Type.Index) {
@ -1263,7 +1270,7 @@ public class GltfLoader implements AssetLoader {
private class FloatArrayPopulator implements Populator<float[]> { private class FloatArrayPopulator implements Populator<float[]> {
@Override @Override
public float[] populate(Integer bufferViewIndex, int componentType, String type, int count, int byteOffset) throws IOException { public float[] populate(Integer bufferViewIndex, int componentType, String type, int count, int byteOffset, boolean normalized) throws IOException {
int numComponents = getNumberOfComponents(type); int numComponents = getNumberOfComponents(type);
int dataSize = numComponents * count; int dataSize = numComponents * count;
@ -1273,7 +1280,7 @@ public class GltfLoader implements AssetLoader {
//no referenced buffer, specs says to pad the data with zeros. //no referenced buffer, specs says to pad the data with zeros.
padBuffer(data, dataSize); padBuffer(data, dataSize);
} else { } else {
readBuffer(bufferViewIndex, byteOffset, dataSize, data, numComponents, 4); readBuffer(bufferViewIndex, byteOffset, dataSize, data, numComponents, getVertexBufferFormat(componentType));
} }
return data; return data;
@ -1284,7 +1291,7 @@ public class GltfLoader implements AssetLoader {
private class Vector3fArrayPopulator implements Populator<Vector3f[]> { private class Vector3fArrayPopulator implements Populator<Vector3f[]> {
@Override @Override
public Vector3f[] populate(Integer bufferViewIndex, int componentType, String type, int count, int byteOffset) throws IOException { public Vector3f[] populate(Integer bufferViewIndex, int componentType, String type, int count, int byteOffset, boolean normalized) throws IOException {
int numComponents = getNumberOfComponents(type); int numComponents = getNumberOfComponents(type);
int dataSize = numComponents * count; int dataSize = numComponents * count;
@ -1294,7 +1301,7 @@ public class GltfLoader implements AssetLoader {
//no referenced buffer, specs says to pad the data with zeros. //no referenced buffer, specs says to pad the data with zeros.
padBuffer(data, dataSize); padBuffer(data, dataSize);
} else { } else {
readBuffer(bufferViewIndex, byteOffset, dataSize, data, numComponents, 4); readBuffer(bufferViewIndex, byteOffset, dataSize, data, numComponents, getVertexBufferFormat(componentType));
} }
return data; return data;
} }
@ -1303,7 +1310,7 @@ public class GltfLoader implements AssetLoader {
private class QuaternionArrayPopulator implements Populator<Quaternion[]> { private class QuaternionArrayPopulator implements Populator<Quaternion[]> {
@Override @Override
public Quaternion[] populate(Integer bufferViewIndex, int componentType, String type, int count, int byteOffset) throws IOException { public Quaternion[] populate(Integer bufferViewIndex, int componentType, String type, int count, int byteOffset, boolean normalized) throws IOException {
int numComponents = getNumberOfComponents(type); int numComponents = getNumberOfComponents(type);
int dataSize = numComponents * count; int dataSize = numComponents * count;
@ -1313,7 +1320,7 @@ public class GltfLoader implements AssetLoader {
//no referenced buffer, specs says to pad the data with zeros. //no referenced buffer, specs says to pad the data with zeros.
padBuffer(data, dataSize); padBuffer(data, dataSize);
} else { } else {
readBuffer(bufferViewIndex, byteOffset, dataSize, data, numComponents, 4); readBuffer(bufferViewIndex, byteOffset, dataSize, data, numComponents, getVertexBufferFormat(componentType));
} }
return data; return data;
@ -1323,7 +1330,7 @@ public class GltfLoader implements AssetLoader {
private class Matrix4fArrayPopulator implements Populator<Matrix4f[]> { private class Matrix4fArrayPopulator implements Populator<Matrix4f[]> {
@Override @Override
public Matrix4f[] populate(Integer bufferViewIndex, int componentType, String type, int count, int byteOffset) throws IOException { public Matrix4f[] populate(Integer bufferViewIndex, int componentType, String type, int count, int byteOffset, boolean normalized) throws IOException {
int numComponents = getNumberOfComponents(type); int numComponents = getNumberOfComponents(type);
int dataSize = numComponents * count; int dataSize = numComponents * count;
@ -1333,7 +1340,7 @@ public class GltfLoader implements AssetLoader {
//no referenced buffer, specs says to pad the data with zeros. //no referenced buffer, specs says to pad the data with zeros.
padBuffer(data, dataSize); padBuffer(data, dataSize);
} else { } else {
readBuffer(bufferViewIndex, byteOffset, dataSize, data, numComponents, 4); readBuffer(bufferViewIndex, byteOffset, dataSize, data, numComponents, getVertexBufferFormat(componentType));
} }
return data; return data;
@ -1343,14 +1350,14 @@ public class GltfLoader implements AssetLoader {
private class JointArrayPopulator implements Populator<SkinBuffers> { private class JointArrayPopulator implements Populator<SkinBuffers> {
@Override @Override
public SkinBuffers populate(Integer bufferViewIndex, int componentType, String type, int count, int byteOffset) throws IOException { public SkinBuffers populate(Integer bufferViewIndex, int componentType, String type, int count, int byteOffset, boolean normalized) throws IOException {
int numComponents = getNumberOfComponents(type); int numComponents = getNumberOfComponents(type);
//can be bytes or shorts. //can be bytes or shorts.
int componentSize = 1; VertexBuffer.Format format = VertexBuffer.Format.Byte;
if (componentType == 5123) { if (componentType == 5123) {
componentSize = 2; format = VertexBuffer.Format.Short;
} }
int dataSize = numComponents * count; int dataSize = numComponents * count;
@ -1360,10 +1367,10 @@ public class GltfLoader implements AssetLoader {
//no referenced buffer, specs says to pad the data with zeros. //no referenced buffer, specs says to pad the data with zeros.
padBuffer(data, dataSize); padBuffer(data, dataSize);
} else { } else {
readBuffer(bufferViewIndex, byteOffset, dataSize, data, numComponents, componentSize); readBuffer(bufferViewIndex, byteOffset, dataSize, data, numComponents, format);
} }
return new SkinBuffers(data, componentSize); return new SkinBuffers(data, format.getComponentSize());
} }
} }
} }

@ -237,42 +237,43 @@ public class GltfUtils {
} }
} }
public static void populateBuffer(Object store, byte[] source, int length, int byteOffset, int byteStride, int numComponents, int componentSize) throws IOException { public static void populateBuffer(Object store, byte[] source, int length, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
if (store instanceof Buffer) { if (store instanceof Buffer) {
Buffer buffer = (Buffer) store; Buffer buffer = (Buffer) store;
buffer.clear(); buffer.clear();
if (buffer instanceof ByteBuffer) { if (buffer instanceof ByteBuffer) {
populateByteBuffer((ByteBuffer) buffer, source, length, byteOffset, byteStride, numComponents, componentSize); populateByteBuffer((ByteBuffer) buffer, source, length, byteOffset, byteStride, numComponents, format);
return; return;
} }
LittleEndien stream = getStream(source); LittleEndien stream = getStream(source);
if (buffer instanceof ShortBuffer) { if (buffer instanceof ShortBuffer) {
populateShortBuffer((ShortBuffer) buffer, stream, length, byteOffset, byteStride, numComponents, componentSize); populateShortBuffer((ShortBuffer) buffer, stream, length, byteOffset, byteStride, numComponents, format);
} else if (buffer instanceof IntBuffer) { } else if (buffer instanceof IntBuffer) {
populateIntBuffer((IntBuffer) buffer, stream, length, byteOffset, byteStride, numComponents, componentSize); populateIntBuffer((IntBuffer) buffer, stream, length, byteOffset, byteStride, numComponents, format);
} else if (buffer instanceof FloatBuffer) { } else if (buffer instanceof FloatBuffer) {
populateFloatBuffer((FloatBuffer) buffer, stream, length, byteOffset, byteStride, numComponents, componentSize); populateFloatBuffer((FloatBuffer) buffer, stream, length, byteOffset, byteStride, numComponents, format);
} }
buffer.rewind(); buffer.rewind();
return; return;
} }
LittleEndien stream = getStream(source); LittleEndien stream = getStream(source);
if (store instanceof short[]) { if (store instanceof short[]) {
populateShortArray((short[]) store, stream, length, byteOffset, byteStride, numComponents, componentSize); populateShortArray((short[]) store, stream, length, byteOffset, byteStride, numComponents, format);
} else } else
if (store instanceof float[]) { if (store instanceof float[]) {
populateFloatArray((float[]) store, stream, length, byteOffset, byteStride, numComponents, componentSize); populateFloatArray((float[]) store, stream, length, byteOffset, byteStride, numComponents, format);
} else if (store instanceof Vector3f[]) { } else if (store instanceof Vector3f[]) {
populateVector3fArray((Vector3f[]) store, stream, length, byteOffset, byteStride, numComponents, componentSize); populateVector3fArray((Vector3f[]) store, stream, length, byteOffset, byteStride, numComponents, format);
} else if (store instanceof Quaternion[]) { } else if (store instanceof Quaternion[]) {
populateQuaternionArray((Quaternion[]) store, stream, length, byteOffset, byteStride, numComponents, componentSize); populateQuaternionArray((Quaternion[]) store, stream, length, byteOffset, byteStride, numComponents, format);
} else if (store instanceof Matrix4f[]) { } else if (store instanceof Matrix4f[]) {
populateMatrix4fArray((Matrix4f[]) store, stream, length, byteOffset, byteStride, numComponents, componentSize); populateMatrix4fArray((Matrix4f[]) store, stream, length, byteOffset, byteStride, numComponents, format);
} }
} }
private static void populateByteBuffer(ByteBuffer buffer, byte[] source, int length, int byteOffset, int byteStride, int numComponents, int componentSize) { private static void populateByteBuffer(ByteBuffer buffer, byte[] source, int length, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) {
int componentSize = format.getComponentSize();
int index = byteOffset; int index = byteOffset;
while (index < length + byteOffset) { while (index < length + byteOffset) {
for (int i = 0; i < numComponents; i++) { for (int i = 0; i < numComponents; i++) {
@ -282,7 +283,8 @@ public class GltfUtils {
} }
} }
private static void populateShortBuffer(ShortBuffer buffer, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, int componentSize) throws IOException { private static void populateShortBuffer(ShortBuffer buffer, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
int componentSize = format.getComponentSize();
int index = byteOffset; int index = byteOffset;
int end = length * componentSize + byteOffset; int end = length * componentSize + byteOffset;
stream.skipBytes(byteOffset); stream.skipBytes(byteOffset);
@ -294,7 +296,8 @@ public class GltfUtils {
} }
} }
private static void populateIntBuffer(IntBuffer buffer, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, int componentSize) throws IOException { private static void populateIntBuffer(IntBuffer buffer, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
int componentSize = format.getComponentSize();
int index = byteOffset; int index = byteOffset;
int end = length * componentSize + byteOffset; int end = length * componentSize + byteOffset;
stream.skipBytes(byteOffset); stream.skipBytes(byteOffset);
@ -306,19 +309,50 @@ public class GltfUtils {
} }
} }
private static void populateFloatBuffer(FloatBuffer buffer, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, int componentSize) throws IOException { private static void populateFloatBuffer(FloatBuffer buffer, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
int componentSize = format.getComponentSize();
int index = byteOffset; int index = byteOffset;
int end = length * componentSize + byteOffset; int end = length * componentSize + byteOffset;
stream.skipBytes(byteOffset); stream.skipBytes(byteOffset);
while (index < end) { while (index < end) {
for (int i = 0; i < numComponents; i++) { for (int i = 0; i < numComponents; i++) {
buffer.put(stream.readFloat()); buffer.put(readAsFloat(stream, format));
} }
index += Math.max(componentSize * numComponents, byteStride); index += Math.max(componentSize * numComponents, byteStride);
} }
} }
private static void populateShortArray(short[] array, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, int componentSize) throws IOException { private static float readAsFloat(LittleEndien stream, VertexBuffer.Format format) throws IOException {
//We may have packed data so depending on the format, we need to read data differently and unpack it
// Implementations must use following equations to get corresponding floating-point value f from a normalized integer c and vise-versa:
// accessor.componentType int-to-float float-to-int
// 5120 (BYTE) f = max(c / 127.0, -1.0) c = round(f * 127.0)
// 5121 (UNSIGNED_BYTE) f = c / 255.0 c = round(f * 255.0)
// 5122 (SHORT) f = max(c / 32767.0, -1.0) c = round(f * 32767.0)
// 5123 (UNSIGNED_SHORT) f = c / 65535.0 c = round(f * 65535.0)
byte b;
switch (format) {
case Byte:
b = stream.readByte();
return Math.max((float) b / 127f, -1f);
case UnsignedByte:
b = stream.readByte();
return (float) b / 255f;
case Short:
b = stream.readByte();
return Math.max((float) b / 32767f, -1f);
case UnsignedShort:
b = stream.readByte();
return (float) b / 65535f;
default:
//we have a regular float
return stream.readFloat();
}
}
private static void populateShortArray(short[] array, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
int componentSize = format.getComponentSize();
int index = byteOffset; int index = byteOffset;
int end = length * componentSize + byteOffset; int end = length * componentSize + byteOffset;
stream.skipBytes(byteOffset); stream.skipBytes(byteOffset);
@ -404,14 +438,15 @@ public class GltfUtils {
mesh.setBuffer(VertexBuffer.Type.BoneWeight, 4, BufferUtils.createFloatBuffer(weightsArray)); mesh.setBuffer(VertexBuffer.Type.BoneWeight, 4, BufferUtils.createFloatBuffer(weightsArray));
} }
private static void populateFloatArray(float[] array, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, int componentSize) throws IOException { private static void populateFloatArray(float[] array, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
int componentSize = format.getComponentSize();
int index = byteOffset; int index = byteOffset;
int end = length * componentSize + byteOffset; int end = length * componentSize + byteOffset;
stream.skipBytes(byteOffset); stream.skipBytes(byteOffset);
int arrayIndex = 0; int arrayIndex = 0;
while (index < end) { while (index < end) {
for (int i = 0; i < numComponents; i++) { for (int i = 0; i < numComponents; i++) {
array[arrayIndex] = stream.readFloat(); array[arrayIndex] = readAsFloat(stream, format);
arrayIndex++; arrayIndex++;
} }
@ -419,16 +454,17 @@ public class GltfUtils {
} }
} }
private static void populateVector3fArray(Vector3f[] array, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, int componentSize) throws IOException { private static void populateVector3fArray(Vector3f[] array, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
int componentSize = format.getComponentSize();
int index = byteOffset; int index = byteOffset;
int end = length * componentSize + byteOffset; int end = length * componentSize + byteOffset;
stream.skipBytes(byteOffset); stream.skipBytes(byteOffset);
int arrayIndex = 0; int arrayIndex = 0;
while (index < end) { while (index < end) {
array[arrayIndex] = new Vector3f( array[arrayIndex] = new Vector3f(
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat() readAsFloat(stream, format)
); );
arrayIndex++; arrayIndex++;
@ -437,17 +473,18 @@ public class GltfUtils {
} }
} }
private static void populateQuaternionArray(Quaternion[] array, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, int componentSize) throws IOException { private static void populateQuaternionArray(Quaternion[] array, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
int componentSize = format.getComponentSize();
int index = byteOffset; int index = byteOffset;
int end = length * componentSize + byteOffset; int end = length * componentSize + byteOffset;
stream.skipBytes(byteOffset); stream.skipBytes(byteOffset);
int arrayIndex = 0; int arrayIndex = 0;
while (index < end) { while (index < end) {
array[arrayIndex] = new Quaternion( array[arrayIndex] = new Quaternion(
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat() readAsFloat(stream, format)
); );
arrayIndex++; arrayIndex++;
@ -456,7 +493,8 @@ public class GltfUtils {
} }
} }
private static void populateMatrix4fArray(Matrix4f[] array, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, int componentSize) throws IOException { private static void populateMatrix4fArray(Matrix4f[] array, LittleEndien stream, int length, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
int componentSize = format.getComponentSize();
int index = byteOffset; int index = byteOffset;
int end = length * componentSize + byteOffset; int end = length * componentSize + byteOffset;
stream.skipBytes(byteOffset); stream.skipBytes(byteOffset);
@ -464,22 +502,22 @@ public class GltfUtils {
while (index < end) { while (index < end) {
array[arrayIndex] = toRowMajor( array[arrayIndex] = toRowMajor(
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat(), readAsFloat(stream, format),
stream.readFloat() readAsFloat(stream, format)
); );
//gltf matrix are column major, JME ones are row major. //gltf matrix are column major, JME ones are row major.
@ -496,10 +534,6 @@ public class GltfUtils {
return new Matrix4f(m00, m10, m20, m30, m01, m11, m21, m31, m02, m12, m22, m32, m03, m13, m23, m33); return new Matrix4f(m00, m10, m20, m30, m01, m11, m21, m31, m02, m12, m22, m32, m03, m13, m23, m33);
} }
public static Matrix4f toRowMajor(float[] a) {
return new Matrix4f(a[0], a[4], a[8], a[12], a[1], a[5], a[9], a[13], a[2], a[5], a[10], a[14], a[3], a[7], a[11], a[15]);
}
public static GltfModelKey getKey(AssetInfo info) { public static GltfModelKey getKey(AssetInfo info) {
if (info.getKey() instanceof GltfModelKey) { if (info.getKey() instanceof GltfModelKey) {
return (GltfModelKey) info.getKey(); return (GltfModelKey) info.getKey();

Loading…
Cancel
Save