skycraft: moar refactor
This commit is contained in:
		
							
								
								
									
										335
									
								
								skycraft/draw.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										335
									
								
								skycraft/draw.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,335 @@
 | 
				
			|||||||
 | 
					import {makeBufferFromFaces } from '../geometry';
 | 
				
			||||||
 | 
					import { loadTexture, makeProgram } from '../gl';
 | 
				
			||||||
 | 
					import * as linalg from './linalg';
 | 
				
			||||||
 | 
					import * as se3 from '../se3';
 | 
				
			||||||
 | 
					import { makeOrbitObject } from './orbit';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const VSHADER = `
 | 
				
			||||||
 | 
					attribute vec3 aPosition;
 | 
				
			||||||
 | 
					attribute vec3 aNormal;
 | 
				
			||||||
 | 
					attribute vec2 aTextureCoord;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uniform mat4 uProjection;
 | 
				
			||||||
 | 
					uniform mat4 uModel;
 | 
				
			||||||
 | 
					uniform mat4 uView;
 | 
				
			||||||
 | 
					uniform vec3 uLightDirection;
 | 
				
			||||||
 | 
					uniform float uAmbiantLight;
 | 
				
			||||||
 | 
					uniform vec3 uGlowColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					varying highp vec2 vTextureCoord;
 | 
				
			||||||
 | 
					varying lowp vec3 vLighting;
 | 
				
			||||||
 | 
					varying lowp vec3 vRay;
 | 
				
			||||||
 | 
					varying lowp vec3 vLightDir;
 | 
				
			||||||
 | 
					varying lowp vec3 vNormal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					highp mat3 transpose(in highp mat3 inmat) {
 | 
				
			||||||
 | 
					    highp vec3 x = inmat[0];
 | 
				
			||||||
 | 
					    highp vec3 y = inmat[1];
 | 
				
			||||||
 | 
					    highp vec3 z = inmat[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return mat3(
 | 
				
			||||||
 | 
					        vec3(x.x, y.x, z.x),
 | 
				
			||||||
 | 
					        vec3(x.y, y.y, z.y),
 | 
				
			||||||
 | 
					        vec3(x.z, y.z, z.z)
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
					    highp mat4 modelview = uView * uModel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gl_Position = uProjection * modelview * vec4(aPosition, 1.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lowp vec3 normal = mat3(uModel) * aNormal;
 | 
				
			||||||
 | 
					    lowp float diffuseAmount = max(dot(-uLightDirection, normal), 0.0);
 | 
				
			||||||
 | 
					    lowp vec3 ambiant = uAmbiantLight * vec3(1.0, 1.0, 0.9);
 | 
				
			||||||
 | 
					    vLighting = ambiant + vec3(1.0, 1.0, 1.0) * diffuseAmount + uGlowColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vTextureCoord = aTextureCoord;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lowp vec3 camPos = -transpose(mat3(uView))*(uView * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
 | 
				
			||||||
 | 
					    vRay = -normalize((uModel * vec4(aPosition, 1.0)).xyz - camPos);
 | 
				
			||||||
 | 
					    vLightDir = -uLightDirection;
 | 
				
			||||||
 | 
					    vNormal = normal;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const FSHADER = `
 | 
				
			||||||
 | 
					uniform sampler2D uSampler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					varying highp vec2 vTextureCoord;
 | 
				
			||||||
 | 
					varying lowp vec3 vLighting;
 | 
				
			||||||
 | 
					varying lowp vec3 vRay;
 | 
				
			||||||
 | 
					varying lowp vec3 vLightDir;
 | 
				
			||||||
 | 
					varying lowp vec3 vNormal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
					    highp vec4 color = texture2D(uSampler, vTextureCoord);
 | 
				
			||||||
 | 
					    if (color.a < 0.1) {
 | 
				
			||||||
 | 
					        discard;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    lowp vec3 specularDir = 2.0 * dot(vLightDir, vNormal) * vNormal - vLightDir;
 | 
				
			||||||
 | 
					    lowp float specularAmount = smoothstep(0.92, 1.0, dot(vRay, specularDir));
 | 
				
			||||||
 | 
					    lowp vec3 specular = 0.8 * specularAmount * vec3(1.0, 1.0, 0.8);
 | 
				
			||||||
 | 
					    gl_FragColor = vec4(vLighting * color.rgb + specular, color.a);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export async function initWorldGl(gl: WebGLRenderingContext) {
 | 
				
			||||||
 | 
					    const program = makeProgram(gl, VSHADER, FSHADER);
 | 
				
			||||||
 | 
					    const texture = await loadTexture(gl, 'texture.png');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // load those ahead of time
 | 
				
			||||||
 | 
					    const viewLoc = gl.getUniformLocation(program, 'uView');
 | 
				
			||||||
 | 
					    const modelLoc = gl.getUniformLocation(program, 'uModel');
 | 
				
			||||||
 | 
					    const projLoc = gl.getUniformLocation(program, 'uProjection');
 | 
				
			||||||
 | 
					    const samplerLoc = gl.getUniformLocation(program, 'uSampler');
 | 
				
			||||||
 | 
					    const lightDirectionLoc = gl.getUniformLocation(program, 'uLightDirection');
 | 
				
			||||||
 | 
					    const ambiantLoc = gl.getUniformLocation(program, 'uAmbiantLight');
 | 
				
			||||||
 | 
					    const glowColorLoc = gl.getUniformLocation(program, 'uGlowColor');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const positionLoc = gl.getAttribLocation(program, 'aPosition');
 | 
				
			||||||
 | 
					    const normalLoc = gl.getAttribLocation(program, 'aNormal');
 | 
				
			||||||
 | 
					    const textureLoc = gl.getAttribLocation(program, 'aTextureCoord');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const setupScene = (sceneParams) => {
 | 
				
			||||||
 | 
					        const {
 | 
				
			||||||
 | 
					            projectionMatrix,
 | 
				
			||||||
 | 
					            viewMatrix,
 | 
				
			||||||
 | 
					            ambiantLightAmount,
 | 
				
			||||||
 | 
					        } = sceneParams;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gl.useProgram(program);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gl.uniformMatrix4fv(projLoc, false, new Float32Array(projectionMatrix));
 | 
				
			||||||
 | 
					        gl.uniformMatrix4fv(viewLoc, false, new Float32Array(viewMatrix));
 | 
				
			||||||
 | 
					        gl.uniform1f(ambiantLoc, ambiantLightAmount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // doing this here because it's the same for all world stuff
 | 
				
			||||||
 | 
					        gl.uniformMatrix4fv(modelLoc, false, new Float32Array(se3.identity()));
 | 
				
			||||||
 | 
					        gl.uniform1i(samplerLoc, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gl.enableVertexAttribArray(positionLoc);
 | 
				
			||||||
 | 
					        gl.enableVertexAttribArray(normalLoc);
 | 
				
			||||||
 | 
					        gl.enableVertexAttribArray(textureLoc);
 | 
				
			||||||
 | 
					        gl.activeTexture(gl.TEXTURE0);
 | 
				
			||||||
 | 
					        gl.bindTexture(gl.TEXTURE_2D, texture);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const drawObject = (objectParams) => {
 | 
				
			||||||
 | 
					        const {
 | 
				
			||||||
 | 
					            position,
 | 
				
			||||||
 | 
					            orientation,
 | 
				
			||||||
 | 
					            glBuffer,
 | 
				
			||||||
 | 
					            numVertices,
 | 
				
			||||||
 | 
					            lightDirection,
 | 
				
			||||||
 | 
					            glowColor,
 | 
				
			||||||
 | 
					        } = objectParams;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gl.uniformMatrix4fv(modelLoc, false, new Float32Array(se3.product(
 | 
				
			||||||
 | 
					            se3.translation(...position), orientation)));
 | 
				
			||||||
 | 
					        gl.uniform3fv(lightDirectionLoc, lightDirection);
 | 
				
			||||||
 | 
					        gl.uniform3fv(glowColorLoc, glowColor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gl.bindBuffer(gl.ARRAY_BUFFER, glBuffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 20, 0);
 | 
				
			||||||
 | 
					        gl.vertexAttribPointer(normalLoc, 3, gl.BYTE, true, 20, 12);
 | 
				
			||||||
 | 
					        gl.vertexAttribPointer(textureLoc, 2, gl.UNSIGNED_SHORT, true, 20, 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gl.drawArrays(gl.TRIANGLES, 0, numVertices);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        setupScene,
 | 
				
			||||||
 | 
					        drawObject,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ORBIT_VSHADER = `
 | 
				
			||||||
 | 
					attribute vec3 aPosition;
 | 
				
			||||||
 | 
					attribute vec2 aValue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uniform mat4 uProjection;
 | 
				
			||||||
 | 
					uniform mat4 uModel;
 | 
				
			||||||
 | 
					uniform mat4 uView;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					varying lowp vec2 vCoords;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
					    highp mat4 modelview = uView * uModel;
 | 
				
			||||||
 | 
					    gl_Position = uProjection * modelview * vec4(aPosition, 1.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vCoords = aValue;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ORBIT_FSHADER = `
 | 
				
			||||||
 | 
					varying lowp vec2 vCoords;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
					  lowp float x = vCoords.x;
 | 
				
			||||||
 | 
					  lowp float y = vCoords.y;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  lowp float f = sqrt(x * x + y * y);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (f > 1.00) {
 | 
				
			||||||
 | 
					    discard;
 | 
				
			||||||
 | 
					  } else if (f < 0.98) {
 | 
				
			||||||
 | 
					    discard;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  gl_FragColor = vec4(1, .5, 0, 0.5);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getOrbitDrawContext(gl: WebGLRenderingContext) {
 | 
				
			||||||
 | 
					    const program = makeProgram(gl, ORBIT_VSHADER, ORBIT_FSHADER);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // load those ahead of time
 | 
				
			||||||
 | 
					    const viewLoc = gl.getUniformLocation(program, 'uView');
 | 
				
			||||||
 | 
					    const modelLoc = gl.getUniformLocation(program, 'uModel');
 | 
				
			||||||
 | 
					    const projLoc = gl.getUniformLocation(program, 'uProjection');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const positionLoc = gl.getAttribLocation(program, 'aPosition');
 | 
				
			||||||
 | 
					    const valueLoc = gl.getAttribLocation(program, 'aValue');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const setupScene = (sceneParams) => {
 | 
				
			||||||
 | 
					        const {
 | 
				
			||||||
 | 
					            projectionMatrix,
 | 
				
			||||||
 | 
					            viewMatrix,
 | 
				
			||||||
 | 
					        } = sceneParams;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gl.useProgram(program);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gl.uniformMatrix4fv(projLoc, false, new Float32Array(projectionMatrix));
 | 
				
			||||||
 | 
					        gl.uniformMatrix4fv(viewLoc, false, new Float32Array(viewMatrix));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // doing this here because it's the same for all world stuff
 | 
				
			||||||
 | 
					        gl.uniformMatrix4fv(modelLoc, false, new Float32Array(se3.identity()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gl.enableVertexAttribArray(positionLoc);
 | 
				
			||||||
 | 
					        gl.enableVertexAttribArray(valueLoc);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const drawObject = (objectParams) => {
 | 
				
			||||||
 | 
					        const {
 | 
				
			||||||
 | 
					            position,
 | 
				
			||||||
 | 
					            orientation,
 | 
				
			||||||
 | 
					            value,
 | 
				
			||||||
 | 
					            glBuffer,
 | 
				
			||||||
 | 
					        } = objectParams;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gl.uniformMatrix4fv(modelLoc, false, new Float32Array(se3.product(
 | 
				
			||||||
 | 
					            se3.translation(...position), orientation)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gl.bindBuffer(gl.ARRAY_BUFFER, glBuffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 20, 0);
 | 
				
			||||||
 | 
					        gl.vertexAttribPointer(valueLoc, 2, gl.FLOAT, false, 20, 12);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gl.disable(gl.CULL_FACE);
 | 
				
			||||||
 | 
					        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
 | 
				
			||||||
 | 
					        gl.enable(gl.CULL_FACE);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        setupScene,
 | 
				
			||||||
 | 
					        drawObject,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getObjects(context, body, parentPosition = undefined) {
 | 
				
			||||||
 | 
					    const objects = [];
 | 
				
			||||||
 | 
					    const {gl, glContext, player} = context;
 | 
				
			||||||
 | 
					    const {position, orientation, glowColor} = body;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (body.glBuffer === undefined) {
 | 
				
			||||||
 | 
					        body.glBuffer = makeBufferFromFaces(gl, body.geometry);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    objects.push({
 | 
				
			||||||
 | 
					        geometry: body.glBuffer,
 | 
				
			||||||
 | 
					        orientation,
 | 
				
			||||||
 | 
					        position,
 | 
				
			||||||
 | 
					        glContext,
 | 
				
			||||||
 | 
					        glowColor,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    if (parentPosition !== undefined) {
 | 
				
			||||||
 | 
					        const orbitObject = makeOrbitObject(gl, context.orbitGlContext, body.orbit, parentPosition);
 | 
				
			||||||
 | 
					        objects.push(orbitObject);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        const shipOrientation = [
 | 
				
			||||||
 | 
					            se3.rotationOnly(player.tf),
 | 
				
			||||||
 | 
					            se3.rotationOnly(context.camera.tf),
 | 
				
			||||||
 | 
					            se3.rotxyz(-Math.PI / 2, Math.PI / 2, Math.PI / 2),
 | 
				
			||||||
 | 
					        ].reduce(se3.product);
 | 
				
			||||||
 | 
					        const shipPos = player.position;
 | 
				
			||||||
 | 
					        objects.push({
 | 
				
			||||||
 | 
					            geometry: makeBufferFromFaces(gl, context.spaceship),
 | 
				
			||||||
 | 
					            orientation: shipOrientation,
 | 
				
			||||||
 | 
					            position: shipPos,
 | 
				
			||||||
 | 
					            glContext,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (body.children !== undefined) {
 | 
				
			||||||
 | 
					        for (const child of body.children) {
 | 
				
			||||||
 | 
					            objects.push(...getObjects(context, child, position));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return objects;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function sunDirection(position: linalg.vec3) {
 | 
				
			||||||
 | 
					    return linalg.scale(position, 1/linalg.norm(position));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function draw(context) {
 | 
				
			||||||
 | 
					    const {gl, camera, player, universe, orbit, orbitGlContext, orbitBody} = context;
 | 
				
			||||||
 | 
					    const {skyColor, ambiantLight, projMatrix} = context;
 | 
				
			||||||
 | 
					    const objects = getObjects(context, universe); 
 | 
				
			||||||
 | 
					    if (orbit !== undefined && orbit.excentricity < 1) {
 | 
				
			||||||
 | 
					        objects.push(makeOrbitObject(gl, orbitGlContext, orbit, orbitBody.position));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gl.clearColor(...skyColor, 1.0);
 | 
				
			||||||
 | 
					    gl.clearDepth(1.0);
 | 
				
			||||||
 | 
					    gl.enable(gl.DEPTH_TEST);
 | 
				
			||||||
 | 
					    gl.depthFunc(gl.LEQUAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gl.enable(gl.CULL_FACE);
 | 
				
			||||||
 | 
					    gl.cullFace(gl.BACK);
 | 
				
			||||||
 | 
					    gl.enable(gl.BLEND);
 | 
				
			||||||
 | 
					    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const viewMatrix = se3.inverse([
 | 
				
			||||||
 | 
					        player.tf,  // player position & orientation
 | 
				
			||||||
 | 
					        camera.tf,  // camera orientation relative to player
 | 
				
			||||||
 | 
					        se3.translation(0, 1, 4),  // step back from the player
 | 
				
			||||||
 | 
					    ].reduce(se3.product));
 | 
				
			||||||
 | 
					    let lastGlContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const {position, orientation, geometry, glContext, glowColor} of objects) {
 | 
				
			||||||
 | 
					        if (glContext !== lastGlContext) {
 | 
				
			||||||
 | 
					            glContext.setupScene({
 | 
				
			||||||
 | 
					                projectionMatrix: projMatrix,
 | 
				
			||||||
 | 
					                viewMatrix,
 | 
				
			||||||
 | 
					                ambiantLightAmount: ambiantLight,
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        lastGlContext = glContext;
 | 
				
			||||||
 | 
					        const lightDirection = sunDirection(position);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        glContext.drawObject({
 | 
				
			||||||
 | 
					            position,
 | 
				
			||||||
 | 
					            orientation,
 | 
				
			||||||
 | 
					            glBuffer: geometry.glBuffer,
 | 
				
			||||||
 | 
					            numVertices: geometry.numVertices,
 | 
				
			||||||
 | 
					            lightDirection,
 | 
				
			||||||
 | 
					            glowColor: glowColor || [0, 0, 0],
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,248 +1,16 @@
 | 
				
			|||||||
import { makeFace, makeBufferFromFaces } from '../geometry';
 | 
					import { makeFace } from '../geometry';
 | 
				
			||||||
import { loadTexture, makeProgram } from '../gl';
 | 
					
 | 
				
			||||||
import * as linalg from './linalg';
 | 
					import * as linalg from './linalg';
 | 
				
			||||||
import { loadObjModel } from './obj';
 | 
					import { loadObjModel } from './obj';
 | 
				
			||||||
import * as se3 from '../se3';
 | 
					import * as se3 from '../se3';
 | 
				
			||||||
import { computeOrbit, findSoi, getCartesianState, makeOrbitObject, updateBodyPhysics } from './orbit';
 | 
					import { computeOrbit, findSoi, getCartesianState, updateBodyPhysics } from './orbit';
 | 
				
			||||||
import { getBodyGeometry } from './chunk';
 | 
					import { getBodyGeometry } from './chunk';
 | 
				
			||||||
 | 
					import { draw, getOrbitDrawContext, initWorldGl } from './draw';
 | 
				
			||||||
const VSHADER = `
 | 
					 | 
				
			||||||
attribute vec3 aPosition;
 | 
					 | 
				
			||||||
attribute vec3 aNormal;
 | 
					 | 
				
			||||||
attribute vec2 aTextureCoord;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
uniform mat4 uProjection;
 | 
					 | 
				
			||||||
uniform mat4 uModel;
 | 
					 | 
				
			||||||
uniform mat4 uView;
 | 
					 | 
				
			||||||
uniform vec3 uLightDirection;
 | 
					 | 
				
			||||||
uniform float uAmbiantLight;
 | 
					 | 
				
			||||||
uniform vec3 uGlowColor;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
varying highp vec2 vTextureCoord;
 | 
					 | 
				
			||||||
varying lowp vec3 vLighting;
 | 
					 | 
				
			||||||
varying lowp vec3 vRay;
 | 
					 | 
				
			||||||
varying lowp vec3 vLightDir;
 | 
					 | 
				
			||||||
varying lowp vec3 vNormal;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
highp mat3 transpose(in highp mat3 inmat) {
 | 
					 | 
				
			||||||
    highp vec3 x = inmat[0];
 | 
					 | 
				
			||||||
    highp vec3 y = inmat[1];
 | 
					 | 
				
			||||||
    highp vec3 z = inmat[2];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return mat3(
 | 
					 | 
				
			||||||
        vec3(x.x, y.x, z.x),
 | 
					 | 
				
			||||||
        vec3(x.y, y.y, z.y),
 | 
					 | 
				
			||||||
        vec3(x.z, y.z, z.z)
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void main() {
 | 
					 | 
				
			||||||
    highp mat4 modelview = uView * uModel;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gl_Position = uProjection * modelview * vec4(aPosition, 1.0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    lowp vec3 normal = mat3(uModel) * aNormal;
 | 
					 | 
				
			||||||
    lowp float diffuseAmount = max(dot(-uLightDirection, normal), 0.0);
 | 
					 | 
				
			||||||
    lowp vec3 ambiant = uAmbiantLight * vec3(1.0, 1.0, 0.9);
 | 
					 | 
				
			||||||
    vLighting = ambiant + vec3(1.0, 1.0, 1.0) * diffuseAmount + uGlowColor;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    vTextureCoord = aTextureCoord;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    lowp vec3 camPos = -transpose(mat3(uView))*(uView * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
 | 
					 | 
				
			||||||
    vRay = -normalize((uModel * vec4(aPosition, 1.0)).xyz - camPos);
 | 
					 | 
				
			||||||
    vLightDir = -uLightDirection;
 | 
					 | 
				
			||||||
    vNormal = normal;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
`;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const FSHADER = `
 | 
					 | 
				
			||||||
uniform sampler2D uSampler;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
varying highp vec2 vTextureCoord;
 | 
					 | 
				
			||||||
varying lowp vec3 vLighting;
 | 
					 | 
				
			||||||
varying lowp vec3 vRay;
 | 
					 | 
				
			||||||
varying lowp vec3 vLightDir;
 | 
					 | 
				
			||||||
varying lowp vec3 vNormal;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void main() {
 | 
					 | 
				
			||||||
    highp vec4 color = texture2D(uSampler, vTextureCoord);
 | 
					 | 
				
			||||||
    if (color.a < 0.1) {
 | 
					 | 
				
			||||||
        discard;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    lowp vec3 specularDir = 2.0 * dot(vLightDir, vNormal) * vNormal - vLightDir;
 | 
					 | 
				
			||||||
    lowp float specularAmount = smoothstep(0.92, 1.0, dot(vRay, specularDir));
 | 
					 | 
				
			||||||
    lowp vec3 specular = 0.8 * specularAmount * vec3(1.0, 1.0, 0.8);
 | 
					 | 
				
			||||||
    gl_FragColor = vec4(vLighting * color.rgb + specular, color.a);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
`;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const kEpoch = 0;
 | 
					const kEpoch = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function initWorldGl(gl: WebGLRenderingContext) {
 | 
					 | 
				
			||||||
    const program = makeProgram(gl, VSHADER, FSHADER);
 | 
					 | 
				
			||||||
    const texture = await loadTexture(gl, 'texture.png');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // load those ahead of time
 | 
					 | 
				
			||||||
    const viewLoc = gl.getUniformLocation(program, 'uView');
 | 
					 | 
				
			||||||
    const modelLoc = gl.getUniformLocation(program, 'uModel');
 | 
					 | 
				
			||||||
    const projLoc = gl.getUniformLocation(program, 'uProjection');
 | 
					 | 
				
			||||||
    const samplerLoc = gl.getUniformLocation(program, 'uSampler');
 | 
					 | 
				
			||||||
    const lightDirectionLoc = gl.getUniformLocation(program, 'uLightDirection');
 | 
					 | 
				
			||||||
    const ambiantLoc = gl.getUniformLocation(program, 'uAmbiantLight');
 | 
					 | 
				
			||||||
    const glowColorLoc = gl.getUniformLocation(program, 'uGlowColor');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const positionLoc = gl.getAttribLocation(program, 'aPosition');
 | 
					 | 
				
			||||||
    const normalLoc = gl.getAttribLocation(program, 'aNormal');
 | 
					 | 
				
			||||||
    const textureLoc = gl.getAttribLocation(program, 'aTextureCoord');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const setupScene = (sceneParams) => {
 | 
					 | 
				
			||||||
        const {
 | 
					 | 
				
			||||||
            projectionMatrix,
 | 
					 | 
				
			||||||
            viewMatrix,
 | 
					 | 
				
			||||||
            ambiantLightAmount,
 | 
					 | 
				
			||||||
        } = sceneParams;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gl.useProgram(program);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gl.uniformMatrix4fv(projLoc, false, new Float32Array(projectionMatrix));
 | 
					 | 
				
			||||||
        gl.uniformMatrix4fv(viewLoc, false, new Float32Array(viewMatrix));
 | 
					 | 
				
			||||||
        gl.uniform1f(ambiantLoc, ambiantLightAmount);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // doing this here because it's the same for all world stuff
 | 
					 | 
				
			||||||
        gl.uniformMatrix4fv(modelLoc, false, new Float32Array(se3.identity()));
 | 
					 | 
				
			||||||
        gl.uniform1i(samplerLoc, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gl.enableVertexAttribArray(positionLoc);
 | 
					 | 
				
			||||||
        gl.enableVertexAttribArray(normalLoc);
 | 
					 | 
				
			||||||
        gl.enableVertexAttribArray(textureLoc);
 | 
					 | 
				
			||||||
        gl.activeTexture(gl.TEXTURE0);
 | 
					 | 
				
			||||||
        gl.bindTexture(gl.TEXTURE_2D, texture);
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const drawObject = (objectParams) => {
 | 
					 | 
				
			||||||
        const {
 | 
					 | 
				
			||||||
            position,
 | 
					 | 
				
			||||||
            orientation,
 | 
					 | 
				
			||||||
            glBuffer,
 | 
					 | 
				
			||||||
            numVertices,
 | 
					 | 
				
			||||||
            lightDirection,
 | 
					 | 
				
			||||||
            glowColor,
 | 
					 | 
				
			||||||
        } = objectParams;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gl.uniformMatrix4fv(modelLoc, false, new Float32Array(se3.product(
 | 
					 | 
				
			||||||
            se3.translation(...position), orientation)));
 | 
					 | 
				
			||||||
        gl.uniform3fv(lightDirectionLoc, lightDirection);
 | 
					 | 
				
			||||||
        gl.uniform3fv(glowColorLoc, glowColor);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gl.bindBuffer(gl.ARRAY_BUFFER, glBuffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 20, 0);
 | 
					 | 
				
			||||||
        gl.vertexAttribPointer(normalLoc, 3, gl.BYTE, true, 20, 12);
 | 
					 | 
				
			||||||
        gl.vertexAttribPointer(textureLoc, 2, gl.UNSIGNED_SHORT, true, 20, 16);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gl.drawArrays(gl.TRIANGLES, 0, numVertices);
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return {
 | 
					 | 
				
			||||||
        setupScene,
 | 
					 | 
				
			||||||
        drawObject,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const ORBIT_VSHADER = `
 | 
					 | 
				
			||||||
attribute vec3 aPosition;
 | 
					 | 
				
			||||||
attribute vec2 aValue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
uniform mat4 uProjection;
 | 
					 | 
				
			||||||
uniform mat4 uModel;
 | 
					 | 
				
			||||||
uniform mat4 uView;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
varying lowp vec2 vCoords;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void main() {
 | 
					 | 
				
			||||||
    highp mat4 modelview = uView * uModel;
 | 
					 | 
				
			||||||
    gl_Position = uProjection * modelview * vec4(aPosition, 1.0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    vCoords = aValue;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
`;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const ORBIT_FSHADER = `
 | 
					 | 
				
			||||||
varying lowp vec2 vCoords;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void main() {
 | 
					 | 
				
			||||||
  lowp float x = vCoords.x;
 | 
					 | 
				
			||||||
  lowp float y = vCoords.y;
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  lowp float f = sqrt(x * x + y * y);
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  if (f > 1.00) {
 | 
					 | 
				
			||||||
    discard;
 | 
					 | 
				
			||||||
  } else if (f < 0.98) {
 | 
					 | 
				
			||||||
    discard;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  gl_FragColor = vec4(1, .5, 0, 0.5);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
`;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function getOrbitDrawContext(gl) {
 | 
					 | 
				
			||||||
    const program = makeProgram(gl, ORBIT_VSHADER, ORBIT_FSHADER);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // load those ahead of time
 | 
					 | 
				
			||||||
    const viewLoc = gl.getUniformLocation(program, 'uView');
 | 
					 | 
				
			||||||
    const modelLoc = gl.getUniformLocation(program, 'uModel');
 | 
					 | 
				
			||||||
    const projLoc = gl.getUniformLocation(program, 'uProjection');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const positionLoc = gl.getAttribLocation(program, 'aPosition');
 | 
					 | 
				
			||||||
    const valueLoc = gl.getAttribLocation(program, 'aValue');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const setupScene = (sceneParams) => {
 | 
					 | 
				
			||||||
        const {
 | 
					 | 
				
			||||||
            projectionMatrix,
 | 
					 | 
				
			||||||
            viewMatrix,
 | 
					 | 
				
			||||||
        } = sceneParams;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gl.useProgram(program);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gl.uniformMatrix4fv(projLoc, false, new Float32Array(projectionMatrix));
 | 
					 | 
				
			||||||
        gl.uniformMatrix4fv(viewLoc, false, new Float32Array(viewMatrix));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // doing this here because it's the same for all world stuff
 | 
					 | 
				
			||||||
        gl.uniformMatrix4fv(modelLoc, false, new Float32Array(se3.identity()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gl.enableVertexAttribArray(positionLoc);
 | 
					 | 
				
			||||||
        gl.enableVertexAttribArray(valueLoc);
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const drawObject = (objectParams) => {
 | 
					 | 
				
			||||||
        const {
 | 
					 | 
				
			||||||
            position,
 | 
					 | 
				
			||||||
            orientation,
 | 
					 | 
				
			||||||
            value,
 | 
					 | 
				
			||||||
            glBuffer,
 | 
					 | 
				
			||||||
        } = objectParams;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gl.uniformMatrix4fv(modelLoc, false, new Float32Array(se3.product(
 | 
					 | 
				
			||||||
            se3.translation(...position), orientation)));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gl.bindBuffer(gl.ARRAY_BUFFER, glBuffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 20, 0);
 | 
					 | 
				
			||||||
        gl.vertexAttribPointer(valueLoc, 2, gl.FLOAT, false, 20, 12);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gl.disable(gl.CULL_FACE);
 | 
					 | 
				
			||||||
        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
 | 
					 | 
				
			||||||
        gl.enable(gl.CULL_FACE);
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return {
 | 
					 | 
				
			||||||
        setupScene,
 | 
					 | 
				
			||||||
        drawObject,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function closeToPlanet(context) {
 | 
					function closeToPlanet(context) {
 | 
				
			||||||
    const body = findSoi(context);
 | 
					    const body = findSoi(context.universe, context.player.position);
 | 
				
			||||||
    const relativePos = linalg.diff(context.player.position, body.position);
 | 
					    const relativePos = linalg.diff(context.player.position, body.position);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return linalg.norm(relativePos) < 20;
 | 
					    return linalg.norm(relativePos) < 20;
 | 
				
			||||||
@@ -531,103 +299,6 @@ function updatePhysics(time: number, context) {
 | 
				
			|||||||
function updateGeometry(context, timeout_ms = 10) {
 | 
					function updateGeometry(context, timeout_ms = 10) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getObjects(context, body, parentPosition = undefined) {
 | 
					 | 
				
			||||||
    const objects = [];
 | 
					 | 
				
			||||||
    const {gl, glContext, player} = context;
 | 
					 | 
				
			||||||
    const {position, orientation, glowColor} = body;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (body.glBuffer === undefined) {
 | 
					 | 
				
			||||||
        body.glBuffer = makeBufferFromFaces(gl, body.geometry);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    objects.push({
 | 
					 | 
				
			||||||
        geometry: body.glBuffer,
 | 
					 | 
				
			||||||
        orientation,
 | 
					 | 
				
			||||||
        position,
 | 
					 | 
				
			||||||
        glContext,
 | 
					 | 
				
			||||||
        glowColor,
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    if (parentPosition !== undefined) {
 | 
					 | 
				
			||||||
        const orbitObject = makeOrbitObject(gl, context.orbitGlContext, body.orbit, parentPosition);
 | 
					 | 
				
			||||||
        objects.push(orbitObject);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        const shipOrientation = [
 | 
					 | 
				
			||||||
            se3.rotationOnly(player.tf),
 | 
					 | 
				
			||||||
            se3.rotationOnly(context.camera.tf),
 | 
					 | 
				
			||||||
            se3.rotxyz(-Math.PI / 2, Math.PI / 2, Math.PI / 2),
 | 
					 | 
				
			||||||
        ].reduce(se3.product);
 | 
					 | 
				
			||||||
        const shipPos = player.position;
 | 
					 | 
				
			||||||
        objects.push({
 | 
					 | 
				
			||||||
            geometry: makeBufferFromFaces(gl, context.spaceship),
 | 
					 | 
				
			||||||
            orientation: shipOrientation,
 | 
					 | 
				
			||||||
            position: shipPos,
 | 
					 | 
				
			||||||
            glContext,
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (body.children !== undefined) {
 | 
					 | 
				
			||||||
        for (const child of body.children) {
 | 
					 | 
				
			||||||
            objects.push(...getObjects(context, child, position));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return objects;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function sunDirection(position: linalg.vec3) {
 | 
					 | 
				
			||||||
    return linalg.scale(position, 1/linalg.norm(position));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function draw(context) {
 | 
					 | 
				
			||||||
    const {gl, camera, player, universe, orbit, orbitGlContext, orbitBody} = context;
 | 
					 | 
				
			||||||
    const {skyColor, ambiantLight, projMatrix} = context;
 | 
					 | 
				
			||||||
    const objects = getObjects(context, universe); 
 | 
					 | 
				
			||||||
    if (orbit !== undefined && orbit.excentricity < 1) {
 | 
					 | 
				
			||||||
        objects.push(makeOrbitObject(gl, orbitGlContext, orbit, orbitBody.position));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gl.clearColor(...skyColor, 1.0);
 | 
					 | 
				
			||||||
    gl.clearDepth(1.0);
 | 
					 | 
				
			||||||
    gl.enable(gl.DEPTH_TEST);
 | 
					 | 
				
			||||||
    gl.depthFunc(gl.LEQUAL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gl.enable(gl.CULL_FACE);
 | 
					 | 
				
			||||||
    gl.cullFace(gl.BACK);
 | 
					 | 
				
			||||||
    gl.enable(gl.BLEND);
 | 
					 | 
				
			||||||
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const viewMatrix = se3.inverse([
 | 
					 | 
				
			||||||
        player.tf,  // player position & orientation
 | 
					 | 
				
			||||||
        camera.tf,  // camera orientation relative to player
 | 
					 | 
				
			||||||
        se3.translation(0, 1, 4),  // step back from the player
 | 
					 | 
				
			||||||
    ].reduce(se3.product));
 | 
					 | 
				
			||||||
    let lastGlContext;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (const {position, orientation, geometry, glContext, glowColor} of objects) {
 | 
					 | 
				
			||||||
        if (glContext !== lastGlContext) {
 | 
					 | 
				
			||||||
            glContext.setupScene({
 | 
					 | 
				
			||||||
                projectionMatrix: projMatrix,
 | 
					 | 
				
			||||||
                viewMatrix,
 | 
					 | 
				
			||||||
                ambiantLightAmount: ambiantLight,
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        lastGlContext = glContext;
 | 
					 | 
				
			||||||
        const lightDirection = sunDirection(position);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        glContext.drawObject({
 | 
					 | 
				
			||||||
            position,
 | 
					 | 
				
			||||||
            orientation,
 | 
					 | 
				
			||||||
            glBuffer: geometry.glBuffer,
 | 
					 | 
				
			||||||
            numVertices: geometry.numVertices,
 | 
					 | 
				
			||||||
            lightDirection,
 | 
					 | 
				
			||||||
            glowColor: glowColor || [0, 0, 0],
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function tick(time: number, context) {
 | 
					function tick(time: number, context) {
 | 
				
			||||||
    handleInput(context);
 | 
					    handleInput(context);
 | 
				
			||||||
    const simTime = time * 0.001 + context.timeOffset;
 | 
					    const simTime = time * 0.001 + context.timeOffset;
 | 
				
			||||||
@@ -723,4 +394,4 @@ async function main() {
 | 
				
			|||||||
    requestAnimationFrame(time => tick(time, context));
 | 
					    requestAnimationFrame(time => tick(time, context));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
window.onload = main;
 | 
					window.onload = main;
 | 
				
			||||||
		Reference in New Issue
	
	Block a user