www.xbdev.net
xbdev - software development
Wednesday February 5, 2025
Home | Contact | Support | glTF File Format The JPG of 3D Formats ...
     
 

glTF File Format Tutorials

Unlocking the power ...

 


Complete Vanilla JavaScript class for loading and parsing the 3D File format (glTF)


The complete code is given below for the loader/dumper. You can try an online version here (LINK)

class glTFLoader {
    
async load(urlgltfPath) {
        try {
            const 
response await fetch(url);
            const 
gltf await response.json();
            
gltf.gltfPath gltfPath;
            const 
parsedData await this.parseGLTF(gltf);
            return 
parsedData;
        } catch (
error) {
            
console.error('Error loading GLTF file:'error);
            throw 
error;
        }
    }

    
async parseGLTF(gltf) {
        const 
parsedData = {
            
buffersawait this.loadBuffers(gltf),
            
bufferViewsgltf.bufferViews,
            
accessorsgltf.accessors,
            
meshesgltf.meshes,
            
nodesgltf.nodes,
            
materialsgltf.materials,
            
texturesgltf.textures,
            
animationsgltf.animations,
        };

        
this.extractMeshData(parsedData);
        
this.extractAnimations(parsedData);
        
this.extractTextures(parsedData);

        return 
parsedData;
    }

    
async loadBuffers(gltf) {
        const 
bufferPromises gltf.buffers.map(buffer => fetchgltf.gltfPath buffer.uri ).then(res => res.arrayBuffer()));
        return 
await Promise.all(bufferPromises);
    }

    
extractMeshData(parsedData) {
        
parsedData.meshes.forEach(mesh => {
            
mesh.primitives.forEach(primitive => {
                const 
positionAccessorIndex primitive.attributes.POSITION;
                const 
positionAccessor parsedData.accessors[positionAccessorIndex];
                const 
positionBufferView parsedData.bufferViews[positionAccessor.bufferView];
                const 
positionBuffer parsedData.buffers[positionBufferView.buffer];

                const 
positions = new Float32Array(
                    
positionBuffer,
                    
positionBufferView.byteOffset + (positionAccessor.byteOffset || 0),
                    
positionAccessor.count * (positionAccessor.type === 'VEC3' 1)
                );
                
primitive.positions positions;

                if (
primitive.indices !== undefined) {
                    const 
indexAccessor parsedData.accessors[primitive.indices];
                    const 
indexBufferView parsedData.bufferViews[indexAccessor.bufferView];
                    const 
indexBuffer parsedData.buffers[indexBufferView.buffer];

                    const 
indices = new Uint16Array(
                        
indexBuffer,
                        
indexBufferView.byteOffset + (indexAccessor.byteOffset || 0),
                        
indexAccessor.count
                    
);
                    
primitive.indices indices;
                }

                if (
primitive.attributes.NORMAL !== undefined) {
                    const 
normalAccessorIndex primitive.attributes.NORMAL;
                    const 
normalAccessor parsedData.accessors[normalAccessorIndex];
                    const 
normalBufferView parsedData.bufferViews[normalAccessor.bufferView];
                    const 
normalBuffer parsedData.buffers[normalBufferView.buffer];

                    const 
normals = new Float32Array(
                        
normalBuffer,
                        
normalBufferView.byteOffset + (normalAccessor.byteOffset || 0),
                        
normalAccessor.count * (normalAccessor.type === 'VEC3' 1)
                    );
                    
primitive.normals normals;
                }

                if (
primitive.attributes.TEXCOORD_0 !== undefined) {
                    const 
texCoordAccessorIndex primitive.attributes.TEXCOORD_0;
                    const 
texCoordAccessor parsedData.accessors[texCoordAccessorIndex];
                    const 
texCoordBufferView parsedData.bufferViews[texCoordAccessor.bufferView];
                    const 
texCoordBuffer parsedData.buffers[texCoordBufferView.buffer];

                    const 
texCoords = new Float32Array(
                        
texCoordBuffer,
                        
texCoordBufferView.byteOffset + (texCoordAccessor.byteOffset || 0),
                        
texCoordAccessor.count * (texCoordAccessor.type === 'VEC2' 1)
                    );
                    
primitive.texCoords texCoords;
                }
            });
        });
    }

    
extractAnimations(parsedData) {
        if (
parsedData.animations) {
            
parsedData.animations.forEach(animation => {
                
animation.samplers.forEach(sampler => {
                    const 
inputAccessor parsedData.accessors[sampler.input];
                    const 
inputBufferView parsedData.bufferViews[inputAccessor.bufferView];
                    const 
inputBuffer parsedData.buffers[inputBufferView.buffer];

                    
sampler.inputData = new Float32Array(
                        
inputBuffer,
                        
inputBufferView.byteOffset + (inputAccessor.byteOffset || 0),
                        
inputAccessor.count
                    
);

                    const 
outputAccessor parsedData.accessors[sampler.output];
                    const 
outputBufferView parsedData.bufferViews[outputAccessor.bufferView];
                    const 
outputBuffer parsedData.buffers[outputBufferView.buffer];

                    
sampler.outputData = new Float32Array(
                        
outputBuffer,
                        
outputBufferView.byteOffset + (outputAccessor.byteOffset || 0),
                        
outputAccessor.count * (outputAccessor.type === 'VEC3' 1)
                    );
                });
            });
        }
    }

    
extractTextures(parsedData) {
        if (
parsedData.textures) {
            
parsedData.textures.forEach(texture => {
                if (
texture.source !== undefined) {
                    const 
image parsedData.images[texture.source];
                    
texture.imageUri image.uri;
                }
            });
        }
    }
}

// Function to display statistics
function displayStats(parsedData) {
    
    const 
stats = {
        
numberOfMeshesparsedData.meshes parsedData.meshes.length 0,
        
numberOfNodesparsedData.nodes parsedData.nodes.length 0,
        
numberOfMaterialsparsedData.materials parsedData.materials.length 0,
        
numberOfTexturesparsedData.textures parsedData.textures.length 0,
        
numberOfAnimationsparsedData.animations parsedData.animations.length 0,
    };

    
let details = `
        Number of Meshes: 
${stats.numberOfMeshes}<br>
        Number of Nodes: 
${stats.numberOfNodes}<br>
        Number of Materials: 
${stats.numberOfMaterials}<br>
        Number of Textures: 
${stats.numberOfTextures}<br>
        Number of Animations: 
${stats.numberOfAnimations}<br>
        <h2>Mesh Details:</h2>
    
`;

    
parsedData.meshes.forEach((meshmeshIndex) => {
        
details += `Mesh ${meshIndex} - Name: ${mesh.name || 'Unnamed'}<br>`;
        
mesh.primitives.forEach((primitiveprimitiveIndex) => {
            const 
verticesCount primitive.positions primitive.positions.length 0;
            const 
indicesCount primitive.indices primitive.indices.length 0;
            
details += `
                
${' '.repeat(8)}Primitive ${primitiveIndex}:<br>
                
${' '.repeat(16)}Number of Vertices: ${verticesCount}<br>
                
${' '.repeat(16)}Number of Indices: ${indicesCount}<br>
            
`;
        });
    });
  
    const 
statsDiv document.createElement('div');
    
document.body.appendChildstatsDiv );
      
statsDiv.innerHTML details;
}

// Function to load GLTF file and display statistics
async function loadGLTFAndShowStats(urlgltfPath) {
    const 
loader = new glTFLoader();
    try {
        const 
parsedData await loader.load(urlgltfPath);
        
displayStats(parsedData);
    } catch (
error) {
        
console.error('An error occurred:'error);
    }
}



const 
gltfFileUrl 'https://webgpulab.xbdev.net/var/resources/gltf/lowpolyworld.gltf';
const 
gltfPath 'https://webgpulab.xbdev.net/var/resources/gltf/';

let div document.createElement('div');
document.body.appendChilddiv );
div.innerHTML = `
Vanilla glTF loader/parser in native JavaScript<br><br>

File: 
${gltfFileUrl}<br><br>
`;


loadGLTFAndShowStats(gltfFileUrlgltfPath);


console.log('done..');


This is what the output for the loader/dump script above looks like:


Vanilla glTF loader/parser in native JavaScript

File
https://webgpulab.xbdev.net/var/resources/gltf/lowpolyworld.gltf

Number of Meshes40
Number of Nodes
40
Number of Materials
22
Number of Textures
0
Number of Animations
0
Mesh Details
:
Mesh 0 NameПлоскость.003_Плоскость.000
        Primitive 0
:
                
Number of Vertices224
                Number of Indices
408
        Primitive 1
:
                
Number of Vertices168
                Number of Indices
288
        Primitive 2
:
                
Number of Vertices246
                Number of Indices
456
        Primitive 3
:
                
Number of Vertices1040
                Number of Indices
1536
        Primitive 4
:
                
Number of Vertices68
                Number of Indices
108
        Primitive 5
:
                
Number of Vertices300
                Number of Indices
504
        Primitive 6
:
                
Number of Vertices277
                Number of Indices
423
        Primitive 7
:
                
Number of Vertices800
                Number of Indices
1200
        Primitive 8
:
                
Number of Vertices1256
                Number of Indices
2172
        Primitive 9
:
                
Number of Vertices4552
                Number of Indices
9108
        Primitive 10
:
                
Number of Vertices32
                Number of Indices
60
        Primitive 11
:
                
Number of Vertices48
                Number of Indices
72
Mesh 1 
NamePlane.013
        Primitive 0
:
                
Number of Vertices4
                Number of Indices
6
Mesh 2 
NamePlane.012
        Primitive 0
:
                
Number of Vertices4
                Number of Indices
6
Mesh 3 
NamePlane.011
        Primitive 0
:
                
Number of Vertices4
                Number of Indices
6
Mesh 4 
NamePlane.010
        Primitive 0
:
                
Number of Vertices4
                Number of Indices
6
Mesh 5 
NamePlane.009
        Primitive 0
:
                
Number of Vertices4
                Number of Indices
6
Mesh 6 
NamePlane.008
        Primitive 0
:
                
Number of Vertices4
                Number of Indices
6
Mesh 7 
NamePlane.007
        Primitive 0
:
                
Number of Vertices4
                Number of Indices
6
Mesh 8 
NamePlane
        Primitive 0
:
                
Number of Vertices4
                Number of Indices
6
Mesh 9 
NamePlane.001
        Primitive 0
:
                
Number of Vertices4
                Number of Indices
6
Mesh 10 
NamePlane.006
        Primitive 0
:
                
Number of Vertices4
                Number of Indices
6
Mesh 11 
NamePlane.002
        Primitive 0
:
                
Number of Vertices4
                Number of Indices
6
Mesh 12 
NamePlane.004
        Primitive 0
:
                
Number of Vertices4
                Number of Indices
6
Mesh 13 
NamePlane.005
        Primitive 0
:
                
Number of Vertices4
                Number of Indices
6
Mesh 14 
NameCylinder.024
        Primitive 0
:
                
Number of Vertices36
                Number of Indices
60
        Primitive 1
:
                
Number of Vertices132
                Number of Indices
132
Mesh 15 
NameCylinder.023
        Primitive 0
:
                
Number of Vertices36
                Number of Indices
60
        Primitive 1
:
                
Number of Vertices132
                Number of Indices
132
Mesh 16 
NameCylinder.022
        Primitive 0
:
                
Number of Vertices108
                Number of Indices
180
        Primitive 1
:
                
Number of Vertices168
                Number of Indices
168
Mesh 17 
NameCylinder.021
        Primitive 0
:
                
Number of Vertices108
                Number of Indices
180
        Primitive 1
:
                
Number of Vertices168
                Number of Indices
168
Mesh 18 
NameCylinder.020
        Primitive 0
:
                
Number of Vertices108
                Number of Indices
180
        Primitive 1
:
                
Number of Vertices168
                Number of Indices
168
Mesh 19 
NameCylinder.019
        Primitive 0
:
                
Number of Vertices36
                Number of Indices
60
        Primitive 1
:
                
Number of Vertices132
                Number of Indices
132
Mesh 20 
NameCylinder.018
        Primitive 0
:
                
Number of Vertices36
                Number of Indices
60
        Primitive 1
:
                
Number of Vertices132
                Number of Indices
132
Mesh 21 
NameCylinder.017
        Primitive 0
:
                
Number of Vertices36
                Number of Indices
60
        Primitive 1
:
                
Number of Vertices132
                Number of Indices
132
Mesh 22 
NameCylinder.016
        Primitive 0
:
                
Number of Vertices108
                Number of Indices
180
        Primitive 1
:
                
Number of Vertices168
                Number of Indices
168
Mesh 23 
NameIcosphere.005
        Primitive 0
:
                
Number of Vertices720
                Number of Indices
720
Mesh 24 
NameCylinder.015
        Primitive 0
:
                
Number of Vertices36
                Number of Indices
60
        Primitive 1
:
                
Number of Vertices132
                Number of Indices
132
Mesh 25 
NameCylinder.014
        Primitive 0
:
                
Number of Vertices36
                Number of Indices
60
        Primitive 1
:
                
Number of Vertices132
                Number of Indices
132
Mesh 26 
NameCylinder.013
        Primitive 0
:
                
Number of Vertices108
                Number of Indices
180
        Primitive 1
:
                
Number of Vertices168
                Number of Indices
168
Mesh 27 
NameCylinder.012
        Primitive 0
:
                
Number of Vertices108
                Number of Indices
180
        Primitive 1
:
                
Number of Vertices168
                Number of Indices
168
Mesh 28 
NameCylinder.011
        Primitive 0
:
                
Number of Vertices108
                Number of Indices
180
        Primitive 1
:
                
Number of Vertices168
                Number of Indices
168
Mesh 29 
NameCylinder.010
        Primitive 0
:
                
Number of Vertices36
                Number of Indices
60
        Primitive 1
:
                
Number of Vertices132
                Number of Indices
132
Mesh 30 
NameCylinder.009
        Primitive 0
:
                
Number of Vertices108
                Number of Indices
180
        Primitive 1
:
                
Number of Vertices168
                Number of Indices
168
Mesh 31 
NameIcosphere.003
        Primitive 0
:
                
Number of Vertices720
                Number of Indices
720
Mesh 32 
NameCylinder.001
        Primitive 0
:
                
Number of Vertices108
                Number of Indices
180
        Primitive 1
:
                
Number of Vertices168
                Number of Indices
168
Mesh 33 
NameCylinder.008
        Primitive 0
:
                
Number of Vertices36
                Number of Indices
60
        Primitive 1
:
                
Number of Vertices132
                Number of Indices
132
Mesh 34 
NameCylinder.007
        Primitive 0
:
                
Number of Vertices36
                Number of Indices
60
        Primitive 1
:
                
Number of Vertices132
                Number of Indices
132
Mesh 35 
NameCylinder.006
        Primitive 0
:
                
Number of Vertices36
                Number of Indices
60
        Primitive 1
:
                
Number of Vertices132
                Number of Indices
132
Mesh 36 
NameCylinder.005
        Primitive 0
:
                
Number of Vertices36
                Number of Indices
60
        Primitive 1
:
                
Number of Vertices132
                Number of Indices
132
Mesh 37 
NameCylinder.002
        Primitive 0
:
                
Number of Vertices36
                Number of Indices
60
        Primitive 1
:
                
Number of Vertices132
                Number of Indices
132
Mesh 38 
NamePlane.003
        Primitive 0
:
                
Number of Vertices472
                Number of Indices
1386
        Primitive 1
:
                
Number of Vertices176
                Number of Indices
288
        Primitive 2
:
                
Number of Vertices156
                Number of Indices
252
Mesh 39 
NameCylinder.004
        Primitive 0
:
                
Number of Vertices36
                Number of Indices
60
        Primitive 1
:
                
Number of Vertices132
                Number of Indices
132




Resources & Links


• glTF Loader/Dumper LINK

• glTF Tutorials/Code/Examples LINK





























Ray-Tracing with WebGPU kenwright WebGPU Development Cookbook - coding recipes for all your webgpu needs! WebGPU by Example: Fractals, Image Effects, Ray-Tracing, Procedural Geometry, 2D/3D, Particles, Simulations WebGPU Games WGSL 2d 3d interactive web-based fun learning WebGPU Compute WebGPU API - Owners WebGPU & WGSL Essentials: A Hands-On Approach to Interactive Graphics, Games, 2D Interfaces, 3D Meshes, Animation, Security and Production Kenwright graphics and animations using the webgpu api 12 week course kenwright learn webgpu api kenwright programming compute and graphics applications with html5 and webgpu api kenwright real-time 3d graphics with webgpu kenwright webgpu for dummies kenwright webgpu api develompent a quick start guide kenwright webgpu by example 2022 kenwright webgpu gems kenwright webgpu interactive compute and graphics visualization cookbook kenwright wgsl webgpu shading language cookbook kenwright WebGPU Shader Language Development: Vertex, Fragment, Compute Shaders for Programmers Kenwright wgsl webgpugems shading language cookbook kenwright WGSL Fundamentals book kenwright WebGPU Data Visualization Cookbook kenwright Special Effects Programming with WebGPU kenwright WebGPU Programming Guide: Interactive Graphics and Compute Programming with WebGPU & WGSL kenwright



 
Advert (Support Website)

 
 Visitor:
Copyright (c) 2002-2025 xbdev.net - All rights reserved.
Designated articles, tutorials and software are the property of their respective owners.