Skip to content

Instantly share code, notes, and snippets.

@mathdoodle
Last active January 13, 2021 03:52
Show Gist options
  • Save mathdoodle/e5e0cdfe494b1556ff877ddc923c06c4 to your computer and use it in GitHub Desktop.
Save mathdoodle/e5e0cdfe494b1556ff877ddc923c06c4 to your computer and use it in GitHub Desktop.
Hello, Geometry!

Geometry 101

<!DOCTYPE html>
<html>
<head>
<script src="https://jspm.io/system@0.19.js"></script>
<style>
body {
margin: 0;
background: #000000;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js"></script>
<script src="https://www.stemcstudio.com:/vendor/davinci-mathscript@1.3.5/davinci-mathscript.min.js"></script>
<script id="line-fs" type="x-shader/x-fragment">varying highp vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}</script>
<script id="line-vs" type="x-shader/x-vertex">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);
}</script>
</head>
<body>
<script>
System.config({
"warnings": false,
"map": {
"davinci-eight": "https://unpkg.com/davinci-eight@8.1.0/build/browser/index.js"
}
});
</script>
<div id="container">
<canvas id="canvas3D"></canvas>
<canvas id="canvas2D" width="500" height="500"></canvas>
</div>
<script>
System.register('./WireCube.js', ['davinci-eight'], function (exports_1, context_1) {
'use strict';
var davinci_eight_1, WireCube;
var __moduleName = context_1 && context_1.id;
return {
setters: [function (davinci_eight_1_1) {
davinci_eight_1 = davinci_eight_1_1;
}],
execute: function () {
WireCube = function () {
function WireCube(engine) {
this.engine = engine;
this.material = null;
this.invalid = true;
var gl = engine.gl;
var size = 1;
var L = Ms.div(size, 2);
this.data = new Float32Array([
Ms.neg(L),
Ms.neg(L),
Ms.neg(L),
Ms.pos(L),
Ms.neg(L),
Ms.neg(L),
Ms.neg(L),
Ms.pos(L),
Ms.neg(L),
Ms.pos(L),
Ms.pos(L),
Ms.neg(L),
Ms.neg(L),
Ms.neg(L),
Ms.pos(L),
Ms.pos(L),
Ms.neg(L),
Ms.pos(L),
Ms.neg(L),
Ms.pos(L),
Ms.pos(L),
Ms.pos(L),
Ms.pos(L),
Ms.pos(L),
Ms.neg(L),
Ms.pos(L),
Ms.pos(L),
Ms.neg(L),
Ms.pos(L),
Ms.neg(L),
Ms.pos(L),
Ms.pos(L),
Ms.pos(L),
Ms.pos(L),
Ms.pos(L),
Ms.neg(L),
Ms.neg(L),
Ms.neg(L),
Ms.pos(L),
Ms.neg(L),
Ms.neg(L),
Ms.neg(L),
Ms.pos(L),
Ms.neg(L),
Ms.pos(L),
Ms.pos(L),
Ms.neg(L),
Ms.neg(L),
Ms.neg(L),
Ms.neg(L),
Ms.neg(L),
Ms.neg(L),
Ms.pos(L),
Ms.neg(L),
Ms.pos(L),
Ms.neg(L),
Ms.neg(L),
Ms.pos(L),
Ms.pos(L),
Ms.neg(L),
Ms.neg(L),
Ms.neg(L),
Ms.pos(L),
Ms.neg(L),
Ms.pos(L),
Ms.pos(L),
Ms.pos(L),
Ms.neg(L),
Ms.pos(L),
Ms.pos(L),
Ms.pos(L),
Ms.pos(L)
]);
this.buffer = gl.createBuffer();
}
WireCube.prototype.bind = function (material) {
this.material = material;
var gl = this.engine.gl;
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
};
WireCube.prototype.unbind = function (_material) {
this.material = null;
var gl = this.engine.gl;
gl.bindBuffer(gl.ARRAY_BUFFER, null);
};
WireCube.prototype.draw = function () {
var gl = this.engine.gl;
var aPosition = this.material.getAttribLocation('aPosition');
if (this.invalid) {
gl.bufferData(gl.ARRAY_BUFFER, this.data, davinci_eight_1.Usage.STATIC_DRAW);
this.invalid = false;
}
gl.vertexAttribPointer(aPosition, 3, davinci_eight_1.DataType.FLOAT, true, 0, 0);
gl.enableVertexAttribArray(aPosition);
gl.drawArrays(davinci_eight_1.BeginMode.LINES, 0, 24);
gl.disableVertexAttribArray(aPosition);
};
return WireCube;
}();
exports_1('default', WireCube);
}
};
});
System.register('./index.js', [
'./math.js',
'davinci-eight',
'./WireCube.js',
'./windowResizer.js'
], function (exports_1, context_1) {
'use strict';
var math_1, davinci_eight_1, davinci_eight_2, davinci_eight_3, davinci_eight_4, davinci_eight_5, davinci_eight_6, WireCube_1, windowResizer_1, engine, ambients, camera, dirLight, trackball, arrowA, arrowB, arrowC, geometry, material, wireCube, stats, diagram, animate;
var __moduleName = context_1 && context_1.id;
return {
setters: [
function (math_1_1) {
math_1 = math_1_1;
},
function (davinci_eight_1_1) {
davinci_eight_1 = davinci_eight_1_1;
davinci_eight_2 = davinci_eight_1_1;
davinci_eight_3 = davinci_eight_1_1;
davinci_eight_4 = davinci_eight_1_1;
davinci_eight_5 = davinci_eight_1_1;
davinci_eight_6 = davinci_eight_1_1;
},
function (WireCube_1_1) {
WireCube_1 = WireCube_1_1;
},
function (windowResizer_1_1) {
windowResizer_1 = windowResizer_1_1;
}
],
execute: function () {
engine = new davinci_eight_1.Engine('canvas3D').size(500, 500).clearColor(0, 0, 0, 1).enable(davinci_eight_1.Capability.DEPTH_TEST);
ambients = [];
camera = new davinci_eight_2.PerspectiveCamera();
camera.eye.copy(math_1.e3).scale(5);
ambients.push(camera);
dirLight = new davinci_eight_2.DirectionalLight();
ambients.push(dirLight);
trackball = new davinci_eight_3.TrackballControls(camera, window);
trackball.subscribe(engine.canvas);
arrowA = new davinci_eight_5.Arrow(engine);
arrowA.color = davinci_eight_4.Color.red;
arrowA.axis = math_1.e1;
arrowB = new davinci_eight_5.Arrow(engine);
arrowB.color = davinci_eight_4.Color.green;
arrowB.axis = math_1.e2;
arrowC = new davinci_eight_5.Arrow(engine);
arrowC.color = davinci_eight_4.Color.blue;
arrowC.axis = math_1.e3;
geometry = new WireCube_1.default(engine);
material = new davinci_eight_4.HTMLScriptsMaterial(engine, [
'line-vs',
'line-fs'
], [], document);
wireCube = new davinci_eight_4.Mesh(geometry, material, engine);
stats = new Stats();
document.body.appendChild(stats.domElement);
diagram = new davinci_eight_6.Diagram3D('canvas2D', camera, camera);
engine.canvas.style.position = 'absolute';
diagram.canvas.style.pointerEvents = 'none';
diagram.canvas.style.position = 'absolute';
animate = function (_timestamp) {
stats.begin();
trackball.update();
dirLight.direction.copy(camera.look).sub(camera.eye);
engine.clear();
diagram.clear();
diagram.ctx.font = '16pt Helvetica';
diagram.ctx.fillStyle = 'white';
diagram.ctx.fillText('Hello, Geometry!', 100, 100);
diagram.fillText('e1', Ms.mul(arrowA.axis, 1.15));
diagram.fillText('e2', Ms.mul(arrowB.axis, 1.15));
diagram.fillText('e3', Ms.mul(arrowC.axis, 1.15));
diagram.ctx.lineWidth = 4;
diagram.ctx.strokeStyle = 'yellow';
diagram.beginPath();
diagram.moveTo(Ms.mul(arrowA.axis, 0.5));
diagram.lineTo(Ms.mul(arrowB.axis, 0.5));
diagram.lineTo(Ms.mul(arrowC.axis, 0.5));
diagram.lineTo(Ms.mul(arrowA.axis, 0.5));
diagram.stroke();
arrowA.render(ambients);
arrowB.render(ambients);
arrowC.render(ambients);
wireCube.render(ambients);
stats.end();
requestAnimationFrame(animate);
};
windowResizer_1.windowResizer(engine, diagram, camera).resize();
requestAnimationFrame(animate);
}
};
});
System.register('./math.js', ['davinci-eight'], function (exports_1, context_1) {
'use strict';
var davinci_eight_1, e1, e2, e3, zero;
var __moduleName = context_1 && context_1.id;
return {
setters: [function (davinci_eight_1_1) {
davinci_eight_1 = davinci_eight_1_1;
}],
execute: function () {
exports_1('e1', e1 = davinci_eight_1.Geometric3.e1());
exports_1('e2', e2 = davinci_eight_1.Geometric3.e2());
exports_1('e3', e3 = davinci_eight_1.Geometric3.e3());
exports_1('zero', zero = davinci_eight_1.Geometric3.zero());
}
};
});
System.register('./windowResizer.js', [], function (exports_1, context_1) {
'use strict';
var __moduleName = context_1 && context_1.id;
function windowResizer(engine, diagram, camera) {
var callback = function () {
engine.size(window.innerWidth, window.innerHeight);
engine.canvas.style.width = Ms.add(window.innerWidth, 'px');
engine.canvas.style.height = Ms.add(window.innerHeight, 'px');
diagram.canvas.width = window.innerWidth;
diagram.canvas.height = window.innerHeight;
diagram.canvas.style.width = Ms.add(window.innerWidth, 'px');
diagram.canvas.style.height = Ms.add(window.innerHeight, 'px');
camera.aspect = Ms.div(window.innerWidth, window.innerHeight);
};
window.addEventListener('resize', callback, false);
var that = {
resize: function () {
callback();
return that;
},
stop: function () {
window.removeEventListener('resize', callback);
return that;
}
};
return that;
}
exports_1('windowResizer', windowResizer);
return {
setters: [],
execute: function () {
}
};
});
</script>
<script>
System.import('./index.js')
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<!-- base href='/' -->
<script src='https://jspm.io/system@0.19.js'></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id='container'>
<canvas id='canvas3D'></canvas>
<canvas id='canvas2D' width='500' height='500'></canvas>
</div>
<script>
System.import('./index.js')
</script>
</body>
</html>
import { e1, e2, e3 } from './math'
import { Engine, Capability } from 'davinci-eight'
import { Facet, PerspectiveCamera, DirectionalLight } from 'davinci-eight'
import { TrackballControls } from 'davinci-eight'
import { Color, HTMLScriptsMaterial, Mesh } from 'davinci-eight'
import { Arrow } from 'davinci-eight'
import { Diagram3D } from 'davinci-eight'
import WireCube from './WireCube'
import { windowResizer } from './windowResizer'
// import Overlay from './Overlay'
/**
* Wrapper around the WebGLRenderingContext providing the ContextManager interface.
*/
const engine = new Engine('canvas3D')
.size(500, 500)
.clearColor(0.0, 0.0, 0.0, 1.0)
.enable(Capability.DEPTH_TEST)
/**
* Rendering information that applies to all objects.
*/
const ambients: Facet[] = []
/**
* Provides the viewing point and perspective transformation.
*/
const camera = new PerspectiveCamera()
camera.eye.copy(e3).scale(5)
ambients.push(camera)
/**
* Provides a light color and direction for Lambert shading.
*/
const dirLight = new DirectionalLight()
ambients.push(dirLight)
/**
* Controls the camera by accumulating mouse movements then moving and rotating the camera.
*/
const trackball = new TrackballControls(camera, window)
trackball.subscribe(engine.canvas)
// Create drawables such as Arrow, Box, Curve, Grid, Sphere, Cylinder.
const arrowA = new Arrow(engine)
arrowA.color = Color.red
arrowA.axis = e1
const arrowB = new Arrow(engine)
arrowB.color = Color.green
arrowB.axis = e2
const arrowC = new Arrow(engine)
arrowC.color = Color.blue
arrowC.axis = e3
const geometry = new WireCube(engine)
const material = new HTMLScriptsMaterial(engine, ['line-vs', 'line-fs'], [], document)
const wireCube = new Mesh(geometry, material, engine)
const stats = new Stats()
document.body.appendChild(stats.domElement)
const diagram = new Diagram3D('canvas2D', camera, camera)
// const diagram = new Overlay('canvas2D', camera)
// More positive z-index values are on top.
// engine.canvas.style.zIndex = "0"
engine.canvas.style.position = 'absolute'
// diagram.canvas.style.zIndex = "1"
// TODO: These should be defaults
diagram.canvas.style.pointerEvents = 'none'
diagram.canvas.style.position = 'absolute'
/**
* Animates the scene.
*/
const animate = function(_timestamp: number) {
stats.begin()
trackball.update()
dirLight.direction.copy(camera.look).sub(camera.eye)
engine.clear()
diagram.clear()
diagram.ctx.font = '16pt Helvetica'
diagram.ctx.fillStyle = 'white'
diagram.ctx.fillText("Hello, Geometry!", 100, 100)
diagram.fillText("e1", arrowA.axis * 1.15)
diagram.fillText("e2", arrowB.axis * 1.15)
diagram.fillText("e3", arrowC.axis * 1.15)
// The yellow triange is drawn on the overlay.
diagram.ctx.lineWidth = 4
diagram.ctx.strokeStyle = 'yellow'
diagram.beginPath()
diagram.moveTo(arrowA.axis * 0.5)
diagram.lineTo(arrowB.axis * 0.5)
diagram.lineTo(arrowC.axis * 0.5)
diagram.lineTo(arrowA.axis * 0.5)
diagram.stroke()
arrowA.render(ambients)
arrowB.render(ambients)
arrowC.render(ambients)
wireCube.render(ambients)
stats.end()
requestAnimationFrame(animate)
}
windowResizer(engine, diagram, camera).resize()
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);
}
import { Geometric3 } from 'davinci-eight'
export const e1 = Geometric3.e1()
export const e2 = Geometric3.e2()
export const e3 = Geometric3.e3()
export const zero = Geometric3.zero()
{
"description": "Hello, Geometry!",
"dependencies": {
"stats.js": "0.16.0",
"davinci-eight": "8.1.0"
},
"operatorOverloading": true,
"name": "copy-of-copy-of-copy-of-eight-starter-template",
"version": "0.1.0",
"keywords": [
"DaVinci eight",
"Overlay",
"2D",
"WebGL",
"3D"
],
"author": "David Geo Holmes",
"linting": true
}
body {
margin: 0;
background: #000000;
}
{
"allowJs": true,
"checkJs": true,
"declaration": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"jsx": "react",
"module": "system",
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"preserveConstEnums": true,
"removeComments": false,
"skipLibCheck": true,
"sourceMap": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"target": "es5",
"traceResolution": true
}
{
"rules": {
"array-type": [
true,
"array"
],
"curly": false,
"comment-format": [
true,
"check-space"
],
"eofline": true,
"forin": true,
"jsdoc-format": true,
"new-parens": true,
"no-conditional-assignment": false,
"no-consecutive-blank-lines": true,
"no-construct": true,
"no-for-in-array": true,
"no-inferrable-types": [
true
],
"no-magic-numbers": false,
"no-shadowed-variable": true,
"no-string-throw": true,
"no-trailing-whitespace": [
true,
"ignore-jsdoc"
],
"no-var-keyword": true,
"one-variable-per-declaration": [
true,
"ignore-for-loop"
],
"prefer-const": true,
"prefer-for-of": true,
"prefer-function-over-method": false,
"prefer-method-signature": true,
"radix": true,
"semicolon": [
true,
"never"
],
"trailing-comma": [
true,
{
"multiline": "never",
"singleline": "never"
}
],
"triple-equals": true,
"use-isnan": true
}
}
import { Engine } from 'davinci-eight'
import { PerspectiveCamera } from 'davinci-eight'
export interface Resizer {
resize(): this
stop(): this
}
/**
* Creates an object that manages resizing of the output to fit the window.
*/
export function windowResizer(engine: Engine, diagram: { canvas: HTMLCanvasElement }, camera: PerspectiveCamera): Resizer {
const callback = function() {
// size sets the viewport and the canvas width and height.
// But it does not set the style with and height.
engine.size(window.innerWidth, window.innerHeight)
engine.canvas.style.width = `${window.innerWidth}px`
engine.canvas.style.height = `${window.innerHeight}px`
diagram.canvas.width = window.innerWidth
diagram.canvas.height = window.innerHeight
diagram.canvas.style.width = `${window.innerWidth}px`
diagram.canvas.style.height = `${window.innerHeight}px`
camera.aspect = window.innerWidth / window.innerHeight
}
window.addEventListener('resize', callback, false)
const that: Resizer = {
/**
*
*/
resize: function() {
callback()
return that
},
/**
* Stop watching window resize
*/
stop: function() {
window.removeEventListener('resize', callback)
return that
}
}
return that
}
import { Geometry, Engine, Material, Usage, DataType, BeginMode } from 'davinci-eight'
/**
* A Geometry for rendering a cube made from lines.
*/
export default class WireCube implements Geometry {
private buffer: WebGLBuffer
public data: Float32Array
private material: Material | null = null
/**
*
*/
public invalid = true
constructor(private engine: 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() as WebGLBuffer
}
bind(material: Material): void {
this.material = material
const gl = this.engine.gl
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer)
}
unbind(_material: Material): void {
this.material = null
const gl = this.engine.gl
gl.bindBuffer(gl.ARRAY_BUFFER, null)
}
draw(): void {
const gl = this.engine.gl
const aPosition = (this.material as Material).getAttribLocation('aPosition')
if (this.invalid) {
gl.bufferData(gl.ARRAY_BUFFER, this.data, Usage.STATIC_DRAW)
this.invalid = false
}
gl.vertexAttribPointer(aPosition, 3, DataType.FLOAT, true, 0, 0)
gl.enableVertexAttribArray(aPosition)
gl.drawArrays(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