Skip to content

Commit

Permalink
lesson 57 snapshot
Browse files Browse the repository at this point in the history
  • Loading branch information
sketchpunk committed Nov 21, 2017
1 parent a68c600 commit 3458cb2
Show file tree
Hide file tree
Showing 46 changed files with 6,803 additions and 0 deletions.
Binary file added lesson_057/fire-gs-atlas.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
61 changes: 61 additions & 0 deletions lesson_057/fungi/Fungi.js
@@ -0,0 +1,61 @@
import gl from "./gl.js";
import CameraOrbit from "./cameras/Orbit.js";
import GridFloor from "./primitives/GridFloor.js";
import Renderer from "./util/Renderer.js";
import RenderLoop from "./util/RenderLoop.js";
import VDebug from "./entities/VisualDebugger.js";
import {KBMCtrl, KBMCtrl_Viewport} from "./util/KBMCtrl.js"

export default{
render :Renderer, //Main Render Function
renderLoop :null, //Render loop
lblFPS :null, //Html Element reference to a tag to update text of FPS

mainCamera :null, //Main camera for the scene
ctrlCamera :null, //Keyboard and Mouse controls for the camera

debugLine :null, //Renderable used to help debug data or models
debugPoint :null, //Same but with points.

gridFloor :null, //Just a reference to the renderable for the grid floor.
scene :[], //Array that holds the heirarchy of transforms / renderables.

deltaTime :0,
sinceStart :0,

//Begin the GL Context
init:function(){ gl.set("FungiCanvas"); return this; },

//Build all the main objects needed to get a scene up and running
ready:function(renderHandler,opt){
this.mainCamera = new CameraOrbit().setPosition(0,0.5,4).setEulerDegrees(-15,10,0);
this.ctrlCamera = new KBMCtrl().addHandler("camera",new KBMCtrl_Viewport(this.mainCamera),true,true);

this.renderLoop = new RenderLoop(renderHandler);
this.lblFPS = document.getElementById("lblFPS");
setInterval(function(){ this.lblFPS.innerHTML = this.renderLoop.fps; }.bind(this),200);

this.gridFloor = GridFloor();
this.scene.push(this.gridFloor);

//Setup Features
if(opt){
if(opt & 1 == 1) this.scene.push( this.debugLine = new VDebug() ); //DEBUG LINE RENDERER
if(opt & 2 == 2) this.scene.push( this.debugPoint = new VDebug().drawPoints() ); //DEBUG POINT RENDERER
}
},

//Get a frame ready to be rendered.
update:function(){
this.mainCamera.update();

gl.UBOTransform.update(
"matCameraView",this.mainCamera.invertedLocalMatrix,
"posCamera",this.mainCamera.position,
"fTime",new Float32Array( [this.sinceStart] )
);

gl.clear();
return this;
}
}
151 changes: 151 additions & 0 deletions lesson_057/fungi/Maths.js
@@ -0,0 +1,151 @@
import Vec3 from "./maths/Vec3.js";
import Mat3 from "./maths/Mat3.js";
import Mat4 from "./maths/Mat4.js";
import Quat from "./maths/Quat.js";
import DualQuat from "./maths/DualQuat.js";

const DEG2RAD = Math.PI/180;
const RAD2DEG = 180/Math.PI;

//Normalize x value to x range, then normalize to lerp the z range.
function map(x, xMin,xMax, zMin,zMax){ return (x - xMin) / (xMax - xMin) * (zMax-zMin) + zMin; }

function clamp(v,min,max){ return Math.max(min,Math.min(max,v)); }

function smoothStep(edge1, edge2, val){ //https://en.wikipedia.org/wiki/Smoothstep
var x = Math.max(0, Math.min(1, (val-edge1)/(edge2-edge1)));
return x*x*(3-2*x);
}

//Get a number between A and B from a normalized number.
function lerp(a,b,t){ return a + t * (b-a); }

//From a point in space, closest spot to a 2D line
function closestPointToLine2D(x0,y0,x1,y1,px,py){
var dx = x1 - x0,
dy = y1 - y0,
t = ((px-x0)*dx + (py-y0)*dy) / (dx*dx+dy*dy),
x = x0 + (dx * t), //Util.lerp(x0, x1, t),
y = y0 + (dy * t); //Util.lerp(y0, y1, t);
return [x,y]
}

//From a point in space, closest spot to a 3D line
function closestPointToLine3D(a,b,p,out){
if(out == undefined) out = new Vec3();
var dx = b.x - a.x,
dy = b.y - a.y,
dz = a.z - a.z,
t = ((p.x-a.x)*dx + (p.y-a.y)*dy + (p.z-a.z)*dz) / (dx*dx+dy*dy+dz*dz),
x = a.x + (dx * t),
y = a.y + (dy * t),
z = a.z + (dz * t);
return out.set(x,y,z);
}

//Return back the two points that are closes on two infinite lines
//http://geomalgorithms.com/a07-_distance.html
function closestpoint_2Lines(A0,A1,B0,B1){
var u = A1.clone().sub(A0),
v = B1.clone().sub(B0),
w = A0.clone().sub(B0),
a = Vec3.dot(u,u), // always >= 0
b = Vec3.dot(u,v),
c = Vec3.dot(v,v), // always >= 0
d = Vec3.dot(u,w),
e = Vec3.dot(v,w),
D = a*c - b*b, // always >= 0
tU, tV;
//compute the line parameters of the two closest points
if(D < 0.000001){ // the lines are almost parallel
tU = 0.0;
tV = (b>c ? d/b : e/c); // use the largest denominator
}else{
tU = (b*e - c*d) / D;
tV = (a*e - b*d) / D;
}

//Calc Length
//Vector vLen = w + (uT * u) - (vT * v); // = L1(sc) - L2(tc)
//Float len = sqrt( dot(vLen,vLen) );

return [ u.scale(tU).add(A0), v.scale(tV).add(B0) ];
}

//Return back the two points that are the closests but bound by the limit of two segments
//http://geomalgorithms.com/a07-_distance.html
function closestPointS_2Segments(A0,A1,B0,B1){
var u = A1.clone().sub(A0),
v = B1.clone().sub(B0),
w = A0.clone().sub(B0),
a = Vec3.dot(u,u), // always >= 0
b = Vec3.dot(u,v),
c = Vec3.dot(v,v), // always >= 0
d = Vec3.dot(u,w),
e = Vec3.dot(v,w),
D = a*c - b*b, // always >= 0
sc, sN, sD = D, // sc = sN / sD, default sD = D >= 0
tc, tN, tD = D; // tc = tN / tD, default tD = D >= 0

// compute the line parameters of the two closest points
if(D < 0.000001){ // the lines are almost parallel
sN = 0.0; // force using point P0 on segment S1
sD = 1.0; // to prevent possible division by 0.0 later
tN = e;
tD = c;
}else{ // get the closest points on the infinite lines
sN = (b*e - c*d);
tN = (a*e - b*d);
if(sN < 0.0){ // sc < 0 => the s=0 edge is visible
sN = 0.0;
tN = e;
tD = c;
}else if (sN > sD){ // sc > 1 => the s=1 edge is visible
sN = sD;
tN = e + b;
tD = c;
}
}

if (tN < 0.0){ // tc < 0 => the t=0 edge is visible
tN = 0.0;
// recompute sc for this edge
if (-d < 0.0) sN = 0.0;
else if (-d > a) sN = sD;
else{
sN = -d;
sD = a;
}
}else if(tN > tD){ // tc > 1 => the t=1 edge is visible
tN = tD;
// recompute sc for this edge
if((-d + b) < 0.0) sN = 0;
else if ((-d + b) > a) sN = sD;
else{
sN = (-d + b);
sD = a;
}
}

// finally do the division to get sc and tc
sc = (Math.abs(sN) < 0.000001 ? 0.0 : sN / sD);
tc = (Math.abs(tN) < 0.000001 ? 0.0 : tN / tD);

// get the difference of the two closest points
//Vector dP = w + (sc * u) - (tc * v); // = S1(sc) - S2(tc)

return [ u.scale(sc).add(A0), v.scale(tc).add(B0) ];
}


export default { DEG2RAD:DEG2RAD, RAD2DEG:RAD2DEG,
map:map,
clamp:clamp,
smoothStep:smoothStep,
closestPointToLine2D:closestPointToLine2D,
closestPointToLine3D:closestPointToLine3D,
closestpoint_2Lines:closestpoint_2Lines,
closestPointS_2Segments:closestPointS_2Segments,
}

export { Vec3, Mat3, Mat4, Quat, DualQuat, DEG2RAD, RAD2DEG }
80 changes: 80 additions & 0 deletions lesson_057/fungi/cameras/Orbit.js
@@ -0,0 +1,80 @@
import gl from "../gl.js";
import fungi from "../fungi.js";
import Transform from "../entities/Transform.js";
import {Vec3, Mat4, Quat, DEG2RAD} from "../Maths.js";

class Orbit extends Transform{
constructor(fov,near,far){
super();
//Setup the projection and invert matrices
this.projectionMatrix = new Float32Array(16);
this.invertedProjectionMatrix = new Float32Array(16);
this.invertedLocalMatrix = new Float32Array(16);

var ratio = gl.ctx.canvas.width / gl.ctx.canvas.height;
Mat4.perspective(this.projectionMatrix, fov || 45, ratio, near || 0.1, far || 100.0);
Mat4.invert(this.invertedProjectionMatrix, this.projectionMatrix); //Save Inverted version for Ray Casting.

gl.UBOTransform.update("matProjection",this.projectionMatrix); //Initialize The Transform UBO.

//Orbit Camera will control things based on euler, its cheating but not ready for quaternions
this.euler = new Vec3();
}

//Override how this transfer creates the localMatrix : Call Update, not this function in render loop.
updateMatrix(){
//Only Update the Matrix if its needed.
//if(!this.position.isModified && !this.rotation.isModified && !this.euler.isModified) return this.localMatrix;

Quat.setFromEuler(this.rotation,this.euler.x,this.euler.y,this.euler.z,"YXZ");
Mat4.fromQuaternion(this.localMatrix,this.rotation);
this.localMatrix.resetTranslation().translate(this.position);

//Set the modified indicator to false on all the transforms.
this.position.isModified = false;
this.rotation.isModified = false;
this.euler.isModified = false;
return this.localMatrix;
}

//Update the Matrices and UBO.
update(){
if(this.position.isModified || this.scale.isModified || this.euler.isModified){
this.updateMatrix();
Mat4.invert(this.invertedLocalMatrix,this.localMatrix);
}
}

setEulerDegrees(x,y,z){ this.euler.set(x * DEG2RAD,y * DEG2RAD,z * DEG2RAD); return this; }

worldToScreen(vAry){
var mat = new Float32Array(16), // Matrix4 Holder
p = [0,0,0,0], // Vec4
rtn = []; // List of vec2 results

//Move Points from WorldSpace to -> View Space (View Matrix) -> ClipSpace (ProjMatrix)
Mat4.mult(mat,this.projectionMatrix,this.invertedLocalMatrix);

for(var i=0; i < vAry.length; i++){
Mat4.transformVec3(p, vAry[i], mat);

//Move from Clip Space to NDC Space (Normalized Device Coordinate Space) (-1 to 1 opengl viewport)
if(p[3] != 0){ //only if W is not zero,
p[0] = p[0] / p[3];
p[1] = p[1] / p[3];
}

//Then finally move the points to Screen Space
//Map points from -1 to 1 range into 0 to 1 range, Then multiple by canvas size
rtn.push( // Replaced /2 with *0.5
( p[0] + 1) * 0.5 * gl.width,
(-p[1] + 1) * 0.5 * gl.height
);
}

if(vAry.length == 1) return rtn[0]; //Just return the one point
return rtn; //Return all the points
}
}

export default Orbit;

0 comments on commit 3458cb2

Please sign in to comment.