My favorites | English | Sign in

Faster apps faster - GWT 2.0 with Speed Tracer New!

Hello, Cube

This sample shows how to place an O3D area in a page and render a simple 3D shape—a spinning red cube.

Run hellocube.html

<!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">
<title>
Hello Cube: Getting started with O3D
</title>
<script type="text/javascript" src="o3djs/base.js"></script>
<script type="text/javascript">
o3djs.require('o3djs.util');
o3djs.require('o3djs.math');
o3djs.require('o3djs.rendergraph');

// 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);

  // Associate the positions Buffer with the StreamBank.
  streamBank.setVertexStream(
      g_o3d.Stream.POSITION, // semantic: This stream stores vertex positions
      0,                     // semantic index: First (and only) position stream
      positionsField,        // field: the field this stream uses.
      0);                    // start_index: How many elements to skip in the
                             //     field.

  // Associate the triangle indices Buffer with the primitive.
  cubePrimitive.indexBuffer = indexBuffer;

  return cubeShape;
}

/**
 * This method gets called every time O3D renders a frame.  Here's where
 * we update the cube's transform to make it spin.
 * @param {o3d.RenderEvent} renderEvent The render event object that gives
 *     us the elapsed time since the last time a frame was rendered.
 */
function renderCallback(renderEvent) {
  g_clock += renderEvent.elapsedTime * g_timeMult;
  // Rotate the cube around the Y axis.
  g_cubeTransform.identity();
  g_cubeTransform.rotateY(2.0 * g_clock);
}


/**
 * Creates the client area.
 */
function init() {
  o3djs.util.makeClients(initStep2);
}

/**
 * Initializes O3D, creates the cube and sets up the transform and
 * render graphs.
 * @param {Array} clientElements Array of o3d object elements.
 */
function initStep2(clientElements) {
  // Initializes global variables and libraries.
  var o3dElement = clientElements[0];
  g_client = o3dElement.client;
  g_o3d = o3dElement.o3d;
  g_math = o3djs.math;

  // Initialize O3D sample libraries.
  o3djs.base.init(o3dElement);

  // Create a pack to manage the objects created.
  g_pack = g_client.createPack();

  // Create the render graph for a view.
  var viewInfo = o3djs.rendergraph.createBasicView(
      g_pack,
      g_client.root,
      g_client.renderGraphRoot);

  // Set up a simple orthographic view.

  viewInfo.drawContext.projection = g_math.matrix4.perspective(
      g_math.degToRad(30), // 30 degree fov.
      g_client.width / g_client.height,
      1,                  // Near plane.
      5000);              // Far plane.

  // Set up our view transformation to look towards the world origin where the
  // cube is located.
  viewInfo.drawContext.view = g_math.matrix4.lookAt([0, 1, 5],  // eye
                                            [0, 0, 0],  // target
                                            [0, 1, 0]); // up

  // Create an Effect object and initialize it using the shaders from the
  // text area.
  var redEffect = g_pack.createObject('Effect');
  var shaderString = document.getElementById('effect').value;
  redEffect.loadFromFXString(shaderString);

  // Create a Material for the mesh.
  var redMaterial = g_pack.createObject('Material');

  // Set the material's drawList.
  redMaterial.drawList = viewInfo.performanceDrawList;

  // Apply our effect to this material. The effect tells the 3D hardware
  // which shaders to use.
  redMaterial.effect = redEffect;

  // Create the Shape for the cube mesh and assign its material.
  var cubeShape = createCube(redMaterial);

  // Create a new transform and parent the Shape under it.
  g_cubeTransform = g_pack.createObject('Transform');
  g_cubeTransform.addShape(cubeShape);

  // Parent the cube's transform to the client root.
  g_cubeTransform.parent = g_client.root;

  // Generate the draw elements for the cube shape.
  cubeShape.createDrawElements(g_pack, null);

  // Set our render callback for animation.
  // This sets a function to be executed every time a frame is rendered.
  g_client.setRenderCallback(renderCallback);

  g_finished = true;  // for selenium testing.
}

/**
 * Removes any callbacks so they don't get called after the page has unloaded.
 */
function uninit() {
  if (g_client) {
    g_client.cleanup();
  }
}

</script>
</head>
<body>
<h1>Hello Cube</h1>
This example shows how to display a spinning red cube in O3D.
<br/>


<!-- Start of O3D plugin -->
<div id="o3d" style="width: 600px; height: 600px;"></div>
<!-- End of O3D plugin -->

<!-- Don't render the textarea -->
<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 -->
</div>
</body>
</html>