Created
April 22, 2009 15:47
-
-
Save dru/99866 to your computer and use it in GitHub Desktop.
Pure & simple O3D example. Without helper js libraries.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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