Wednesday February 5, 2025
Home
|
Contact
|
Support
|
OBJ 3D File Formats The bits and bytes...
<<
Random Page
Programming
C/C++
C# (with .net)
Win32/Win64
RegEx
Markdown (.md)
Python (.py)
Batch (.bat)
Programming XBOX & 360
XDK Tuts
NonXDK Tuts
OpenXDK Tuts
XNA with C#
Tutorials
Win32/Win64
DirectX3D (DirectX)
Maths of 3D
ASM..10101
Java
Physics
Visual Studio
Vulkan
Graphics
LaTeX
Data Mining & Machine Learning
AI
Fractals
Dual-Quaternions
Shaders
Vertex & Pixel Asm
Cg
Effect Files (fx)
GLSL (glsl)
WGSL (wgsl)
Executable File Formats
PE (.exe) Inside Out.
XBE XBOX Format
Android (.apk)
3D File Formats
Quake2 (.md2) Format
Quake3 (.md3) Format
Quake3 BSP (.bsp)
3DS Format (.3ds)
X DirectX (.x)
...
Image Formats
Bitmap(.bmp)
JPEG(.jpg)
DirectX DDS
Flash SWF
PNG(.png)
GIF(.gif)
WebP (.webp)
...
Internet Programming
WinSock
PHP
JavaScript
WebGL
WebXR
Retro Games
WebGPU
WebNN
Projects
Misc Demos
Notebook
Pixels
TexLive (LaTeX)
Crosswords
eNotes
Media
Quotes
Evolve
HSK
Slides
Trending
WordSearch
Links
Recommended Books
Donations (PayPal)
Contact
Advert (Support Website)
Amazon
OBJ 3D File Formats
The bits and bytes...
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:
Obj format overview
(
triangle only obj file
)
.
obj file
:
mtllib tree
.
mtl
o Icosphere
v 0.089624 1.419387 0.052847
vt 0.818181 0.000000
vn 0.5499 0.7413 0.3847
usemtl Material.001
f 1
/
1
/
1 14
/
2
/
1 13
/
3
/
1
.
mtl file
:
newmtl Material.001
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.217401 0.800000 0.176586
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
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
readObj
= 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&
]
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.