Просмотр исходного кода

Revert "Merge pull request #2553 from riccardobl/gltfimp"

This reverts commit 169f395055d07387afedc536f9aacfa6186bf7c1, reversing
changes made to fab757bc6e5be28b3fad98082426520ca772ba28.
Riccardo Balbo 2 дней назад
Родитель
Сommit
084deaeb8d

+ 0 - 72
jme3-core/src/main/java/com/jme3/util/BufferInputStream.java

@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2009-2025 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-
-public class BufferInputStream extends InputStream {
-
-    ByteBuffer input;
-
-    public BufferInputStream(ByteBuffer input) {
-        this.input = input;
-    }
-
-    @Override
-    public int read() throws IOException {
-        if (input.remaining() == 0) return -1; else return input.get() & 0xff;
-    }
-
-    @Override
-    public int read(byte[] b) {
-        return read(b, 0, b.length);
-    }
-
-    @Override
-    public int read(byte[] b, int off, int len) {
-        if (b == null) throw new NullPointerException("b == null");
-        if (off < 0 || len < 0 || len > b.length - off) throw new IndexOutOfBoundsException();
-        if (len == 0) return 0;
-        if (!input.hasRemaining()) return -1;
-
-        int toRead = Math.min(len, input.remaining());
-        input.get(b, off, toRead);
-        return toRead;
-    }
-
-    @Override
-    public int available() {
-        return input.remaining();
-    }
-}

+ 2 - 13
jme3-examples/src/main/java/jme3test/model/TestGltfLoading.java

@@ -31,11 +31,11 @@
  */
 package jme3test.model;
 
+import com.jme3.anim.AnimClip;
 import com.jme3.anim.AnimComposer;
 import com.jme3.anim.SkinningControl;
 import com.jme3.app.*;
 import com.jme3.asset.plugins.FileLocator;
-import com.jme3.asset.plugins.UrlLocator;
 import com.jme3.input.KeyInput;
 import com.jme3.input.controls.ActionListener;
 import com.jme3.input.controls.KeyTrigger;
@@ -82,7 +82,6 @@ public class TestGltfLoading extends SimpleApplication {
 
         String folder = System.getProperty("user.home");
         assetManager.registerLocator(folder, FileLocator.class);
-        assetManager.registerLocator("https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/refs/heads/main/", UrlLocator.class);
 
         // cam.setLocation(new Vector3f(4.0339394f, 2.645184f, 6.4627485f));
         // cam.setRotation(new Quaternion(-0.013950467f, 0.98604023f, -0.119502485f, -0.11510504f));
@@ -153,14 +152,7 @@ public class TestGltfLoading extends SimpleApplication {
 
 //        loadModel("Models/gltf/Corset/glTF/Corset.gltf", new Vector3f(0, -1, 0), 20f);
 //        loadModel("Models/gltf/BoxInterleaved/glTF/BoxInterleaved.gltf", new Vector3f(0, 0, 0), 1f);
-
-        // From url locator
-
-        // loadModel("Models/AnimatedColorsCube/glTF/AnimatedColorsCube.gltf", new Vector3f(0, 0f, 0), 0.1f);
-        // loadModel("Models/AntiqueCamera/glTF/AntiqueCamera.gltf", new Vector3f(0, 0, 0), 0.1f);
-        // loadModel("Models/AnimatedMorphCube/glTF/AnimatedMorphCube.gltf", new Vector3f(0, 0, 0), 0.1f);
-        // loadModel("Models/AnimatedMorphCube/glTF-Binary/AnimatedMorphCube.glb", new Vector3f(0, 0, 0), 0.1f);
-
+        
         probeNode.attachChild(assets.get(0));
 
         ChaseCameraAppState chaseCam = new ChaseCameraAppState();
@@ -239,10 +231,7 @@ public class TestGltfLoading extends SimpleApplication {
     private void loadModel(String path, Vector3f offset, Vector3f scale) {
         GltfModelKey k = new GltfModelKey(path);
         //k.setKeepSkeletonPose(true);
-        long t  = System.currentTimeMillis();        
         Spatial s = assetManager.loadModel(k);
-        System.out.println("Load time : " + (System.currentTimeMillis() - t) + " ms");
-        
         s.scale(scale.x, scale.y, scale.z);
         s.move(offset);
         assets.add(s);

+ 7 - 9
jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GlbLoader.java

@@ -32,11 +32,9 @@
 package com.jme3.scene.plugins.gltf;
 
 import com.jme3.asset.AssetInfo;
-import com.jme3.util.BufferUtils;
 import com.jme3.util.LittleEndien;
 
 import java.io.*;
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -52,12 +50,12 @@ public class GlbLoader extends GltfLoader {
      */
     private static final Logger logger = Logger.getLogger(GlbLoader.class.getName());
 
-    private ArrayList<ByteBuffer> data = new ArrayList<>();
+    private ArrayList<byte[]> data = new ArrayList<>();
 
     @Override
     public Object load(AssetInfo assetInfo) throws IOException {
         data.clear();
-        LittleEndien stream = new LittleEndien(new BufferedInputStream(assetInfo.openStream()));
+        LittleEndien stream = new LittleEndien(new DataInputStream(assetInfo.openStream()));
         /* magic */ stream.readInt();
 
         int version = stream.readInt();
@@ -78,11 +76,11 @@ public class GlbLoader extends GltfLoader {
             int chunkType = stream.readInt();
             if (chunkType == JSON_TYPE) {
                 json = new byte[chunkLength];
-                GltfUtils.readToByteArray(stream, json, chunkLength);
+                stream.read(json);
             } else {
-                ByteBuffer buff = BufferUtils.createByteBuffer(chunkLength);
-                GltfUtils.readToByteBuffer(stream, buff, chunkLength);
-                data.add(buff);
+                byte[] bin = new byte[chunkLength];
+                stream.read(bin);
+                data.add(bin);
             }
             //8 is the byte size of the 2 ints chunkLength and chunkType.
             length -= chunkLength + 8;
@@ -95,7 +93,7 @@ public class GlbLoader extends GltfLoader {
     }
 
     @Override
-    protected ByteBuffer getBytes(int bufferIndex, String uri, Integer bufferLength) throws IOException {
+    protected byte[] getBytes(int bufferIndex, String uri, Integer bufferLength) throws IOException {
         return data.get(bufferIndex);
     }
 

+ 19 - 77
jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java

@@ -48,14 +48,11 @@ import com.jme3.scene.mesh.MorphTarget;
 import static com.jme3.scene.plugins.gltf.GltfUtils.*;
 import com.jme3.texture.Texture;
 import com.jme3.texture.Texture2D;
-import com.jme3.util.BufferInputStream;
-import com.jme3.util.BufferUtils;
 import com.jme3.util.IntMap;
 import com.jme3.util.mikktspace.MikktspaceTangentGenerator;
 import java.io.*;
 import java.net.URLDecoder;
 import java.nio.Buffer;
-import java.nio.ByteBuffer;
 import java.nio.FloatBuffer;
 import java.util.*;
 import java.util.logging.Level;
@@ -112,6 +109,7 @@ public class GltfLoader implements AssetLoader {
 
     protected Object loadFromStream(AssetInfo assetInfo, InputStream stream) throws IOException {
         try {
+            dataCache.clear();
             info = assetInfo;
             skinnedSpatials.clear();
             rootNode = new Node();
@@ -183,27 +181,6 @@ public class GltfLoader implements AssetLoader {
             throw new AssetLoadException("An error occurred loading " + assetInfo.getKey().getName(), e);
         } finally {
             stream.close();
-            dataCache.clear();
-            skinBuffers.clear();
-            skinnedSpatials.clear();
-            info = null;
-            docRoot = null;
-            rootNode = null;
-            defaultMat = null;
-            accessors = null;
-            bufferViews = null;
-            buffers = null;
-            scenes = null;
-            nodes = null;
-            meshes = null;
-            materials = null;
-            textures = null;
-            images = null;
-            samplers = null;
-            animations = null;
-            skins = null;
-            cameras = null;
-            useNormalsFlag = false;
         }
     }
 
@@ -576,15 +553,11 @@ public class GltfLoader implements AssetLoader {
         // Not sure it's useful for us, but I guess it's useful when you map data directly to the GPU.
         // int target = getAsInteger(bufferView, "target", 0);
 
-        ByteBuffer data = readData(bufferIndex);
+        byte[] data = readData(bufferIndex);
         data = customContentManager.readExtensionAndExtras("bufferView", bufferView, data);
 
-        if(!(data instanceof ByteBuffer)){
-            throw new IOException("Buffer data is not a NIO Buffer");
-        }
-
         if (store == null) {
-            store = BufferUtils.createByteBuffer(byteLength);
+            store = new byte[byteLength];
         }
 
         if (count == -1) {
@@ -596,40 +569,14 @@ public class GltfLoader implements AssetLoader {
         return store;
     }
 
-    public Buffer viewBuffer(Integer bufferViewIndex, int byteOffset, int count,  
-            int numComponents, VertexBuffer.Format originalFormat,  VertexBuffer.Format targetFormat) throws IOException {
-        JsonObject bufferView = bufferViews.get(bufferViewIndex).getAsJsonObject();
-        Integer bufferIndex = getAsInteger(bufferView, "buffer");
-        assertNotNull(bufferIndex, "No buffer defined for bufferView " + bufferViewIndex);
-        int bvByteOffset = getAsInteger(bufferView, "byteOffset", 0);
-        Integer byteLength = getAsInteger(bufferView, "byteLength");
-        assertNotNull(byteLength, "No byte length defined for bufferView " + bufferViewIndex);
-        int byteStride = getAsInteger(bufferView, "byteStride", 0);
-
-        ByteBuffer data = readData(bufferIndex);
-        data = customContentManager.readExtensionAndExtras("bufferView", bufferView, data);
-
-        if(!(data instanceof ByteBuffer)){
-            throw new IOException("Buffer data is not a NIO Buffer");
-        }
- 
-
-        if (count == -1) {
-            count = byteLength;
-        }
-
-        return GltfUtils.getBufferView(data, byteOffset + bvByteOffset, count, byteStride, numComponents, originalFormat, targetFormat );
-
-    }
-
-    public ByteBuffer readData(int bufferIndex) throws IOException {
+    public byte[] readData(int bufferIndex) throws IOException {
         assertNotNull(buffers, "No buffer defined");
 
         JsonObject buffer = buffers.get(bufferIndex).getAsJsonObject();
         String uri = getAsString(buffer, "uri");
         Integer bufferLength = getAsInteger(buffer, "byteLength");
         assertNotNull(bufferLength, "No byteLength defined for buffer " + bufferIndex);
-        ByteBuffer data = (ByteBuffer) fetchFromCache("buffers", bufferIndex, Object.class);
+        byte[] data = (byte[]) fetchFromCache("buffers", bufferIndex, Object.class);
         if (data != null) {
             return data;
         }
@@ -641,12 +588,12 @@ public class GltfLoader implements AssetLoader {
         return data;
     }
 
-    protected ByteBuffer getBytes(int bufferIndex, String uri, Integer bufferLength) throws IOException {
-        ByteBuffer data;
+    protected byte[] getBytes(int bufferIndex, String uri, Integer bufferLength) throws IOException {
+        byte[] data;
         if (uri != null) {
             if (uri.startsWith("data:")) {
                 // base 64 embed data
-                data = BufferUtils.createByteBuffer(Base64.getDecoder().decode(uri.substring(uri.indexOf(",") + 1)));
+                data = Base64.getDecoder().decode(uri.substring(uri.indexOf(",") + 1));
             } else {
                 // external file let's load it
                 String decoded = decodeUri(uri);
@@ -656,11 +603,11 @@ public class GltfLoader implements AssetLoader {
                 }
 
                 BinDataKey key = new BinDataKey(info.getKey().getFolder() + decoded);
-                try(InputStream input = (InputStream) info.getManager().loadAsset(key)){
-                    data = BufferUtils.createByteBuffer(bufferLength);
-                    GltfUtils.readToByteBuffer(input, data, bufferLength);
+                InputStream input = (InputStream) info.getManager().loadAsset(key);
+                data = new byte[bufferLength];
+                try (DataInputStream dataStream = new DataInputStream(input)) {
+                    dataStream.readFully(data);
                 }
-               
             }
         } else {
             // no URI, this should not happen in a gltf file, only in glb files.
@@ -837,23 +784,19 @@ public class GltfLoader implements AssetLoader {
         if (uri == null) {
             assertNotNull(bufferView, "Image " + sourceIndex + " should either have an uri or a bufferView");
             assertNotNull(mimeType, "Image " + sourceIndex + " should have a mimeType");
-            ByteBuffer data = (ByteBuffer) viewBuffer(bufferView, 0, -1, 1, VertexBuffer.Format.Byte, VertexBuffer.Format.Byte);
-
+            byte[] data = (byte[]) readBuffer(bufferView, 0, -1, null, 1, VertexBuffer.Format.Byte);
             String extension = mimeType.split("/")[1];
             TextureKey key = new TextureKey("image" + sourceIndex + "." + extension, flip);
-            try(BufferedInputStream bis = new BufferedInputStream(new BufferInputStream(data))){
-                result = (Texture2D) info.getManager().loadAssetFromStream(key, bis);
-            }
+            result = (Texture2D) info.getManager().loadAssetFromStream(key, new ByteArrayInputStream(data));
+
         } else if (uri.startsWith("data:")) {
             // base64 encoded image
             String[] uriInfo = uri.split(",");
-            ByteBuffer data = BufferUtils.createByteBuffer(Base64.getDecoder().decode(uriInfo[1]));
+            byte[] data = Base64.getDecoder().decode(uriInfo[1]);
             String headerInfo = uriInfo[0].split(";")[0];
             String extension = headerInfo.split("/")[1];
             TextureKey key = new TextureKey("image" + sourceIndex + "." + extension, flip);
-            try(BufferedInputStream bis = new BufferedInputStream(new BufferInputStream(data))){
-                result = (Texture2D) info.getManager().loadAssetFromStream(key, bis);
-            }
+            result = (Texture2D) info.getManager().loadAssetFromStream(key, new ByteArrayInputStream(data));
         } else {
             // external file image
             String decoded = decodeUri(uri);
@@ -1395,14 +1338,13 @@ public class GltfLoader implements AssetLoader {
             }
             int numComponents = getNumberOfComponents(type);
 
+            Buffer buff = VertexBuffer.createBuffer(format, numComponents, count);
             int bufferSize = numComponents * count;
-            Buffer buff;
             if (bufferViewIndex == null) {
-                buff = VertexBuffer.createBuffer(format, numComponents, count);
                 // no referenced buffer, specs says to pad the buffer with zeros.
                 padBuffer(buff, bufferSize);
             } else {
-                buff = (Buffer) viewBuffer(bufferViewIndex, byteOffset, count, numComponents, originalFormat, format);
+                readBuffer(bufferViewIndex, byteOffset, count, buff, numComponents, originalFormat);
             }
 
             if (bufferType == VertexBuffer.Type.Index) {

+ 132 - 308
jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfUtils.java

@@ -44,8 +44,6 @@ import com.jme3.texture.Texture;
 import com.jme3.util.*;
 import java.io.*;
 import java.nio.*;
-import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
 import java.util.*;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -62,11 +60,7 @@ public class GltfUtils {
      */
     private GltfUtils() {
     }
-
-    public static ByteBuffer asReadableByteBuffer(ByteBuffer bbf){
-        return bbf.slice().order(ByteOrder.LITTLE_ENDIAN);
-    }
-
+    
     /**
      * Parse a json input stream and returns a {@link JsonObject}
      * @param stream the stream to parse
@@ -233,68 +227,62 @@ public class GltfUtils {
         }
     }
 
-    public static void padBuffer(Buffer buffer, int bufferSize) {
-        buffer.clear();
-        if (buffer instanceof IntBuffer) {
-            IntBuffer ib = (IntBuffer) buffer;
-            for (int i = 0; i < bufferSize; i++) {
-                ib.put(0);
+    public static void padBuffer(Object store, int bufferSize) {
+        if (store instanceof Buffer) {
+            Buffer buffer = (Buffer) store;
+            buffer.clear();
+            if (buffer instanceof IntBuffer) {
+                IntBuffer ib = (IntBuffer) buffer;
+                for (int i = 0; i < bufferSize; i++) {
+                    ib.put(0);
+                }
+            } else if (buffer instanceof FloatBuffer) {
+                FloatBuffer fb = (FloatBuffer) buffer;
+                for (int i = 0; i < bufferSize; i++) {
+                    fb.put(0);
+                }
+            } else if (buffer instanceof ShortBuffer) {
+                ShortBuffer sb = (ShortBuffer) buffer;
+                for (int i = 0; i < bufferSize; i++) {
+                    sb.put((short) 0);
+                }
+            } else if (buffer instanceof ByteBuffer) {
+                ByteBuffer bb = (ByteBuffer) buffer;
+                for (int i = 0; i < bufferSize; i++) {
+                    bb.put((byte) 0);
+                }
             }
-        } else if (buffer instanceof FloatBuffer) {
-            FloatBuffer fb = (FloatBuffer) buffer;
-            for (int i = 0; i < bufferSize; i++) {
-                fb.put(0);
+            buffer.rewind();
+        }
+        if (store instanceof short[]) {
+            short[] array = (short[]) store;
+            for (int i = 0; i < array.length; i++) {
+                array[i] = 0;
             }
-        } else if (buffer instanceof ShortBuffer) {
-            ShortBuffer sb = (ShortBuffer) buffer;
-            for (int i = 0; i < bufferSize; i++) {
-                sb.put((short) 0);
+        } else if (store instanceof float[]) {
+            float[] array = (float[]) store;
+            for (int i = 0; i < array.length; i++) {
+                array[i] = 0;
             }
-        } else if (buffer instanceof ByteBuffer) {
-            ByteBuffer bb = (ByteBuffer) buffer;
-            for (int i = 0; i < bufferSize; i++) {
-                bb.put((byte) 0);
+        } else if (store instanceof Vector3f[]) {
+            Vector3f[] array = (Vector3f[]) store;
+            for (int i = 0; i < array.length; i++) {
+                array[i] = new Vector3f();
+            }
+        } else if (store instanceof Quaternion[]) {
+            Quaternion[] array = (Quaternion[]) store;
+            for (int i = 0; i < array.length; i++) {
+                array[i] = new Quaternion();
+            }
+        } else if (store instanceof Matrix4f[]) {
+            Matrix4f[] array = (Matrix4f[]) store;
+            for (int i = 0; i < array.length; i++) {
+                array[i] = new Matrix4f();
             }
-        }
-        buffer.rewind();
-    }
-
-    public static void padBuffer(float[] array, int bufferSize) {
-        for (int i = 0; i < bufferSize; i++) {
-            array[i] = 0;
-        }
-    }
-
-    public static void padBuffer(short[] array, int bufferSize) {
-        for (int i = 0; i < bufferSize; i++) {
-            array[i] = 0;
-        }
-    }
-    
-    public static void padBuffer(Vector3f[] array, int bufferSize) {
-        for (int i = 0; i < bufferSize; i++) {
-            array[i] = new Vector3f();
         }
     }
 
-    public static void padBuffer(Quaternion[] array, int bufferSize) {
-        for (int i = 0; i < bufferSize; i++) {
-            array[i] = new Quaternion();
-        }      
-    }
-
-    public static void padBuffer(Matrix4f[] array, int bufferSize) {
-        for (int i = 0; i < bufferSize; i++) {
-            array[i] = new Matrix4f();
-        }        
-    }
-
-
-
-
-
-    public static void populateBuffer(Object store, ByteBuffer source, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
-        source = asReadableByteBuffer(source);
+    public static void populateBuffer(Object store, byte[] source, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
 
         if (store instanceof Buffer) {
             Buffer buffer = (Buffer) store;
@@ -303,37 +291,34 @@ public class GltfUtils {
                 populateByteBuffer((ByteBuffer) buffer, source, count, byteOffset, byteStride, numComponents, format);
                 return;
             }
+            LittleEndien stream = getStream(source);
             if (buffer instanceof ShortBuffer) {
-                populateShortBuffer((ShortBuffer) buffer, source, count, byteOffset, byteStride, numComponents, format);
+                populateShortBuffer((ShortBuffer) buffer, stream, count, byteOffset, byteStride, numComponents, format);
             } else if (buffer instanceof IntBuffer) {
-                populateIntBuffer((IntBuffer) buffer, source, count, byteOffset, byteStride, numComponents, format);
+                populateIntBuffer((IntBuffer) buffer, stream, count, byteOffset, byteStride, numComponents, format);
             } else if (buffer instanceof FloatBuffer) {
-                populateFloatBuffer((FloatBuffer) buffer, source, count, byteOffset, byteStride, numComponents, format);
+                populateFloatBuffer((FloatBuffer) buffer, stream, count, byteOffset, byteStride, numComponents, format);
             }
             buffer.rewind();
             return;
         }
-
+        LittleEndien stream = getStream(source);
         if (store instanceof byte[]) {
-            populateByteArray((byte[]) store, source, count, byteOffset, byteStride, numComponents, format);
+            populateByteArray((byte[]) store, stream, count, byteOffset, byteStride, numComponents, format);
         } else if (store instanceof short[]) {
-            populateShortArray((short[]) store, source, count, byteOffset, byteStride, numComponents, format);
+            populateShortArray((short[]) store, stream, count, byteOffset, byteStride, numComponents, format);
         } else if (store instanceof float[]) {
-            populateFloatArray((float[]) store, source, count, byteOffset, byteStride, numComponents, format);
+            populateFloatArray((float[]) store, stream, count, byteOffset, byteStride, numComponents, format);
         } else if (store instanceof Vector3f[]) {
-            populateVector3fArray((Vector3f[]) store, source, count, byteOffset, byteStride, numComponents, format);
+            populateVector3fArray((Vector3f[]) store, stream, count, byteOffset, byteStride, numComponents, format);
         } else if (store instanceof Quaternion[]) {
-            populateQuaternionArray((Quaternion[]) store, source, count, byteOffset, byteStride, numComponents, format);
+            populateQuaternionArray((Quaternion[]) store, stream, count, byteOffset, byteStride, numComponents, format);
         } else if (store instanceof Matrix4f[]) {
-            populateMatrix4fArray((Matrix4f[]) store, source, count, byteOffset, byteStride, numComponents, format);
+            populateMatrix4fArray((Matrix4f[]) store, stream, count, byteOffset, byteStride, numComponents, format);
         }
     }
 
-    private static void skip(ByteBuffer buff, int n) {
-        buff.position(Math.min(buff.position() + n, buff.limit()));
-    }
-
-    private static void populateByteBuffer(ByteBuffer buffer, ByteBuffer source, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) {
+    private static void populateByteBuffer(ByteBuffer buffer, byte[] source, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) {
         int componentSize = format.getComponentSize();
         int index = byteOffset;
         int dataLength = componentSize * numComponents;
@@ -341,69 +326,69 @@ public class GltfUtils {
         int end = count * stride + byteOffset;
         while (index < end) {
             for (int i = 0; i < numComponents; i++) {
-                buffer.put(source.get(index + i));
+                buffer.put(source[index + i]);
             }
             index += stride;
         }
     }
 
-    private static void populateShortBuffer(ShortBuffer buffer, ByteBuffer source, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
+    private static void populateShortBuffer(ShortBuffer buffer, LittleEndien stream, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
         int componentSize = format.getComponentSize();
         int index = byteOffset;
         int dataLength = componentSize * numComponents;
         int stride = Math.max(dataLength, byteStride);
-        int end = count * stride + byteOffset;        
-        source.position(source.position() + byteOffset);
+        int end = count * stride + byteOffset;
+        stream.skipBytes(byteOffset);
         while (index < end) {
             for (int i = 0; i < numComponents; i++) {
-                buffer.put(source.getShort());
+                buffer.put(stream.readShort());
             }
 
             if (dataLength < stride) {
-                skip(source, stride - dataLength);
+                stream.skipBytes(stride - dataLength);
             }
             index += stride;
         }
     }
 
 
-    private static void populateIntBuffer(IntBuffer buffer, ByteBuffer source, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
+    private static void populateIntBuffer(IntBuffer buffer, LittleEndien stream, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
         int componentSize = format.getComponentSize();
         int index = byteOffset;
         int dataLength = componentSize * numComponents;
         int stride = Math.max(dataLength, byteStride);
         int end = count * stride + byteOffset;
-        source.position(source.position() + byteOffset);
+        stream.skipBytes(byteOffset);
         while (index < end) {
             for (int i = 0; i < numComponents; i++) {
-                buffer.put(source.getInt());
+                buffer.put(stream.readInt());
             }
             if (dataLength < stride) {
-                skip(source, stride - dataLength);
+                stream.skipBytes(stride - dataLength);
             }
             index += stride;
         }
     }
 
-    private static void populateFloatBuffer(FloatBuffer buffer, ByteBuffer source, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
+    private static void populateFloatBuffer(FloatBuffer buffer, LittleEndien stream, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
         int componentSize = format.getComponentSize();
         int index = byteOffset;
         int dataLength = componentSize * numComponents;
         int stride = Math.max(dataLength, byteStride);
         int end = count * stride + byteOffset;
-        source.position(source.position() + byteOffset);
+        stream.skipBytes(byteOffset);
         while (index < end) {
             for (int i = 0; i < numComponents; i++) {
-                buffer.put(readAsFloat(source, format));
+                buffer.put(readAsFloat(stream, format));
             }
             if (dataLength < stride) {
-                skip(source, stride - dataLength);
+                stream.skipBytes(stride - dataLength);
             }
             index += stride;
         }
     }
 
-    public static float readAsFloat(ByteBuffer source, VertexBuffer.Format format) throws IOException {
+    public 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
@@ -414,34 +399,34 @@ public class GltfUtils {
         int c;
         switch (format) {
             case Byte:
-                c = source.get();
+                c = stream.readByte();
                 return Math.max(c / 127f, -1f);
             case UnsignedByte:
-                c = source.get() & 0xFF;
+                c = stream.readUnsignedByte();
                 return c / 255f;
             case Short:
-                c = source.getShort();
+                c = stream.readShort();
                 return Math.max(c / 32767f, -1f);
-            case UnsignedShort:               
-                c = source.get() & 0xff | (source.get() & 0xff) << 8;
+            case UnsignedShort:
+                c = stream.readUnsignedShort();
                 return c / 65535f;
             default:
                 //we have a regular float
-                return source.getFloat();
+                return stream.readFloat();
         }
 
     }
 
-    private static void populateByteArray(byte[] array, ByteBuffer source, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
+    private static void populateByteArray(byte[] array, LittleEndien stream, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
         int componentSize = format.getComponentSize();
         int index = byteOffset;
         int dataLength = componentSize * numComponents;
         int stride = Math.max(dataLength, byteStride);
         int end = count * stride + byteOffset;
-        source.position(source.position() + byteOffset);
+        stream.skipBytes(byteOffset);
 
         if (dataLength == stride) {
-            read(source, array, end - index);
+            read(stream, array, end - index);
 
             return;
         }
@@ -449,21 +434,20 @@ public class GltfUtils {
         int arrayIndex = 0;
         byte[] buffer = new byte[numComponents];
         while (index < end) {
-            read(source, buffer, numComponents);
+            read(stream, buffer, numComponents);
             System.arraycopy(buffer, 0, array, arrayIndex, numComponents);
             arrayIndex += numComponents;
             if (dataLength < stride) {
-                skip(source, stride - dataLength);
+                stream.skipBytes(stride - dataLength);
             }
             index += stride;
         }
     }
 
-    private static void read(ByteBuffer source, byte[] buffer, int length) throws IOException {
+    private static void read(LittleEndien stream, byte[] buffer, int length) throws IOException {
         int n = 0;
         while (n < length) {
-            int cnt = Math.min(source.remaining(), length - n);
-            source.get(buffer, n, cnt);
+            int cnt = stream.read(buffer, n, length - n);
             if (cnt < 0) {
                 throw new AssetLoadException("Data ended prematurely");
             }
@@ -471,25 +455,25 @@ public class GltfUtils {
         }
     }
 
-    private static void populateShortArray(short[] array, ByteBuffer source, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
+    private static void populateShortArray(short[] array, LittleEndien stream, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
         int componentSize = format.getComponentSize();
         int index = byteOffset;
         int dataLength = componentSize * numComponents;
         int stride = Math.max(dataLength, byteStride);
         int end = count * stride + byteOffset;
-        source.position(source.position() + byteOffset);
+        stream.skipBytes(byteOffset);
         int arrayIndex = 0;
         while (index < end) {
             for (int i = 0; i < numComponents; i++) {
                 if (componentSize == 2) {
-                    array[arrayIndex] = source.getShort();
+                    array[arrayIndex] = stream.readShort();
                 } else {
-                    array[arrayIndex] = source.get();
+                    array[arrayIndex] = stream.readByte();
                 }
                 arrayIndex++;
             }
             if (dataLength < stride) {
-                skip(source, stride - dataLength);
+                stream.skipBytes(stride - dataLength);
             }
             index += stride;
         }
@@ -573,106 +557,107 @@ public class GltfUtils {
         mesh.getBuffer(VertexBuffer.Type.BoneWeight).setUsage(VertexBuffer.Usage.CpuOnly);
     }
 
-    private static void populateFloatArray(float[] array, ByteBuffer source, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
+    private static void populateFloatArray(float[] array, LittleEndien stream, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
         int componentSize = format.getComponentSize();
         int index = byteOffset;
         int dataLength = componentSize * numComponents;
         int stride = Math.max(dataLength, byteStride);
         int end = count * stride + byteOffset;
-        source.position(source.position() + byteOffset);
+        stream.skipBytes(byteOffset);
         int arrayIndex = 0;
         while (index < end) {
             for (int i = 0; i < numComponents; i++) {
-                array[arrayIndex] = readAsFloat(source, format);
+                array[arrayIndex] = readAsFloat(stream, format);
                 arrayIndex++;
             }
             if (dataLength < stride) {
-                skip(source, stride - dataLength);
+                stream.skipBytes(stride - dataLength);
             }
             index += stride;
         }
     }
 
-    private static void populateVector3fArray(Vector3f[] array, ByteBuffer source, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
+    private static void populateVector3fArray(Vector3f[] array, LittleEndien stream, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
         int componentSize = format.getComponentSize();
         int index = byteOffset;
         int dataLength = componentSize * numComponents;
         int stride = Math.max(dataLength, byteStride);
         int end = count * stride + byteOffset;
-        source.position(source.position() + byteOffset);
+        stream.skipBytes(byteOffset);
         int arrayIndex = 0;
         while (index < end) {
             array[arrayIndex] = new Vector3f(
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format)
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format)
             );
 
             arrayIndex++;
             if (dataLength < stride) {
-                skip(source, stride - dataLength);
+                stream.skipBytes(stride - dataLength);
             }
+
             index += stride;
         }
     }
 
-    private static void populateQuaternionArray(Quaternion[] array, ByteBuffer source, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
+    private static void populateQuaternionArray(Quaternion[] array, LittleEndien stream, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
         int componentSize = format.getComponentSize();
         int index = byteOffset;
         int dataLength = componentSize * numComponents;
         int stride = Math.max(dataLength, byteStride);
         int end = count * stride + byteOffset;
-        source.position(source.position() + byteOffset);
+        stream.skipBytes(byteOffset);
         int arrayIndex = 0;
         while (index < end) {
             array[arrayIndex] = new Quaternion(
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format)
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format)
             );
 
             arrayIndex++;
             if (dataLength < stride) {
-                skip(source, stride - dataLength);
+                stream.skipBytes(stride - dataLength);
             }
             index += stride;
         }
     }
 
-    private static void populateMatrix4fArray(Matrix4f[] array, ByteBuffer source, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
+    private static void populateMatrix4fArray(Matrix4f[] array, LittleEndien stream, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
         int componentSize = format.getComponentSize();
         int index = byteOffset;
         int dataLength = componentSize * numComponents;
         int stride = Math.max(dataLength, byteStride);
         int end = count * stride + byteOffset;
-        source.position(source.position() + byteOffset);
+        stream.skipBytes(byteOffset);
         int arrayIndex = 0;
         while (index < end) {
 
             array[arrayIndex] = toRowMajor(
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format),
-                    readAsFloat(source, format)
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format),
+                    readAsFloat(stream, format)
             );
             //gltf matrix are column major, JME ones are row major.
 
             arrayIndex++;
             if (dataLength < stride) {
-                skip(source, stride - dataLength);
+                stream.skipBytes(stride - dataLength);
             }
 
             index += stride;
@@ -910,165 +895,4 @@ public class GltfUtils {
             System.err.println("\n---------------------------");
         }
     }
-
-    public static void readToByteBuffer(InputStream input, ByteBuffer dst, int bytesToRead) throws IOException {
-        if (bytesToRead <= 0) throw new IOException("bytesToRead must be > 0");
-
-        int startPos = dst.position();
-        int remaining = dst.limit() - startPos;
-        if (remaining < bytesToRead) {
-            throw new IOException("Destination ByteBuffer too small: remaining=" + remaining + " < bytesToRead=" + bytesToRead);
-        }
-    
-        ReadableByteChannel ch = Channels.newChannel(input); 
-        int total = 0;
-        while (total < bytesToRead) {
-            int n = ch.read(dst);
-            if (n == -1) break;
-            total += n;
-        }
-
-        if (total < bytesToRead) {
-            throw new IOException("Data ended prematurely " + total + " < " + bytesToRead);
-        }
-
-        dst.flip();
-    }
-
-    public static void readToByteArray(InputStream input, byte[] dst, int bytesToRead) throws IOException {
-        if (bytesToRead < 0) throw new IllegalArgumentException("bytesToRead < 0");
-        if (bytesToRead > dst.length) {
-            throw new IOException("Destination array too small: length=" + dst.length + " < bytesToRead=" + bytesToRead);
-        }
-
-        int totalRead = 0;
-        while (totalRead < bytesToRead) {
-            int n = input.read(dst, totalRead, bytesToRead - totalRead);
-            if (n == -1) break;
-            totalRead += n;
-        }
-
-        if (totalRead < bytesToRead) {
-            throw new IOException("Data ended prematurely " + totalRead + " < " + bytesToRead);
-        }
-    }
-
-
-    /**
-     * Try to expose a glTF buffer region as a typed NIO view without copying.
-     * Falls back to allocating a destination buffer and populating it when
-     * interleaving, normalization, or format mismatch prevents a pure view.
-     *
-     * @param source         the original ByteBuffer (direct or heap)
-     * @param count          number of elements
-     * @param byteOffset     start offset within source (relative to beginning)
-     * @param byteStride     stride in bytes (0 means tightly packed = element size)
-     * @param numComponents  components per element (e.g. 3 for VEC3)
-     * @param originalFormat the source component type  
-     * @param targetFormat   the desired buffer view type to return
-     */
-    public static Buffer getBufferView(ByteBuffer source, int byteOffset,  int count, int byteStride,
-                                       int numComponents, VertexBuffer.Format originalFormat,
-                                       VertexBuffer.Format targetFormat) throws IOException {
-        // Work in little-endian as per glTF spec
-        source = asReadableByteBuffer(source);  
-
-        // Layout from source format
-        int srcCompSize = originalFormat.getComponentSize();
-        int elemSize = srcCompSize * numComponents;
-        int stride = Math.max(elemSize, byteStride);
-        int start = byteOffset;
-        int bytes = stride * count;
-
-
-        boolean tightlyPacked = (stride == elemSize);
-
-        if (tightlyPacked) {
-            ByteBuffer view = source.duplicate();
-            view.position(start).limit(start + bytes);
-            view = view.slice().order(ByteOrder.LITTLE_ENDIAN);
-
-            // Zero-copy returns only when source/target formats are compatible and aligned
-            switch (targetFormat) {
-                case Byte:
-                case UnsignedByte:
-                    if (srcCompSize == 1 &&
-                        (originalFormat == VertexBuffer.Format.Byte ||
-                         originalFormat == VertexBuffer.Format.UnsignedByte)) {
-                        return view;
-                    }
-                    break;
-
-                case Short:
-                case UnsignedShort:
-                    if (srcCompSize == 2 &&
-                        (originalFormat == VertexBuffer.Format.Short ||
-                         originalFormat == VertexBuffer.Format.UnsignedShort) &&
-                        (start & 1) == 0) {
-                        return view.asShortBuffer();
-                    }
-                    break;
-
-                case Int:
-                case UnsignedInt:
-                    if (srcCompSize == 4 &&
-                        (originalFormat == VertexBuffer.Format.Int ||
-                         originalFormat == VertexBuffer.Format.UnsignedInt) &&
-                        (start & 3) == 0) {
-                        return view.asIntBuffer();
-                    }
-                    break;
-
-                case Float:
-                    if (srcCompSize == 4 &&
-                        originalFormat == VertexBuffer.Format.Float &&
-                        (start & 3) == 0) {
-                        return view.asFloatBuffer();
-                    }
-                    break;
-
-                case Double:
-                    if (srcCompSize == 8 &&
-                        originalFormat == VertexBuffer.Format.Double &&
-                        (start & 7) == 0) {
-                        return view.asDoubleBuffer();
-                    }
-                    break;
-            }
-        }
-
-        // Fallback: allocate destination buffer by desired targetFormat and populate from source
-        int elements = count * numComponents;
-        switch (targetFormat) {
-            case Byte:
-            case UnsignedByte: {
-                ByteBuffer out = BufferUtils.createByteBuffer(elements);
-                populateBuffer(out, source, count, byteOffset, byteStride, numComponents, originalFormat);
-                return out;
-            }
-            case Short:
-            case UnsignedShort: {
-                ShortBuffer out = BufferUtils.createShortBuffer(elements);
-                populateBuffer(out, source, count, byteOffset, byteStride, numComponents, originalFormat);
-                return out;
-            }
-            case Int:
-            case UnsignedInt: {
-                IntBuffer out = BufferUtils.createIntBuffer(elements);
-                populateBuffer(out, source, count, byteOffset, byteStride, numComponents, originalFormat);
-                return out;
-            }
-            case Float: {
-                FloatBuffer out = BufferUtils.createFloatBuffer(elements);
-                populateBuffer(out, source, count, byteOffset, byteStride, numComponents, originalFormat);
-                return out;
-            }
-            case Double:
-                throw new IllegalArgumentException("Double conversion fallback not supported");
-            default:
-                throw new IllegalArgumentException("Unsupported format " + targetFormat);
-        }
-    }
-
-
 }