124 lines
No EOL
4 KiB
TypeScript
124 lines
No EOL
4 KiB
TypeScript
import { vec3 } from "gl-matrix";
|
|
import { Drawer2D } from "./drawer2D";
|
|
import { Drawer3D } from "./drawer3D";
|
|
import { TriangleDrawer } from "./triangle_drawer";
|
|
|
|
class InputMap{
|
|
private pressedKey:Set<string>;
|
|
//private mouseLast : [number,number];
|
|
private mouseDelta : [number,number];
|
|
constructor(){
|
|
this.pressedKey = new Set<string>();
|
|
this.mouseDelta = [0,0];
|
|
}
|
|
registerHandler(){
|
|
const self = this;
|
|
document.addEventListener("keydown",(ev)=>{
|
|
if(self.pressedKey.has(ev.key)){
|
|
console.log(ev.key,"pressed");
|
|
}
|
|
self.pressedKey.add(ev.key);
|
|
});
|
|
document.addEventListener("keyup",(ev)=>{
|
|
const exist = self.pressedKey.delete(ev.key);
|
|
if(exist){
|
|
console.log(ev.key,"released");
|
|
}
|
|
});
|
|
}
|
|
isPressed(keyname:string){
|
|
return this.pressedKey.has(keyname);
|
|
}
|
|
}
|
|
|
|
/** get timestamp counter in millisecond*/
|
|
function getCurrentTime() : number{
|
|
return performance.now();
|
|
}
|
|
const MillisecondPerFrame = 1000/60;
|
|
export class CanvasApp{
|
|
readonly gl: WebGL2RenderingContext;
|
|
private n : number;
|
|
renderer: Drawer2D;
|
|
trenderer : TriangleDrawer;
|
|
r : Drawer3D;
|
|
inputMap: InputMap;
|
|
constructor(gl: WebGL2RenderingContext){
|
|
this.gl = gl;
|
|
this.renderer = new Drawer2D(gl);
|
|
this.trenderer = new TriangleDrawer(gl);
|
|
this.r = new Drawer3D(gl);
|
|
this.inputMap = new InputMap();
|
|
this.inputMap.registerHandler();
|
|
}
|
|
intialize():boolean{
|
|
this.renderer.prepare();
|
|
this.trenderer.prepare(this.gl);
|
|
this.r.init();
|
|
let escPressed = false;
|
|
document.addEventListener("mousemove",(ev)=>{
|
|
if(!escPressed){
|
|
this.r.camera.rotateRight(Math.PI / 180.0 * ev.movementX);
|
|
this.r.camera.rotateUp(Math.PI / 180.0 * ev.movementY);
|
|
}
|
|
});
|
|
document.addEventListener("keydown",(e)=>{
|
|
if(e.key == "Escape"){
|
|
escPressed = !escPressed;
|
|
}
|
|
});
|
|
this.gl.clearColor(0,0,0,0);
|
|
this.gl.clearDepth(1);
|
|
this.gl.enable(this.gl.DEPTH_TEST);
|
|
//this.gl.enable(this.gl.CULL_FACE);
|
|
return true;
|
|
}
|
|
handleInput(){
|
|
const Speed = 0.5;
|
|
let forward = this.r.camera.forward;
|
|
let right = this.r.camera.right;
|
|
vec3.scale(forward,forward,Speed);
|
|
vec3.scale(right,right,Speed);
|
|
if(this.inputMap.isPressed("d")){
|
|
vec3.add(this.r.camera.pos,this.r.camera.pos,right);
|
|
}
|
|
if(this.inputMap.isPressed("a")){
|
|
const r = vec3.create();
|
|
vec3.negate(r,right);
|
|
vec3.add(this.r.camera.pos,this.r.camera.pos,r);
|
|
}
|
|
if(this.inputMap.isPressed("w")){
|
|
vec3.add(this.r.camera.pos,this.r.camera.pos,forward);
|
|
}
|
|
if(this.inputMap.isPressed("s")){
|
|
const f = vec3.create();
|
|
vec3.negate(f,forward);
|
|
vec3.add(this.r.camera.pos,this.r.camera.pos,f);
|
|
}
|
|
}
|
|
startRun(synctime = 0){
|
|
const beforeLoop = getCurrentTime();
|
|
this.loop();
|
|
const afterLoop = getCurrentTime();
|
|
const delta = afterLoop - beforeLoop - synctime;
|
|
const delay = (delta < MillisecondPerFrame) ? (MillisecondPerFrame - delta) : 0;
|
|
setTimeout((()=>{
|
|
const afterWait = getCurrentTime();
|
|
this.startRun(afterWait - afterLoop - delay);
|
|
}).bind(this),delay);
|
|
}
|
|
loop(){
|
|
this.handleInput();
|
|
}
|
|
startDraw(){
|
|
this.drawScene(0);
|
|
}
|
|
drawScene(time:DOMHighResTimeStamp){
|
|
this.gl.viewport(0,0,this.gl.canvas.width,this.gl.canvas.height);
|
|
this.gl.clear(this.gl.COLOR_BUFFER_BIT|this.gl.DEPTH_BUFFER_BIT);
|
|
//this.renderer.draw(this.gl,{});
|
|
//this.trenderer.draw(this.gl,{});
|
|
this.r.draw(this.gl,{});
|
|
requestAnimationFrame(this.drawScene.bind(this));
|
|
}
|
|
}; |