The teapot model data, in JSON format. The full file is 68K, and only the first part of each data field is shown here: { "vertexPositions" : [5.929688,4.125,0,5.387188,4.125,2.7475,5.2971,4.494141,... "vertexNormals" : [-0.966742,-0.255752,0,-0.893014,-0.256345,-0.369882,... "vertexTextureCoords" : [2,2,1.75,2,1.75,1.975,2,1.975,1.75,1.95,2,1.95,1.75,... "indices" : [0,1,2,2,3,0,3,2,4,4,5,3,5,4,6,6,7,5,7,6,8,8,9,7,1,10,11,11,2,1,... } ------------------------------------------------------------------------------------- The code from teapot.html that is needed to send the data from the teapot model to the shader program: vertexAttributeBuffer = gl.createBuffer(); normalAttributeBuffer = gl.createBuffer(); texCoordsAttributeBuffer = gl.createBuffer(); indexBuffer = gl.createBuffer(); gl.enableVertexAttribArray(vertexAttributeLocation); gl.enableVertexAttribArray(normalAttributeLocation); gl.enableVertexAttribArray(texCoordsAttributeLocation); gl.bindBuffer(gl.ARRAY_BUFFER,vertexAttributeBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(teapotData.vertexPositions), gl.STATIC_DRAW); gl.vertexAttribPointer(vertexAttributeLocation, 3, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER,normalAttributeBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(teapotData.vertexNormals), gl.STATIC_DRAW); gl.vertexAttribPointer(normalAttributeLocation, 3, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER,texCoordsAttributeBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(teapotData.vertexTextureCoords), gl.STATIC_DRAW); gl.vertexAttribPointer(texCoordsAttributeLocation, 2, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(teapotData.indices), gl.STATIC_DRAW); ------------------------------------------------------------------------------------- A simple OBJ file for a pyramid: v 1 0 1 v 1 0 -1 v -1 0 -1 v -1 0 1 v 0 1 0 f 5 4 1 f 5 1 2 f 5 2 3 f 5 3 4 f 1 4 3 2 ------------------------------------------------------------------------------------- A Blender OBJ export of a cube, with normal vectors: # Blender v2.61 (sub 0) OBJ File: '' # www.blender.org o Cube v 1.000000 -1.000000 -1.000000 v 1.000000 -1.000000 1.000000 v -1.000000 -1.000000 1.000000 v -1.000000 -1.000000 -1.000000 v 1.000000 1.000000 -0.999999 v 0.999999 1.000000 1.000001 v -1.000000 1.000000 1.000000 v -1.000000 1.000000 -1.000000 vn 0.000000 -1.000000 0.000000 vn 0.000000 1.000000 0.000000 vn 1.000000 0.000000 0.000000 vn -0.000000 -0.000000 1.000000 vn -1.000000 -0.000000 -0.000000 vn 0.000000 0.000000 -1.000000 s off f 1//1 2//1 3//1 4//1 f 5//2 8//2 7//2 6//2 f 1//3 5//3 6//3 2//3 f 2//4 6//4 7//4 3//4 f 3//5 7//5 8//5 4//5 f 5//6 1//6 4//6 8//6 ------------------------------------------------------------------------------------ The AJAX loader function from glutil3d-simple.js /** * Loads a file from a given url using AJAX. The AJAX code * that is used here should work in any browser that supports * WebGL, but not in Internet Explorer [except maybe new versions] * The first parameter is the url of the file to be loaded, presumably * a relative url. onSuccess is a function that will be called when * the AJAX requests succeeds; the first parameter to onSuccess is * the response text from the AJAX call (that is, the content loaded * from the url), and the second (optional) paramter is the XMLHttpRequest * object in case you want to get more information from that object. * onFailure is a function that will be called if the AJAX request * fails; the first parameter is an error message, and the second (optinal) * parameter is the XMLHttpRequest object. If timeLimit is given, * then the request will fail if there is no response within timeLimit * milliseconds. Only the url parameter is required; the others can * be missing or null. */ function ajaxLoad(url, onSuccess, onFailure, timeLimit) { var timeout = null; var request = new XMLHttpRequest(); // (doesn't work in IE) request.open("GET", url); request.onreadystatechange = function () { if (request.readyState == 4) { if (timeout) cancelTimeout(timeout); if (request.status == 200) { if (onSuccess) onSuccess(request.responseText, request); } else { if (onFailure) onFailure(request.statusText, request); } } } if (timeLimit) { setTimeout(function() { timeout = null; request.abort(); if (onFailure) onFailure("Request timed out", request); }, timeLimit); } request.send(); } --------------------------------------------------------------------------------- The call to ajaxLoad from teapot.html: ajaxLoad("teapot.json", function(responsetext){ try { teapotData = JSON.parse(responsetext); } catch (e) { document.getElementById('message').innerHTML = "Could not load model: Can't understand data that was received"; return; } document.getElementById('message').innerHTML = "Drag your mouse on the teapot to rotate it."; init(); }, function(errortext){ document.getElementById('message').innerHTML = "Could not load model: " + errortext; } ); ------------------------------------------------------------------------------- An example of my polyhedron export format, for Thursday's lab: { "vertices": [ [1.000000,-1.000000,-1.000000], [-1.000000,-1.000000,1.000000], [-1.000000,1.000000,-1.000000], [1.000000,1.000000,1.000000] ], "faces": [ [0,3,2], [3,0,1], [0,2,1], [2,3,1] ], "faceNormals": [ [-0.577350,-0.577350,0.577350], [-0.577350,0.577350,-0.577350], [0.577350,0.577350,0.577350], [0.577350,-0.577350,-0.577350] ] }