WebGL: Loading OBJ

←Back

Overview: Wavefront OBJ

OBJ is one of industry-standard 3D geometry formats, which is originally developed by Wavefront Technologies. OBJ file format stores 3D geometric data in ASCII text. OBJ format consists of 2 major sections. The first section is to define vertext attributes such as vertex positions (v), normals (vn) and texture coordinates (vt). The second part is the list of polygons (f) referencing the indices of the previous vertex attribute arrays.

OBJ also supports to partition the entire 3D model into multiple group. Each group can have separate material; color and texture map. These material definitions are stored in a separate file; .MTL.

This page shows how to parse the OBJ file and to render the 3D geometry data in WebGL. The comprehensive specification and documentation can be found at Paul Bourke's web page.

Loading OBJ File

In OBJ format, a list of unique vertex attributes is defined with specific keywords; v for positions, vn for normals and vt for texture coordinates.


# vertex position
v 0 1 2

# vertex normal
vn 0 0 1

# vertex tex coord
vt 0 1

After the definition of the list of vertex attributes, it defines a list of faces beginning with f keyword by indexing the previously defined vertex attributes. The vertex normal and texture coordinates are optional to define a face. However, the index of vertex positions are mandatory to define a face. All index values are 1-based. The face can be a triangle or polygon. If a face constructed by more than 3 vertices, it must be triangulated in WebGL.


# 4 different cases of face definitions
f 1  2  3              # with v only
f 1/1  2/2  3/3        # with v and vt
f 1//1  2//2  3//3     # with v and vn
f 1/1/1  2/2/2  3/3/3  # with v, vt and vn
...

ObjModel.js is a JavaScript class to parse an OBJ file, and to pass the vertex data to VBOs in WebGL. The core interfaces of ObjModel class are;

ObjModel
InterfaceDescription
read(url)Parse OBJ from URL, and return a Promise object
verticesFloat32Array to hold vertex positions
normalsFloat32Array to hold vertex normals
texCoordsFloat32Array to hold texture coordinates
indicesUnit16Array or Unit32Array to hold indices

A typical usage of ObjModel class follows;


// global object
gl = {};
...

// load OBJ file
gl.obj = new ObjModel();
gl.obj.read("debugger_50k.obj").then(obj =>
{
    // loaded OBJ successfully
    initVBO(obj);       // copy vertex data to VBO
    log(obj);           // print OBJ info
});

function initVBO(obj)
{
    gl.vbo = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, gl.vbo);
    // total # of bytes
    let dataSize = obj.vertices.byteLength + obj.normals.byteLength;
    gl.bufferData(gl.ARRAY_BUFFER, dataSize, gl.STATIC_DRAW);
    // copy vertices
    gl.bufferSubData(gl.ARRAY_BUFFER, 0, obj.vertices);
    // copy normals
    gl.bufferSubData(gl.ARRAY_BUFFER, obj.vertices.byteLength, obj.normals);

    gl.ibo = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.ibo);
    // copy indices
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, obj.indices, gl.STATIC_DRAW);
}
...

// draw VBO
gl.bindBuffer(gl.ARRAY_BUFFER, gl.vbo);
gl.vertexAttribPointer(program.attribute.position, 3, gl.FLOAT, false, 0, 0);
gl.vertexAttribPointer(program.attribute.normal, 3, gl.FLOAT, false, 0, gl.obj.normals.byteLength);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.ibo);
gl.drawElements(gl.TRIANGLES, gl.obj.indices.length, gl.obj.indexType, 0);
...

There is a C++ version of ObjModel class and ObjViewer application using OpenGL for Windows and macOS. You can download the source codes and binaries from the following link.
ObjViewer.zip
ObjViewer_mac.zip

ObjViewer for windows
ObjViewer for Windows
ObjViewer for macOS
ObjViewer for macOS

Example

This example is parsing and rendering an OBJ model with a default texture map if the OBJ file specifies texture coordinates. You can upload your own OBJ file or choose from the sample OBJ files.


decoration Fullscreen Demo: test_obj.html
decoration GitHub Repo: test_obj.html

←Back
 
Hide Comments
comments powered by Disqus