Skip to content

Instantly share code, notes, and snippets.

@mathdoodle
Last active September 20, 2016 14:36
Show Gist options
  • Save mathdoodle/6471228a4f96febf6ef016cd40745588 to your computer and use it in GitHub Desktop.
Save mathdoodle/6471228a4f96febf6ef016cd40745588 to your computer and use it in GitHub Desktop.
EIGHT with GeoCAS Multivector

EIGHT with GeoCAS

Overview

Researching the operation of GeoCAS.Multivector.

/**
* Displays an exception by writing it to a <pre> element.
*/
export default function displayError(e: any) {
const stderr = <HTMLPreElement>document.getElementById('error')
stderr.style.color = "#FF0000"
stderr.innerHTML = `${e}`
}
/**
* The Field Adapter for a number field.
*/
const fa = new GeoCAS.NumberFieldAdapter();
/**
* Setting the metric parameter to the number of dimensions
* is equivalent to specifying a [1, 1, 1] diagonal metric.
*/
const dimensions = 3;
/**
* A (diagonal) Euclidean metric for a 3D vector space.
*/
const diag = [1, 1, 1];
const metric = dimensions;
export const one = GeoCAS.getScalar(1, metric, fa);
export const e1 = GeoCAS.getBasisVector(0, metric, fa);
export const e2 = GeoCAS.getBasisVector(1, metric, fa);
export const e3 = GeoCAS.getBasisVector(2, metric, fa);
/**
* Updates a mutable SpinorE3 from a Multivector<number>.
*/
export function setSpinorE3(target: EIGHT.SpinorE3, source: GeoCAS.Multivector<number>): void {
target.a = source.scp(one);
target.zx = source.scp(e1 ^ e3)
target.xy = source.scp(e2 ^ e1)
target.yz = source.scp(e3 ^ e2)
}
/**
* Updates a mutable VectorE3 from a Multivector<number>.
*/
export function setVectorE3(target: EIGHT.VectorE3, source: GeoCAS.Multivector<number>): void {
target.x = source.scp(e1)
target.y = source.scp(e2)
target.z = source.scp(e3)
}
/**
* Universal exponential function for more natural notation.
*/
export function exp<T extends {exp: ()=>T}>(arg: T): T {
return arg.exp()
}
<!doctype html>
<html>
<head>
<!-- STYLES-MARKER -->
<style>
/* STYLE-MARKER */
</style>
<script src='https://jspm.io/[email protected]'></script>
<!-- SHADERS-MARKER -->
<!-- SCRIPTS-MARKER -->
</head>
<body>
<canvas id='canvas'></canvas>
<pre id='error'></pre>
<script>
// CODE-MARKER
</script>
<script>
System.import('./index.js')
</script>
</body>
</html>
import {one, e1, e2, e3} from './e3ga';
import {setSpinorE3, setVectorE3} from './e3ga';
import {exp} from './e3ga';
// Comment out the following line to use the standard window.requestAnimationFrame
import requestAnimationFrame from './requestAnimationFrame';
import WireCube from './WireCube';
/**
* Wrapper around the WebGLRenderingContext providing the ContextManager interface.
*/
const engine = new EIGHT.Engine('canvas')
.size(500, 500)
.clearColor(0.1, 0.1, 0.1, 1.0)
.enable(EIGHT.Capability.DEPTH_TEST)
/**
* A collection of objects that can be rendered with a single draw method call.
*/
const scene = new EIGHT.Scene(engine)
/**
* Rendering information that applies to all objects.
*/
const ambients: EIGHT.Facet[] = []
/**
* Provides the viewing point and perspective transformation.
*/
const camera = new EIGHT.PerspectiveCamera()
setVectorE3(camera.eye, 3 * e3)
ambients.push(camera)
/**
* Provides a light color and direction for Lambert shading.
*/
const dirLight = new EIGHT.DirectionalLight()
ambients.push(dirLight)
/**
* Controls the camera by accumulating mouse movements then moving and rotating the camera.
*/
const trackball = new EIGHT.TrackballControls(camera, window)
trackball.subscribe(engine.canvas)
trackball.noPan = true;
// Create drawables such as Arrow, Box, Curve, Grid, Sphere, Cylinder.
// Add them to the scene here...
const box = new EIGHT.Box({color: EIGHT.Color.green})
box.width = 0.6
box.height = 0.6
box.depth = 0.6
scene.add(box)
const geometry = new WireCube(engine)
const material = new EIGHT.HTMLScriptsMaterial(['line-vs', 'line-fs'], document, [], engine)
const wireCube = new EIGHT.Mesh(geometry, material, engine)
scene.add(wireCube)
const stats = new Stats()
document.body.appendChild(stats.dom)
/**
* The bivector for the rotation.
*/
const B = e3 ^ e1;
/**
* Animates the scene.
*/
const animate = function(timestamp: number) {
stats.begin()
engine.clear()
trackball.update()
dirLight.direction.copy(camera.look).sub(camera.eye)
// Manupulate the X (Position) and R (Attitude)
// properties of your scene objects here...
const θ = timestamp * 0.001;
setSpinorE3(box.R, exp(-B * θ / 2));
scene.draw(ambients)
stats.end()
requestAnimationFrame(animate)
}
requestAnimationFrame(animate)
varying highp vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}
attribute vec3 aPosition;
uniform vec3 uColor;
uniform float uOpacity;
uniform mat4 uModel;
uniform mat4 uProjection;
uniform mat4 uView;
varying highp vec4 vColor;
void main(void) {
gl_Position = uProjection * uView * uModel * vec4(aPosition, 1.0);
vColor = vec4(uColor, uOpacity);
}
{
"description": "EIGHT with GeoCAS Multivector",
"dependencies": {
"davinci-eight": "2.310.0",
"stats.js": "0.16.0",
"dat-gui": "0.5.0",
"geocas": "1.0.0"
},
"operatorOverloading": true,
"name": "copy-of-eight-starter-template",
"version": "0.1.0",
"keywords": [
"EIGHT",
"GeoCAS",
"Multivector"
],
"author": "David Geo Holmes"
}
import displayError from './displayError'
/**
* Catches exceptions thrown in the animation callback and displays them.
* This function will have a slight performance impact owing to the try...catch statement.
* This function may be bypassed for production use by using window.requestAnimationFrame directly.
*/
export default function requestAnimationFrame(callback: FrameRequestCallback): number {
const wrapper: FrameRequestCallback = function(time: number) {
try {
callback(time)
}
catch(e) {
displayError(e)
}
}
return window.requestAnimationFrame(wrapper)
}
body { margin: 0; }
canvas { width: 500px; height: 500px }
#stats { position: absolute; top: 0; left: 0; }
/**
* A Geometry for rendering a cube made from lines.
*/
export default class WireCube implements EIGHT.Geometry {
private buffer: WebGLBuffer;
public data: Float32Array;
/**
*
*/
public invalid = true;
constructor(private engine: EIGHT.Engine) {
const gl = engine.gl;
const size = 1;
const L = size / 2;
this.data = new Float32Array([
-L, -L, -L, +L, -L, -L,
-L, +L, -L, +L, +L, -L,
-L, -L, +L, +L, -L, +L,
-L, +L, +L, +L, +L, +L,
-L, +L, +L, -L, +L, -L,
+L, +L, +L, +L, +L, -L,
-L, -L, +L, -L, -L, -L,
+L, -L, +L, +L, -L, -L,
-L, -L, -L, -L, +L, -L,
+L, -L, -L, +L, +L, -L,
-L, -L, +L, -L, +L, +L,
+L, -L, +L, +L, +L, +L
]);
this.buffer = gl.createBuffer();
}
bind(material: EIGHT.Material): void {
const gl = this.engine.gl;
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
}
unbind(material: EIGHT.Material): void {
const gl = this.engine.gl;
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
draw(material: EIGHT.Material): void {
const gl = this.engine.gl;
const aPosition = material.getAttribLocation('aPosition');
if (this.invalid) {
gl.bufferData(gl.ARRAY_BUFFER, this.data, EIGHT.Usage.STATIC_DRAW);
this.invalid = false;
}
gl.vertexAttribPointer(aPosition, 3, EIGHT.DataType.FLOAT, true, 0, 0);
gl.enableVertexAttribArray(aPosition);
gl.drawArrays(EIGHT.BeginMode.LINES, 0, 24);
gl.disableVertexAttribArray(aPosition);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment