Security News
RubyGems.org Adds New Maintainer Role
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
webgl-obj-loader
Advanced tools
A simple script to help bring OBJ models to your WebGL world. I originally wrote this script for my CS Graphics class so that we didn't have to only have cubes and spheres for models in order to learn WebGL. At the time, the only sort of model loader for WebGL was Mr. Doob's ThreeJS. And in order to use the loaders you had to use the entire framework (or do some very serious hacking and duct-taping in order get the model information). My main focus in creating this loader was to easily allow importing models without having to have special knowledge of a 3D graphics program (like Blender) while keeping it low-level enough so that the focus was on learning WebGL rather than learning some framework.
The main Mesh class. The constructor will parse through the OBJ file data
and collect the vertex, vertex normal, texture, and face information. This
information can then be used later on when creating your VBOs. Look at the
initMeshBuffers
source for an example of how to use the newly created Mesh
verts = [1, -1, 1, ...]
, verts[0] is x
, verts[1] is y
, and verts[2] is z
. Continuing on, verts[3]
would be the beginning of the next vertex: its x component. This is in preparation for using gl.ELEMENT_ARRAY_BUFFER
for the gl.drawElements
call.vertices
.s
and t
(or u
and v
) coordinates for this mesh's texture. It is flat just like vertices
except it goes by groups of 2 instead of 3.indices[42]
could contain the number 38
. This would then be used internally by WebGL on all three of the above arrays telling which vertex, normal, and texture coords to use: vertices[38]
, vertexNormals[38]
, and textures[38]
.A simple example:
In your index.html
file:
<html>
<head>
<script type="text/plain" id="my_cube.obj">
####
#
# OBJ File Generated by Blender
#
####
o my_cube.obj
v 1 1 1
v -1 1 1
v -1 -1 1
v 1 -1 1
v 1 1 -1
v -1 1 -1
v -1 -1 -1
v 1 -1 -1
vn 0 0 1
vn 1 0 0
vn -1 0 0
vn 0 0 -1
vn 0 1 0
vn 0 -1 0
f 1//1 2//1 3//1
f 3//1 4//1 1//1
f 5//2 1//2 4//2
f 4//2 8//2 5//2
f 2//3 6//3 7//3
f 7//3 3//3 2//3
f 7//4 8//4 5//4
f 5//4 6//4 7//4
f 5//5 6//5 2//5
f 2//5 1//5 5//5
f 8//6 4//6 3//6
f 3//6 7//6 8//6
</script>
</head>
</html>
And in your app.js
:
var gl = canvas.getContext('webgl');
var objStr = document.getElementById('my_cube.obj').innerHTML;
var mesh = new OBJ.Mesh(objStr);
// use the included helper function to initialize the VBOs
// if you don't want to use this function, have a look at its
// source to see how to use the Mesh instance.
OBJ.initMeshBuffers(gl, mesh);
// have a look at the initMeshBuffers docs for an exmample of how to
// render the model at this point
Takes in a JS Object of mesh_name
, '/url/to/OBJ/file'
pairs and a callback
function. Each OBJ file will be ajaxed in and automatically converted to
an OBJ.Mesh. When all files have successfully downloaded the callback
function provided will be called and passed in an object containing
the newly created meshes.
Note: In order to use this function as a way to download meshes, a webserver of some sort must be used.
nameAndURLs: an object where the key is the name of the mesh and the value is the url to that mesh's OBJ file
completionCallback: should contain a function that will take one parameter: an object array where the keys will be the unique object name and the value will be a Mesh object
meshes: In case other meshes are loaded separately or if a previously declared variable is desired to be used, pass in a (possibly empty) json object of the pattern: { 'mesh_name': OBJ.Mesh }
A simple example:
var app = {};
app.meshes = {};
var gl = document.getElementById('mycanvas').getContext('webgl');
function webGLStart(meshes){
app.meshes = meshes;
// initialize the VBOs
OBJ.initMeshBuffers(gl, app.meshes.suzanne);
OBJ.initMeshBuffers(gl, app.meshes.sphere);
... other cool stuff ...
// refer to the initMeshBuffers docs for an example of
// how to render the mesh to the screen after calling
// initMeshBuffers
}
window.onload = function(){
OBJ.downloadMeshes({
'suzanne': 'models/suzanne.obj', // located in the models folder on the server
'sphere': 'models/sphere.obj'
}, webGLStart);
}
Takes in the WebGL context and a Mesh, then creates and appends the buffers to the mesh object as attributes.
gl WebGLRenderingContext the canvas.getContext('webgl')
context instance
mesh Mesh a single OBJ.Mesh
instance
The newly created mesh attributes are:
Attrbute | Description |
---|---|
normalBuffer | contains the model's Vertex Normals |
normalBuffer.itemSize | set to 3 items |
normalBuffer.numItems | the total number of vertex normals |
textureBuffer | contains the model's Texture Coordinates |
textureBuffer.itemSize | set to 2 items (or 3 if W texture coord is enabled) |
textureBuffer.numItems | the number of texture coordinates |
vertexBuffer | contains the model's Vertex Position Coordinates (does not include w) |
vertexBuffer.itemSize | set to 3 items |
vertexBuffer.numItems | the total number of vertices |
indexBuffer | contains the indices of the faces |
indexBuffer.itemSize | is set to 1 |
indexBuffer.numItems | the total number of indices |
A simple example (a lot of steps are missing, so don't copy and paste):
var gl = canvas.getContext('webgl'),
var mesh = new OBJ.Mesh(obj_file_data);
// compile the shaders and create a shader program
var shaderProgram = gl.createProgram();
// compilation stuff here
...
// make sure you have vertex, vertex normal, and texture coordinate
// attributes located in your shaders and attach them to the shader program
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");
gl.enableVertexAttribArray(shaderProgram.vertexNormalAttribute);
shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
// create and initialize the vertex, vertex normal, and texture coordinate buffers
// and save on to the mesh object
OBJ.initMeshBuffers(gl, mesh);
// now to render the mesh
gl.bindBuffer(gl.ARRAY_BUFFER, mesh.vertexBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, mesh.vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
// it's possible that the mesh doesn't contain
// any texture coordinates (e.g. suzanne.obj in the development branch).
// in this case, the texture vertexAttribArray will need to be disabled
// before the call to drawElements
if(!mesh.textures.length){
gl.disableVertexAttribArray(shaderProgram.textureCoordAttribute);
}
else{
// if the texture vertexAttribArray has been previously
// disabled, then it needs to be re-enabled
gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
gl.bindBuffer(gl.ARRAY_BUFFER, mesh.textureBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, mesh.textureBuffer.itemSize, gl.FLOAT, false, 0, 0);
}
gl.bindBuffer(gl.ARRAY_BUFFER, mesh.normalBuffer);
gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, mesh.normalBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.mesh.indexBuffer);
gl.drawElements(gl.TRIANGLES, model.mesh.indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
Deletes the mesh's buffers, which you would do when deleting an object from a scene so that you don't leak video memory. Excessive buffer creation and deletion leads to video memory fragmentation. Beware.
npm install webgl-obj-loader
var fs = require('fs');
var OBJ = require('webgl-obj-loader');
var meshPath = './development/models/sphere.obj';
var opt = { encoding: 'utf8' };
fs.readFile(meshPath, opt, function (err, data){
if (err) return console.error(err);
var mesh = new OBJ.Mesh(data);
});
Thanks to mentos1386 for the webpack-obj-loader!
http://frenchtoast747.github.com/webgl-obj-loader/
This demo is the same thing inside of the gh-pages branch. Do a git checkout gh-pages
inside of the webgl-obj-loader directory to see how the OBJ loader is used in a project.
2.0.0
indicesPerMaterial
has been removed in favor of always providing the indices per material.
mesh.indices
holding an array of arrays of numbers, mesh.indicesPerMaterial
will now hold the indices where the top
level array index is the index of the material and the inner arrays are the indices for that material.1.1.0
1.0.1
enableWTextureCoord: true
in the options parameter of the Mesh
class.1.0.0
f 1/1
fetch()
API which utilizes
promises.0.1.1
0.1.0
downloadMeshes
no longer requires jQuery to ajax in the OBJ files.OBJ
0.0.3
0.0.2
0.0.1
FAQs
A simple OBJ model loader to help facilitate the learning of WebGL
We found that webgl-obj-loader demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.
Security News
Research
Socket's threat research team has detected five malicious npm packages targeting Roblox developers, deploying malware to steal credentials and personal data.