Skip to content

Instantly share code, notes, and snippets.

@dru
Created April 22, 2009 15:47
Show Gist options
  • Save dru/99866 to your computer and use it in GitHub Desktop.
Save dru/99866 to your computer and use it in GitHub Desktop.
Pure & simple O3D example. Without helper js libraries.
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<object id="o3d" type="application/vnd.o3d.auto" style="width: 500px; height: 500px; "></object>
<div style="display:none">
<!-- Start of effect -->
<textarea id="effect">
// World View Projection matrix that will transform the input vertices
// to screen space.
float4x4 worldViewProjection : WorldViewProjection;
// input parameters for our vertex shader
struct VertexShaderInput {
float4 position : POSITION;
};
// input parameters for our pixel shader
struct PixelShaderInput {
float4 position : POSITION;
};
/**
* The vertex shader simply transforms the input vertices to screen space.
*/
PixelShaderInput vertexShaderFunction(VertexShaderInput input) {
PixelShaderInput output;
// Multiply the vertex positions by the worldViewProjection matrix to
// transform them to screen space.
output.position = mul(input.position, worldViewProjection);
return output;
}
/**
* This pixel shader just returns the color red.
*/
float4 pixelShaderFunction(PixelShaderInput input): COLOR {
return float4(1, 0, 0, 1); // Red.
}
// Here we tell our effect file *which* functions are
// our vertex and pixel shaders.
// #o3d VertexShaderEntryPoint vertexShaderFunction
// #o3d PixelShaderEntryPoint pixelShaderFunction
// #o3d MatrixLoadOrder RowMajor
</textarea>
<!-- End of effect -->
<script type="text/javascript">
// Events
// Run the init() function once the page has finished loading.
// Run the uninit() function when the page has is unloaded.
window.onload = init;
window.onunload = uninit;
// global variables
var g_o3d;
var g_math;
var g_client;
var g_pack;
var g_clock = 0;
var g_timeMult = 1;
var g_cubeTransform;
var g_finished = false; // for selenium testing
/**
* Creates a O3D shape representing a cube. The shape consists of
* a single primitive with eight vertices and 12 triangles (two for each face
* of the cube).
* @param {o3d.Material} material the material used by the primitive.
* @return {o3d.Shape} The Shape object created.
*/
function createCube(material) {
// Create a Shape object for the mesh.
var cubeShape = g_pack.createObject('Shape');
// Create the Primitive that will contain the geometry data for
// the cube.
var cubePrimitive = g_pack.createObject('Primitive');
// Create a StreamBank to hold the streams of vertex data.
var streamBank = g_pack.createObject('StreamBank');
// Assign the material that was passed in to the primitive.
cubePrimitive.material = material;
// Assign the Primitive to the Shape.
cubePrimitive.owner = cubeShape;
// Assign the StreamBank to the Primitive.
cubePrimitive.streamBank = streamBank;
// The cube is made of 12 triangles. There's eight vertices in total which
// are shared between the face triangles.
cubePrimitive.primitiveType = g_o3d.Primitive.TRIANGLELIST;
cubePrimitive.numberPrimitives = 12; // 12 triangles
cubePrimitive.numberVertices = 8; // 8 vertices in total
// Create a javascript array that stores the X, Y and Z coordinates of each
// of the 8 corners of the cube.
var positionArray = [
-0.5, -0.5, 0.5, // vertex 0
0.5, -0.5, 0.5, // vertex 1
-0.5, 0.5, 0.5, // vertex 2
0.5, 0.5, 0.5, // vertex 3
-0.5, 0.5, -0.5, // vertex 4
0.5, 0.5, -0.5, // vertex 5
-0.5, -0.5, -0.5, // vertex 6
0.5, -0.5, -0.5 // vertex 7
];
// The following array defines how vertices are to be put together to form
// the triangles that make up the cube's faces. In the index array, every
// three elements define a triangle. So for example vertices 0, 1 and 2
// make up the first triangle, vertices 2, 1 and 3 the second one, etc.
var indicesArray = [
0, 1, 2, // face 1
2, 1, 3,
2, 3, 4, // face 2
4, 3, 5,
4, 5, 6, // face 3
6, 5, 7,
6, 7, 0, // face 4
0, 7, 1,
1, 7, 3, // face 5
3, 7, 5,
6, 0, 4, // face 6
4, 0, 2
];
// Create buffers containing the vertex data.
var positionsBuffer = g_pack.createObject('VertexBuffer');
var positionsField = positionsBuffer.createField('FloatField', 3);
positionsBuffer.set(positionArray);
var indexBuffer = g_pack.createObject('IndexBuffer');
indexBuffer.set(indicesArray);
streamBank.setVertexStream(g_o3d.Stream.POSITION, 0, positionsField, 0);
cubePrimitive.indexBuffer = indexBuffer;
return cubeShape;
}
function degToRad(degrees) {
return degrees * Math.PI / 180;
};
function normalize(a) {
var r = [];
var n = 0.0;
var aLength = a.length;
for (var i = 0; i < aLength; ++i)
n += a[i] * a[i];
n = Math.sqrt(n);
for (var i = 0; i < aLength; ++i)
r[i] = a[i] / n;
return r;
};
function subVector(a, b) {
var r = [];
var aLength = a.length;
for (var i = 0; i < aLength; ++i)
r[i] = a[i] - b[i];
return r;
};
function cross(a, b) {
return [a[1] * b[2] - a[2] * b[1],
a[2] * b[0] - a[0] * b[2],
a[0] * b[1] - a[1] * b[0]];
};
function perspective(angle, aspect, near, far) {
var f = Math.tan(0.5 * (Math.PI - angle));
var range = near - far;
return [
[f / aspect, 0, 0, 0],
[0, f, 0, 0],
[0, 0, far / range, -1],
[0, 0, near * far / range, 0]
];
};
function inverse(m) {
var tmp_0 = m[2][2] * m[3][3];
var tmp_1 = m[3][2] * m[2][3];
var tmp_2 = m[1][2] * m[3][3];
var tmp_3 = m[3][2] * m[1][3];
var tmp_4 = m[1][2] * m[2][3];
var tmp_5 = m[2][2] * m[1][3];
var tmp_6 = m[0][2] * m[3][3];
var tmp_7 = m[3][2] * m[0][3];
var tmp_8 = m[0][2] * m[2][3];
var tmp_9 = m[2][2] * m[0][3];
var tmp_10 = m[0][2] * m[1][3];
var tmp_11 = m[1][2] * m[0][3];
var tmp_12 = m[2][0] * m[3][1];
var tmp_13 = m[3][0] * m[2][1];
var tmp_14 = m[1][0] * m[3][1];
var tmp_15 = m[3][0] * m[1][1];
var tmp_16 = m[1][0] * m[2][1];
var tmp_17 = m[2][0] * m[1][1];
var tmp_18 = m[0][0] * m[3][1];
var tmp_19 = m[3][0] * m[0][1];
var tmp_20 = m[0][0] * m[2][1];
var tmp_21 = m[2][0] * m[0][1];
var tmp_22 = m[0][0] * m[1][1];
var tmp_23 = m[1][0] * m[0][1];
var t0 = (tmp_0 * m[1][1] + tmp_3 * m[2][1] + tmp_4 * m[3][1]) -
(tmp_1 * m[1][1] + tmp_2 * m[2][1] + tmp_5 * m[3][1]);
var t1 = (tmp_1 * m[0][1] + tmp_6 * m[2][1] + tmp_9 * m[3][1]) -
(tmp_0 * m[0][1] + tmp_7 * m[2][1] + tmp_8 * m[3][1]);
var t2 = (tmp_2 * m[0][1] + tmp_7 * m[1][1] + tmp_10 * m[3][1]) -
(tmp_3 * m[0][1] + tmp_6 * m[1][1] + tmp_11 * m[3][1]);
var t3 = (tmp_5 * m[0][1] + tmp_8 * m[1][1] + tmp_11 * m[2][1]) -
(tmp_4 * m[0][1] + tmp_9 * m[1][1] + tmp_10 * m[2][1]);
var d = 1.0 / (m[0][0] * t0 + m[1][0] * t1 + m[2][0] * t2 + m[3][0] * t3);
return [[d * t0, d * t1, d * t2, d * t3],
[d * ((tmp_1 * m[1][0] + tmp_2 * m[2][0] + tmp_5 * m[3][0]) -
(tmp_0 * m[1][0] + tmp_3 * m[2][0] + tmp_4 * m[3][0])),
d * ((tmp_0 * m[0][0] + tmp_7 * m[2][0] + tmp_8 * m[3][0]) -
(tmp_1 * m[0][0] + tmp_6 * m[2][0] + tmp_9 * m[3][0])),
d * ((tmp_3 * m[0][0] + tmp_6 * m[1][0] + tmp_11 * m[3][0]) -
(tmp_2 * m[0][0] + tmp_7 * m[1][0] + tmp_10 * m[3][0])),
d * ((tmp_4 * m[0][0] + tmp_9 * m[1][0] + tmp_10 * m[2][0]) -
(tmp_5 * m[0][0] + tmp_8 * m[1][0] + tmp_11 * m[2][0]))],
[d * ((tmp_12 * m[1][3] + tmp_15 * m[2][3] + tmp_16 * m[3][3]) -
(tmp_13 * m[1][3] + tmp_14 * m[2][3] + tmp_17 * m[3][3])),
d * ((tmp_13 * m[0][3] + tmp_18 * m[2][3] + tmp_21 * m[3][3]) -
(tmp_12 * m[0][3] + tmp_19 * m[2][3] + tmp_20 * m[3][3])),
d * ((tmp_14 * m[0][3] + tmp_19 * m[1][3] + tmp_22 * m[3][3]) -
(tmp_15 * m[0][3] + tmp_18 * m[1][3] + tmp_23 * m[3][3])),
d * ((tmp_17 * m[0][3] + tmp_20 * m[1][3] + tmp_23 * m[2][3]) -
(tmp_16 * m[0][3] + tmp_21 * m[1][3] + tmp_22 * m[2][3]))],
[d * ((tmp_14 * m[2][2] + tmp_17 * m[3][2] + tmp_13 * m[1][2]) -
(tmp_16 * m[3][2] + tmp_12 * m[1][2] + tmp_15 * m[2][2])),
d * ((tmp_20 * m[3][2] + tmp_12 * m[0][2] + tmp_19 * m[2][2]) -
(tmp_18 * m[2][2] + tmp_21 * m[3][2] + tmp_13 * m[0][2])),
d * ((tmp_18 * m[1][2] + tmp_23 * m[3][2] + tmp_15 * m[0][2]) -
(tmp_22 * m[3][2] + tmp_14 * m[0][2] + tmp_19 * m[1][2])),
d * ((tmp_22 * m[2][2] + tmp_16 * m[0][2] + tmp_21 * m[1][2]) -
(tmp_20 * m[1][2] + tmp_23 * m[2][2] + tmp_17 * m[0][2]))]];
};
function lookAt(eye, target, up) {
var vz = normalize(subVector(eye, target).slice(0, 3)).concat(0);
var vx = normalize(cross(up, vz)).concat(0);
var vy = cross(vz, vx).concat(0);
return inverse([vx, vy, vz, eye.concat(1)]);
};
function renderCallback(renderEvent) {
g_clock += renderEvent.elapsedTime * g_timeMult;
g_cubeTransform.identity();
g_cubeTransform.rotateY(2.0 * g_clock);
}
function init() {
var o3dElement = document.o3d;
g_client = o3dElement.client;
g_o3d = o3dElement.o3d;
g_pack = g_client.createPack();
var viewport = g_pack.createObject('Viewport');
var clearBuffer = g_pack.createObject('ClearBuffer');
clearBuffer.clearColor = [0.0, 0.0, 0.0, 1.0];
clearBuffer.parent = viewport;
var treeTraversal = g_pack.createObject('TreeTraversal');
treeTraversal.parent = viewport;
treeTraversal.transform = g_client.root;
var performanceState = g_pack.createObject('State');
performanceState.getStateParam('ColorWriteEnable').value = 7;
var performanceStateSet = g_pack.createObject('StateSet');
performanceStateSet.state = performanceState;
performanceStateSet.parent = viewport;
var performanceDrawList = g_pack.createObject('DrawList');
var performanceDrawPass = g_pack.createObject('DrawPass');
performanceDrawPass.drawList = performanceDrawList;
performanceDrawPass.parent = performanceStateSet;
var drawContext = g_pack.createObject('DrawContext');
treeTraversal.registerDrawList(performanceDrawList, drawContext, true);
viewport.parent = g_client.renderGraphRoot;
drawContext.projection = perspective(
degToRad(30), // 30 degree fov.
g_client.width / g_client.height,
1, // Near plane.
5000); // Far plane.
drawContext.view = lookAt([0, 1, 5], // eye
[0, 0, 0], // target
[0, 1, 0]); // up
var redEffect = g_pack.createObject('Effect');
var shaderString = document.getElementById('effect').value;
redEffect.loadFromFXString(shaderString);
var redMaterial = g_pack.createObject('Material');
redMaterial.drawList = performanceDrawList;
redMaterial.effect = redEffect;
var cubeShape = createCube(redMaterial);
g_cubeTransform = g_pack.createObject('Transform');
g_cubeTransform.addShape(cubeShape);
g_cubeTransform.parent = g_client.root;
cubeShape.createDrawElements(g_pack, null);
g_client.setRenderCallback(renderCallback);
}
function uninit() {
if (g_client) {
g_client.cleanup();
}
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment