www.xbdev.net
xbdev - software development
Thursday April 2, 2026
Home | Contact | Support | OBJ 3D File Formats The bits and bytes...
     
 

OBJ 3D File Formats

The bits and bytes...

 


Visualization of the obj file format - minimal working code on left and the model on the right.
Visualization of the obj file format - minimal working code on left and the model on the right.


OBJ File Format (.obj)


The `obj` file format is a text based format.

Example of what the file format looks like in a text editor (triangle only)

triangle.obj
n># Equilateral Triangle OBJ File mtllib triangle.mtl o Triangle # Vertices (y=0 for flat triangle) v -0.5 0 -0.288675 # Left vertex v 0.5 0 -0.288675 # Right vertex v 0.0 0 0.577350 # Top vertex # Texture Coordinates (UV mapping) vt 0.0 0.0 # Bottom-left vt 1.0 0.0 # Bottom-right vt 0.5 1.0 # Top-center # Normals (facing up) vn 0 1 0 # Material usemtl DefaultMaterial # Face (counter-clockwise winding) f 1/1/1 2/2/1 3/3/1


The material information can be include inline in the obj - or included in an additional file with the '.mtl' extension. (This file is referenced in the obj using the
mtllib
tag):

triangle.mtl
n># Material for the triangle newmtl DefaultMaterial Ka 1.0 1.0 1.0 # Ambient color (white) Kd 0.8 0.2 0.2 # Diffuse color (red) Ks 0.5 0.5 0.5 # Specular highlights Ns 32 # Shininess (0-1000) illum 2 # Phong shading




Example obj file loader (in Javascript)


The following `obj` file loader is in a single file. Also converts non-triangle (quad) mesh elements to triangles.


Output for the example OBJ Loader - loads in a 3d model of a Stadium
Output for the example OBJ Loader - loads in a 3d model of a Stadium


bj = function(txt) { console.log('readObj...'); let objects = []; let materials = []; objects.push( { 'name':'test', 'v':[], 'vt':[], 'vn':[], 'f':[], 'usemtl':'' } ); let data = { 'v':[], 'n':[], 'f':[], 'm':[] }; txt = txt.replaceAll(' ', ' '); let lines = txt.split('\n'); console.log('num lines:', lines.length ); let curmat = -1; for (let i=0; i<lines.length; i++) { let line = lines[i]; line = line.trim() if ( line.length < 2 ) continue; if ( line[0] == '#' ) continue; let parts = line.split(' '); if ( parts.length < 1 ) continue; try{ switch( parts[0] ) { case 'usemtl': { let matname = parts[1]; if ( !materials.includes( matname ) ) { materials.push( matname ); } curmat = materials.indexOf( matname ); //console.log( 'curmat:', curmat ); } break; case 'v': // v 0.089624 1.419387 0.052847 { objects.reverse()[0].v.push( parts[1] ); objects.reverse()[0].v.push( parts[2] ); objects.reverse()[0].v.push( parts[3] ); } break; case 'vt': // vt 0.818181 0.000000 { objects.reverse()[0].vt.push( parts[1] ); objects.reverse()[0].vt.push( parts[2] ); } break; case 'vn': // vn 0.5499 0.7413 0.3847 { objects.reverse()[0].vn.push( parts[1] ); objects.reverse()[0].vn.push( parts[2] ); objects.reverse()[0].vn.push( parts[3] ); } break; case 'f': // f 1/1/1 14/2/1 13/3/1 { // f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3 ... // f v1//vn1 v2//vn2 v3//vn3 ... (double slashes) /* If you have 4 indices, e.g.: 0 1 2 3 The division into two triangles would be one with the first 3 indices, and one with the first, third, and fourth. In this example: 0 1 2 0 2 3 Let's try some ASCII art to illustrate this: 3-------2 | /| | / | | / | |/ | 0-------1 */ let i0 = parts[1].split('/')[0]-1; let i1 = parts[2].split('/')[0]-1; let i2 = parts[3].split('/')[0]-1; let i3 = parts.length ==4 ? undefined : (parts[4].split('/')[0]-1); let n0 = parts[1].split('/')[2]-1; let n1 = parts[2].split('/')[2]-1; let n2 = parts[3].split('/')[2]-1; let n3 = parts.length ==4 ? undefined : (parts[4].split('/')[2]-1); if ( parts[1].includes('//') ) { n0 = parts[1].split('//')[1]-1; n1 = parts[2].split('//')[1]-1; n2 = parts[3].split('//')[1]-1; n3 = parts.length == 4 ? undefined : (parts[4].split('//')[1]-1); } if ( i3 == undefined ) // triangles { let v = [] for (let g=0; g<3; g++) { let idx = [i0,i1,i2][g]; let x0 = objects.reverse()[0].v[ (3* idx)+0 ]; let y0 = objects.reverse()[0].v[ (3* idx)+1 ]; let z0 = objects.reverse()[0].v[ (3* idx)+2 ]; v.push( { x:x0, y:y0, z:z0 } ); } data.v.push( v[0].x ); data.v.push( v[0].y ); data.v.push( v[0].z ); data.v.push( v[1].x ); data.v.push( v[1].y ); data.v.push( v[1].z ); data.v.push( v[2].x ); data.v.push( v[2].y ); data.v.push( v[2].z ); data.m.push( curmat ); data.m.push( curmat ); data.m.push( curmat ); data.f.push( data.f.length ); data.f.push( data.f.length ); data.f.push( data.f.length ); let n = []; for (let g=0; g<[n0,n1,n2].length; g++) { let nx0 = objects.reverse()[0].vn[ 3*[n0,n1,n2][g]+0 ]; let ny0 = objects.reverse()[0].vn[ 3*[n0,n1,n2][g]+1 ]; let nz0 = objects.reverse()[0].vn[ 3*[n0,n1,n2][g]+2 ]; n.push( { x:nx0, y:ny0, z:nz0 } ); } data.n.push( n[0].x ); data.n.push( n[0].y ); data.n.push( n[0].z ); data.n.push( n[1].x ); data.n.push( n[1].y ); data.n.push( n[1].z ); data.n.push( n[2].x ); data.n.push( n[2].y ); data.n.push( n[2].z ); } else // quads { let v = []; for (let g=0; g<4; g++) { let idx = [i0,i1,i2,i3][g]; let x0 = objects.reverse()[0].v[ (3* idx)+0 ]; let y0 = objects.reverse()[0].v[ (3* idx)+1 ]; let z0 = objects.reverse()[0].v[ (3* idx)+2 ]; v.push( { x:x0, y:y0, z:z0 } ); } data.v.push( v[0].x ); data.v.push( v[0].y ); data.v.push( v[0].z ); data.v.push( v[1].x ); data.v.push( v[1].y ); data.v.push( v[1].z ); data.v.push( v[2].x ); data.v.push( v[2].y ); data.v.push( v[2].z ); data.m.push( curmat ); data.m.push( curmat ); data.m.push( curmat ); data.f.push( data.f.length ); data.f.push( data.f.length ); data.f.push( data.f.length ); data.v.push( v[0].x ); data.v.push( v[0].y ); data.v.push( v[0].z ); data.v.push( v[2].x ); data.v.push( v[2].y ); data.v.push( v[2].z ); data.v.push( v[3].x ); data.v.push( v[3].y ); data.v.push( v[3].z ); data.m.push( curmat ); data.m.push( curmat ); data.m.push( curmat ); data.f.push( data.f.length ); data.f.push( data.f.length ); data.f.push( data.f.length ); let n = []; for (let g=0; g<4; g++) { let idx = [n0,n1,n2,n3][g]; let nx0 = objects.reverse()[0].vn[ (3* idx)+0 ]; let ny0 = objects.reverse()[0].vn[ (3* idx)+1 ]; let nz0 = objects.reverse()[0].vn[ (3* idx)+2 ]; n.push( { x:nx0, y:ny0, z:nz0 } ); } data.n.push( n[0].x ); data.n.push( n[0].y ); data.n.push( n[0].z ); data.n.push( n[1].x ); data.n.push( n[1].y ); data.n.push( n[1].z ); data.n.push( n[2].x ); data.n.push( n[2].y ); data.n.push( n[2].z ); data.n.push( n[0].x ); data.n.push( n[0].y ); data.n.push( n[0].z ); data.n.push( n[2].x ); data.n.push( n[2].y ); data.n.push( n[2].z ); data.n.push( n[3].x ); data.n.push( n[3].y ); data.n.push( n[3].z ); } } break; }// end switch(..) }catch(e){ } }// for console.log( 'dump:', data.m.slice(0, 20) ); return [ data ]; }// readObj(..)



Resources and Examples


• WebGPU Example [LINK]

• Notebook `obj` to `json` Example [https://notebook.xbdev.net/index.php?page=objtojson&]

• Visualization using JS/Canvas (WebBook Lab) [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-2026 xbdev.net - All rights reserved.
Designated articles, tutorials and software are the property of their respective owners.