| Index: samples/siteswap/siteswap.html
|
| ===================================================================
|
| --- samples/siteswap/siteswap.html (revision 0)
|
| +++ samples/siteswap/siteswap.html (revision 0)
|
| @@ -0,0 +1,323 @@
|
| +<!-- @@REWRITE(insert html-copyright) -->
|
| +<!--
|
| +O3D Siteswap animator
|
| +@@REWRITE(delete-start)
|
| +Author: Eric Uhrhane (ericu@google.com)
|
| +@@REWRITE(delete-end)
|
| +-->
|
| +<!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>
|
| + Site Swap Simulator
|
| +</title>
|
| +<style type="text/css">
|
| + html, body {
|
| + height: 100%;
|
| + margin: 0;
|
| + padding: 0;
|
| + border: none;
|
| + }
|
| +</style>
|
| +<!-- Our javascript code -->
|
| +<script type="text/javascript" src="../o3djs/base.js"></script>
|
| +<script type="text/javascript" src="siteswap.js"></script>
|
| +<script type="text/javascript" src="math.js"></script>
|
| +<script type="text/javascript" src="animation.js"></script>
|
| +<script type="text/javascript">
|
| +
|
| +o3djs.require('o3djs.util');
|
| +
|
| +// Set up the client area.
|
| +function init() {
|
| + o3djs.util.setMainEngine(o3djs.util.Engine.V8);
|
| + o3djs.util.addScriptUri(''); // Allow V8 to load scripts in the cwd.
|
| + o3djs.util.makeClients(initStep2);
|
| + setUpSelection();
|
| +}
|
| +
|
| +// Select the entire input pattern, so that the user can just type.
|
| +function setUpSelection() {
|
| + var input_pattern = document.getElementById('input_pattern');
|
| + input_pattern.focus();
|
| + input_pattern.selectionStart = 0;
|
| + input_pattern.selectionEnd = input_pattern.value.length;
|
| +}
|
| +
|
| +/*
|
| + * Wrappers to enable button presses to call through to the embedded V8 engine.
|
| + */
|
| +
|
| +// Update whether we're animating or frozen based on the value of the checkbox.
|
| +function updateAnimatingWrapper() {
|
| + g.o3dElement.eval('updateAnimating()');
|
| +}
|
| +
|
| +// Compute a new pattern.
|
| +function onComputePatternWrapper() {
|
| + g.o3dElement.eval('onComputePattern()');
|
| +}
|
| +
|
| +// Adjust the view matrix to the new proportions of the plugin window.
|
| +// TODO: Switch to using the resize event once that's checked in.
|
| +function onResizeWrapper() {
|
| + g.o3dElement.eval('onResize()');
|
| +}
|
| +window.onresize = onResizeWrapper;
|
| +
|
| +// Clean up all our callbacks, etc.
|
| +function cleanupWrapper() {
|
| + if (g && g.o3dElement) {
|
| + g.o3dElement.eval('cleanup()');
|
| + }
|
| +}
|
| +
|
| +// The point of this function is to suppress form submit; we want to use the
|
| +// pattern entered when the user hits return, not submit the page to the
|
| +// webserver.
|
| +function suppressSubmit(event) {
|
| + onComputePatternWrapper(); // TODO: This suppresses form autocomplete storage.
|
| + return false;
|
| +}
|
| +
|
| +</script>
|
| +</head>
|
| +<body onload="init()" onunload="cleanupWrapper()">
|
| +<table width="100%" style="height:100%;">
|
| + <tr>
|
| + <td>
|
| + <h1>Juggler</h1>
|
| + This sample displays a site-swap juggling pattern with animation done by
|
| + a vertex shader.
|
| + <form name="the_form" onsubmit="return suppressSubmit(event)">
|
| + <table>
|
| + <tr>
|
| + <td>
|
| + <table>
|
| + <tr>
|
| + <td>
|
| + <input
|
| + type="radio"
|
| + name="radio_group_hands"
|
| + value="1"
|
| + onclick=onComputePatternWrapper()>
|
| + 1 Hand<br>
|
| + <input
|
| + type="radio"
|
| + name="radio_group_hands"
|
| + value="2"
|
| + onclick=onComputePatternWrapper()
|
| + checked>
|
| + 2 Hands<br>
|
| + <input
|
| + type="radio"
|
| + name="radio_group_hands"
|
| + value="3"
|
| + onclick=onComputePatternWrapper()>
|
| + 3 Hands<br>
|
| + <input
|
| + type="radio"
|
| + name="radio_group_hands"
|
| + value="4"
|
| + onclick=onComputePatternWrapper()>
|
| + 4 Hands<br>
|
| + </td>
|
| + <td>
|
| + <input type="text" name="input_pattern" id="input_pattern"
|
| + value="3 4 5">
|
| + </td>
|
| + <td>
|
| + <input type="checkbox" name="check_box" checked
|
| + onclick=updateAnimatingWrapper()>Animate
|
| + <input
|
| + type="checkbox"
|
| + name="pair_hands"
|
| + onclick=onComputePatternWrapper();
|
| + >Pair Hands
|
| + </td>
|
| + <td>
|
| + <input type="button" name="computePattern"
|
| + value="Compute Pattern"
|
| + onclick=onComputePatternWrapper()>
|
| + </td>
|
| + </tr>
|
| + </table>
|
| + </td>
|
| + <td>
|
| + </td>
|
| + </tr>
|
| + </table>
|
| + </form>
|
| + <table id="container" width="90%" style="height:70%;">
|
| + <tr>
|
| + <td height="100%">
|
| + <!-- Start of g.o3d plugin -->
|
| + <div id="o3d" style="width: 100%; height: 100%;"></div>
|
| + <!-- End of g.o3d plugin -->
|
| + </td>
|
| + </tr>
|
| + </table>
|
| + <!-- a simple way to get a multiline string -->
|
| + <textarea id="shader" name="shader" cols="80" rows="20"
|
| + style="display: none;">
|
| +// the 4x4 world view projection matrix
|
| +float4x4 worldViewProjection : WorldViewProjection;
|
| +
|
| +// positions of the light and camera
|
| +float3 light_pos;
|
| +float3 camera_pos;
|
| +
|
| +// phong lighting properties of the material
|
| +float4 light_ambient;
|
| +float4 light_diffuse;
|
| +float4 light_specular;
|
| +
|
| +// shininess of the material (for specular lighting)
|
| +float shininess;
|
| +
|
| +// time for animation
|
| +float time;
|
| +
|
| +// coefficients for a t^2 + b t + c for each of x, y, z
|
| +float3 coeff_a;
|
| +float3 coeff_b;
|
| +float3 coeff_c;
|
| +
|
| +// flag and coefficient for optional LERP with rate t * coeff_lerp;
|
| +float coeff_lerp;
|
| +
|
| +// coefficients for a t^2 + b t + c for each of x, y, z, for optional LERP
|
| +float3 coeff_l_a;
|
| +float3 coeff_l_b;
|
| +float3 coeff_l_c;
|
| +
|
| +// coefficients for d sin(f t) + e cos(e t) for each of x, y, z
|
| +float3 coeff_d;
|
| +float3 coeff_e;
|
| +float3 coeff_f;
|
| +
|
| +// to be subtracted from time to get the t for the above equation
|
| +float time_base;
|
| +
|
| +// input parameters for our vertex shader
|
| +struct VertexShaderInput {
|
| + float4 position : POSITION;
|
| + float3 normal : NORMAL;
|
| + float4 color : COLOR;
|
| +};
|
| +
|
| +// input parameters for our pixel shader
|
| +// also the output parameters for our vertex shader
|
| +struct PixelShaderInput {
|
| + float4 position : POSITION;
|
| + float3 lightVector : TEXCOORD0;
|
| + float3 normal : TEXCOORD1;
|
| + float3 viewPosition : TEXCOORD2;
|
| + float4 color : COLOR;
|
| +};
|
| +
|
| +/**
|
| + * Vertex Shader - vertex shader for phong illumination
|
| + */
|
| +PixelShaderInput vertexShaderFunction(VertexShaderInput input) {
|
| + /**
|
| + * We use the standard phong illumination equation here.
|
| + * We restrict (clamp) the dot products so that we
|
| + * don't get any negative values.
|
| + * All vectors are normalized for proper calculations.
|
| + *
|
| + * The output color is the summation of the
|
| + * ambient, diffuse, and specular contributions.
|
| + *
|
| + * Note that we have to transform each vertex and normal
|
| + * by the world view projection matrix first.
|
| + */
|
| + PixelShaderInput output;
|
| +
|
| + float t = time - time_base;
|
| + float3 offset = float3(0, 0, 0);
|
| + offset += t * t * coeff_a + t * coeff_b + coeff_c;
|
| + offset += coeff_d * sin(t * coeff_f);
|
| + offset += coeff_e * cos(t * coeff_f);
|
| +
|
| + float3 lerpOffset = t * t * coeff_l_a + t * coeff_l_b + coeff_l_c;
|
| + if (coeff_lerp > 0) {
|
| + float rate = min(coeff_lerp * t, 1);
|
| + float3 lerpVector = float3(rate, rate, rate);
|
| + offset = lerp(offset, lerpOffset, lerpVector);
|
| + } else if (coeff_lerp < 0) {
|
| + float rate = min(-coeff_lerp * t, 1);
|
| + float3 lerpVector = float3(rate, rate, rate);
|
| + offset = lerp(lerpOffset, offset, lerpVector);
|
| + }
|
| +
|
| + input.position = input.position + float4(offset.xyz, 0);
|
| +
|
| + output.position = mul(input.position, worldViewProjection);
|
| +
|
| + /**
|
| + * lightVector - light vector
|
| + * normal - normal vector
|
| + * viewPosition - view vector (from camera)
|
| + */
|
| +
|
| + // NOTE: In this case we do not need to multiply by any matrices since the
|
| + // WORLD transformation matrix is the identity. If you were moving the
|
| + // object such that the WORLD transform matrix was not the identity, you
|
| + // would need to multiply the normal by the WORLDINVERSETTRANSFORM matrix
|
| + // since the normal is in object space. Other values (light_pos, camera_pos)
|
| + // are already in world space.
|
| + float3 lightVector = light_pos - input.position.xyz;
|
| + float3 normal = input.normal;
|
| + float3 viewPosition = camera_pos - input.position.xyz;
|
| +
|
| + output.lightVector = lightVector;
|
| + output.normal = normal;
|
| + output.viewPosition = viewPosition;
|
| + output.color = input.color;
|
| + return output;
|
| +}
|
| +
|
| +/**
|
| + * Pixel Shader
|
| + */
|
| +float4 pixelShaderFunction(PixelShaderInput input): COLOR {
|
| + float3 lightVector = normalize(input.lightVector);
|
| + float3 normal = normalize(input.normal);
|
| + float3 viewPosition = normalize(input.viewPosition);
|
| + float3 halfVector = normalize(lightVector + viewPosition);
|
| +
|
| + // use lit function to calculate phong shading
|
| + // x component contains the ambient coefficient
|
| + // y component contains the diffuse coefficient:
|
| + // max(dot(normal, lightVector),0)
|
| + // z component contains the specular coefficient:
|
| + // dot(normal, lightVector) < 0 || dot(normal, halfVector) < 0 ?
|
| + // 0 : pow(dot(normal, halfVector), shininess)
|
| + // NOTE: This is actually Blinn-Phong shading, not Phong shading
|
| + // which would use the reflection vector instead of the half vector
|
| +
|
| + float4 phong_coeff = lit(dot(normal, lightVector),
|
| + dot(normal, halfVector), shininess);
|
| +
|
| + float4 ambient = light_ambient * phong_coeff.x * input.color;
|
| + float4 diffuse = light_diffuse * phong_coeff.y * input.color;
|
| + float4 specular = light_specular * phong_coeff.z * input.color;
|
| +
|
| + return ambient + diffuse + specular;
|
| +}
|
| +
|
| +// Here we tell our effect file *which* functions are
|
| +// our vertex and pixel shaders.
|
| +
|
| +// #o3d VertexShaderEntryPoint vertexShaderFunction
|
| +// #o3d PixelShaderEntryPoint pixelShaderFunction
|
| +// #o3d MatrixLoadOrder RowMajor
|
| + </textarea>
|
| + </td>
|
| + </tr>
|
| +</table>
|
| +</body>
|
| +</html>
|
|
|