Last active
July 7, 2020 19:16
-
-
Save mathdoodle/07760feb161200d7dd35fe3219a229a2 to your computer and use it in GitHub Desktop.
Diagram3D
This file contains hidden or 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
/** | |
* 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}` | |
} |
This file contains hidden or 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> | |
<html> | |
<head> | |
<!-- STYLES-MARKER --> | |
<style> | |
/* STYLE-MARKER */ | |
</style> | |
<script src='https://jspm.io/[email protected]'></script> | |
<!-- SHADERS-MARKER --> | |
<!-- SCRIPTS-MARKER --> | |
</head> | |
<body> | |
<div id='container'> | |
<canvas id='canvas3D'></canvas> | |
<canvas id='canvas2D' width='500' height='500'></canvas> | |
</div> | |
<pre id='error'></pre> | |
<script> | |
// CODE-MARKER | |
</script> | |
<script> | |
System.import('./index.js') | |
</script> | |
</body> | |
</html> |
This file contains hidden or 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
import { e1, e2, e3/*, zero*/ } from './math'; | |
import { | |
Engine, | |
Capability, | |
Scene, | |
Facet, PerspectiveCamera, DirectionalLight, TrackballControls, Box, Color, Arrow, HTMLScriptsMaterial, Mesh, Diagram3D | |
} from 'davinci-eight' | |
// Comment out the following line to use the standard window.requestAnimationFrame | |
import requestAnimationFrame from './requestAnimationFrame'; | |
import WireCube from './WireCube'; | |
import Overlay from './Overlay'; | |
/** | |
* Wrapper around the WebGLRenderingContext providing the ContextManager interface. | |
*/ | |
const engine = new Engine('canvas3D') | |
.size(500, 500) | |
.clearColor(0.1, 0.1, 0.1, 1.0) | |
.enable(Capability.DEPTH_TEST); | |
/** | |
* A collection of objects that can be rendered with a single draw method call. | |
*/ | |
const scene = new Scene(engine) | |
/** | |
* 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) | |
trackball.noPan = true; | |
// Create drawables such as Arrow, Box, Curve, Grid, Sphere, Cylinder. | |
// Add them to the scene here... | |
const box = new Box(engine, { color: Color.green }) | |
box.width = 0.6 | |
box.height = 0.6 | |
box.depth = 0.6 | |
// scene.add(box) | |
const arrowA = new Arrow(engine); | |
arrowA.color = Color.red | |
arrowA.axis = e1 | |
scene.add(arrowA); | |
const arrowB = new Arrow(engine); | |
arrowB.color = Color.blue | |
arrowB.axis = e2 | |
scene.add(arrowB); | |
const geometry = new WireCube(engine) | |
const material = new HTMLScriptsMaterial(engine, ['line-vs', 'line-fs'], [], document) | |
const wireCube = new Mesh(geometry, material, engine) | |
scene.add(wireCube) | |
const stats = new Stats() | |
document.body.appendChild(stats.domElement) | |
// const diagram = new Diagram3D('canvas2D', camera); | |
const diagram = new Overlay('canvas2D', camera); | |
/** | |
* 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.fillText("a", arrowA.axis); | |
diagram.fillText("b", arrowB.axis); | |
scene.render(ambients) | |
stats.end() | |
requestAnimationFrame(animate) | |
} | |
requestAnimationFrame(animate) |
This file contains hidden or 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
varying highp vec4 vColor; | |
void main(void) { | |
gl_FragColor = vColor; | |
} |
This file contains hidden or 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
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); | |
} |
This file contains hidden or 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
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(); |
This file contains hidden or 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
import { PerspectiveCamera, VectorE3, VectorE2, Geometric3 } from 'davinci-eight' | |
export default class Overlay { | |
public ctx: CanvasRenderingContext2D; | |
constructor(_canvas: string, private camera: PerspectiveCamera) { | |
const canvasElement = <HTMLCanvasElement> document.getElementById('canvas2D'); | |
this.ctx = canvasElement.getContext('2d') as CanvasRenderingContext2D; | |
this.ctx.strokeStyle = "#FFFFFF"; | |
this.ctx.fillStyle = '#ffffff'; | |
this.ctx.font = '24px Helvetica'; | |
} | |
clear(): void { | |
this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height); | |
} | |
fillText(text: string, X: VectorE3, maxWidth?: number) { | |
const coords = this.canvasCoords(X); | |
this.ctx.fillText(text, coords.x, coords.y, maxWidth); | |
} | |
beginPath() { | |
this.ctx.beginPath(); | |
} | |
moveTo(X: VectorE3) { | |
const coords = this.canvasCoords(X); | |
this.ctx.moveTo(coords.x, coords.y); | |
} | |
lineTo(X: VectorE3) { | |
const coords = this.canvasCoords(X); | |
this.ctx.lineTo(coords.x, coords.y); | |
} | |
stroke() { | |
this.ctx.stroke(); | |
} | |
private canvasCoords(X: VectorE3): VectorE2 { | |
const camera = this.camera; | |
const cameraCoords = view(Geometric3.fromVector(X), camera.eye, camera.look, camera.up); | |
const N = camera.near; | |
const F = camera.far; | |
const θ = camera.fov; | |
const aspect = camera.aspect; | |
const canonCoords = perspective(cameraCoords, N, F, θ, aspect); | |
const x = (canonCoords.x + 1) * this.ctx.canvas.width / 2; | |
const y = (canonCoords.y - 1) * -this.ctx.canvas.height / 2; | |
return { x, y } | |
} | |
} | |
/** | |
* View transformation converts world coordinates to camera frame coordinates. | |
*/ | |
function view(X: Geometric3, eye: Geometric3, look: Geometric3, up: Geometric3): VectorE3 { | |
const n = (eye - look).normalize(); | |
const u = up.clone().cross(n).normalize(); | |
const v = n.clone().cross(u); | |
const du = - eye | u; | |
const dv = - eye | v; | |
const dn = - eye | n; | |
const x = (X | u + du).a; | |
const y = (X | v + dv).a; | |
const z = (X | n + dn).a; | |
return { x, y, z }; | |
} | |
/** | |
* Perspective transformation projects camera coordinates onto the near plane. | |
*/ | |
function perspective(X: VectorE3, N: number, F: number, fov: number, aspect: number): VectorE3 { | |
const t = N * Math.tan(fov / 2); | |
const b = -t; | |
const r = aspect * t; | |
const l = -r; | |
const x = ((2 * N) * X.x + (r + l) * X.z) / (-X.z * (r - l)); | |
const y = ((2 * N) * X.y + (t + b) * X.z) / (-X.z * (t - b)); | |
const z = (-(F + N) * X.z - 2 * F * N) / (-X.z * (F - N)) | |
return { x, y, z }; | |
} |
This file contains hidden or 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
{ | |
"description": "Diagram3D", | |
"dependencies": { | |
"stats.js": "0.16.0", | |
"davinci-eight": "7.4.4" | |
}, | |
"operatorOverloading": true, | |
"name": "copy-of-copy-of-eight-starter-template", | |
"version": "0.1.0", | |
"keywords": [ | |
"EIGHT", | |
"Overlay", | |
"2D", | |
"WebGL", | |
"3D" | |
], | |
"author": "David Geo Holmes" | |
} |
This file contains hidden or 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
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) | |
} |
This file contains hidden or 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
body { margin: 0; } | |
#container { | |
position: relative; | |
} | |
#canvas3D { | |
position: absolute; | |
left: 0px; | |
top: 0px; | |
width: 500px; | |
height: 500px; | |
} | |
#canvas2D { | |
position: absolute; | |
left: 0px; | |
top: 0px; | |
z-index: 10; | |
width: 500px; | |
height: 500px; | |
/** | |
* Allow events to go to the other elements | |
*/ | |
pointer-events: none; | |
} | |
#stats { position: absolute; top: 0; left: 0; } |
This file contains hidden or 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
Show hidden characters
{ | |
"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 | |
} |
This file contains hidden or 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
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