camera and moving
This commit is contained in:
		
							parent
							
								
									1e6314fcdd
								
							
						
					
					
						commit
						652e0d7c96
					
				
					 4 changed files with 156 additions and 72 deletions
				
			
		
							
								
								
									
										115
									
								
								src/app.ts
									
										
									
									
									
								
							
							
						
						
									
										115
									
								
								src/app.ts
									
										
									
									
									
								
							| 
						 | 
					@ -1,71 +1,118 @@
 | 
				
			||||||
 | 
					import { vec3 } from "gl-matrix";
 | 
				
			||||||
import { Drawer2D } from "./drawer2D";
 | 
					import { Drawer2D } from "./drawer2D";
 | 
				
			||||||
import { Drawer3D } from "./drawer3D";
 | 
					import { Drawer3D } from "./drawer3D";
 | 
				
			||||||
import { TriangleDrawer } from "./triangle_drawer";
 | 
					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{
 | 
					export class CanvasApp{
 | 
				
			||||||
    readonly gl: WebGL2RenderingContext;
 | 
					    readonly gl: WebGL2RenderingContext;
 | 
				
			||||||
 | 
					    private n : number;
 | 
				
			||||||
    renderer: Drawer2D;
 | 
					    renderer: Drawer2D;
 | 
				
			||||||
    trenderer : TriangleDrawer;
 | 
					    trenderer : TriangleDrawer;
 | 
				
			||||||
    r : Drawer3D;
 | 
					    r : Drawer3D;
 | 
				
			||||||
 | 
					    inputMap: InputMap;
 | 
				
			||||||
    constructor(gl: WebGL2RenderingContext){
 | 
					    constructor(gl: WebGL2RenderingContext){
 | 
				
			||||||
        this.gl = gl;
 | 
					        this.gl = gl;
 | 
				
			||||||
        this.renderer = new Drawer2D(gl);
 | 
					        this.renderer = new Drawer2D(gl);
 | 
				
			||||||
        this.trenderer = new TriangleDrawer(gl);
 | 
					        this.trenderer = new TriangleDrawer(gl);
 | 
				
			||||||
        this.r = new Drawer3D(gl);
 | 
					        this.r = new Drawer3D(gl);
 | 
				
			||||||
 | 
					        this.inputMap = new InputMap();
 | 
				
			||||||
 | 
					        this.inputMap.registerHandler();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    intialize():boolean{
 | 
					    intialize():boolean{
 | 
				
			||||||
        this.renderer.prepare();
 | 
					        this.renderer.prepare();
 | 
				
			||||||
        this.trenderer.prepare(this.gl);
 | 
					        this.trenderer.prepare(this.gl);
 | 
				
			||||||
        this.r.init();
 | 
					        this.r.init();
 | 
				
			||||||
 | 
					        let escPressed = false;
 | 
				
			||||||
        document.addEventListener("keydown",(e)=>{
 | 
					        document.addEventListener("mousemove",(ev)=>{
 | 
				
			||||||
            if(e.key == "h"){
 | 
					            if(!escPressed){
 | 
				
			||||||
                this.r.camera.rotateRight(Math.PI * 5 / 180.0);
 | 
					                this.r.camera.rotateRight(Math.PI / 180.0 * ev.movementX);
 | 
				
			||||||
            }
 | 
					                this.r.camera.rotateUp(Math.PI / 180.0 * ev.movementY);
 | 
				
			||||||
            if(e.key == "f"){
 | 
					            }
 | 
				
			||||||
                this.r.camera.rotateRight(-Math.PI * 5 / 180.0)
 | 
					        });
 | 
				
			||||||
            }
 | 
					        document.addEventListener("keydown",(e)=>{
 | 
				
			||||||
            if(e.key == "t"){
 | 
					            if(e.key == "Escape"){
 | 
				
			||||||
                this.r.camera.rotateUp(Math.PI * 5 / 180.0)
 | 
					                escPressed = !escPressed;
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if(e.key == "g"){
 | 
					 | 
				
			||||||
                this.r.camera.rotateUp(-Math.PI * 5 / 180.0)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if(e.key == "d"){
 | 
					 | 
				
			||||||
                this.r.camera.pos[0] += 0.5;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if(e.key == "a"){
 | 
					 | 
				
			||||||
                this.r.camera.pos[0] -= 0.5;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if(e.key == "w"){
 | 
					 | 
				
			||||||
                this.r.camera.pos[2] += 0.5;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if(e.key == "s"){
 | 
					 | 
				
			||||||
                this.r.camera.pos[2] -= 0.5;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.gl.clearColor(0,0,0,0);
 | 
					        this.gl.clearColor(0,0,0,0);
 | 
				
			||||||
        this.gl.clearDepth(1);
 | 
					        this.gl.clearDepth(1);
 | 
				
			||||||
        this.gl.enable(this.gl.DEPTH_TEST);
 | 
					        this.gl.enable(this.gl.DEPTH_TEST);
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    startRun(){
 | 
					    handleInput(){
 | 
				
			||||||
        const current = new Date();
 | 
					        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();
 | 
					        this.loop();
 | 
				
			||||||
        const delta = (new Date().getMilliseconds()) - current.getMilliseconds();
 | 
					        const afterLoop = getCurrentTime();
 | 
				
			||||||
        const delay = (delta < 16) ? (16 - delta) : 1;
 | 
					        const delta = afterLoop - beforeLoop - synctime;
 | 
				
			||||||
 | 
					        const delay = (delta < MillisecondPerFrame) ? (MillisecondPerFrame - delta) : 0;
 | 
				
			||||||
        setTimeout((()=>{
 | 
					        setTimeout((()=>{
 | 
				
			||||||
            this.startRun();
 | 
					            const afterWait = getCurrentTime();
 | 
				
			||||||
 | 
					            this.startRun(afterWait - afterLoop - delay);
 | 
				
			||||||
        }).bind(this),delay);
 | 
					        }).bind(this),delay);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    loop(){
 | 
					    loop(){
 | 
				
			||||||
        
 | 
					        this.handleInput();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    startDraw(){
 | 
					    startDraw(){
 | 
				
			||||||
        this.drawScene();
 | 
					        this.drawScene(0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    drawScene(){
 | 
					    drawScene(time:DOMHighResTimeStamp){
 | 
				
			||||||
        this.gl.viewport(0,0,this.gl.canvas.width,this.gl.canvas.height);
 | 
					        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.gl.clear(this.gl.COLOR_BUFFER_BIT|this.gl.DEPTH_BUFFER_BIT);
 | 
				
			||||||
        //this.renderer.draw(this.gl,{});
 | 
					        //this.renderer.draw(this.gl,{});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,49 +1,82 @@
 | 
				
			||||||
import {mat4, vec3, quat, mat3} from "gl-matrix";
 | 
					import { mat4, vec3, quat, mat3 } from "gl-matrix";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class Camera{
 | 
					export class Camera {
 | 
				
			||||||
    pos:vec3;
 | 
					    pos: vec3;
 | 
				
			||||||
    rot:quat;
 | 
					
 | 
				
			||||||
    #proj : mat4;
 | 
					    yaw: number;
 | 
				
			||||||
    fovY : number;
 | 
					    pitch: number;
 | 
				
			||||||
    aspect : number;
 | 
					    roll: number;
 | 
				
			||||||
    far : number;
 | 
					
 | 
				
			||||||
 | 
					    #proj: mat4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fovY: number;
 | 
				
			||||||
 | 
					    aspect: number;
 | 
				
			||||||
 | 
					    far: number;
 | 
				
			||||||
    near: number;
 | 
					    near: number;
 | 
				
			||||||
    constructor(pos:vec3,rot?:quat){
 | 
					    constructor(pos: vec3) {
 | 
				
			||||||
        this.pos = pos;
 | 
					        this.pos = pos;
 | 
				
			||||||
        this.#proj = mat4.create();
 | 
					        this.#proj = mat4.create();
 | 
				
			||||||
        if(rot == undefined){
 | 
					        this.yaw = 0;
 | 
				
			||||||
            const lookAt = mat4.lookAt(mat4.create(),this.pos,[0,0,0],[0,1,0]);
 | 
					        this.pitch = 0;
 | 
				
			||||||
            const rotMat = mat3.fromMat4(mat3.create(),lookAt);
 | 
					        this.roll = 0;
 | 
				
			||||||
            this.rot = quat.fromMat3(quat.create(), rotMat);
 | 
					        console.log("forward" , this.forward);
 | 
				
			||||||
            //quat.normalize(this.rot,this.rot);
 | 
					        console.log("up" , this.up);
 | 
				
			||||||
            //quat.conjugate(this.rot,this.rot);
 | 
					    }
 | 
				
			||||||
        }
 | 
					    rotateRight(rad: number) {
 | 
				
			||||||
        else{
 | 
					        this.yaw += rad;
 | 
				
			||||||
            this.rot = rot;
 | 
					        if(this.yaw >= Math.PI * 2 ){
 | 
				
			||||||
 | 
					            this.yaw -= Math.PI * 2;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    rotateRight(rad:number){
 | 
					    rotateUp(rad: number) {
 | 
				
			||||||
        quat.rotateY(this.rot,this.rot,rad);
 | 
					        this.pitch += rad;
 | 
				
			||||||
 | 
					        this.pitch = Math.min(this.pitch, Math.PI * 89/ 180);
 | 
				
			||||||
 | 
					        this.pitch = Math.max(this.pitch, - Math.PI * 89 / 180);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    rotateUp(rad:number){
 | 
					    rotateClockwise(rad: number) {
 | 
				
			||||||
        quat.rotateZ(this.rot,this.rot,rad);
 | 
					        this.roll += rad;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    rotateClockwise(rad:number){
 | 
					    get viewMatrix(): mat4 {
 | 
				
			||||||
        quat.rotateX(this.rot,this.rot,rad);
 | 
					        const eye = vec3.create();
 | 
				
			||||||
    }
 | 
					        const lookAt = mat4.create();
 | 
				
			||||||
    get viewMatrix():mat4{
 | 
					        vec3.add(eye, this.pos, this.forward);
 | 
				
			||||||
        const p = vec3.negate(vec3.create() ,this.pos);
 | 
					        return mat4.lookAt(lookAt, this.pos, eye, this.up);
 | 
				
			||||||
        const t = mat4.fromTranslation(mat4.create(),p);
 | 
					 | 
				
			||||||
        const r = mat4.fromQuat(mat4.create(),this.rot);
 | 
					 | 
				
			||||||
        return mat4.mul(mat4.create(),r,t);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * update projection matrix
 | 
					     * update projection matrix
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    UpdateProjectionMat(){
 | 
					    UpdateProjectionMat() {
 | 
				
			||||||
        mat4.perspective(this.#proj,this.fovY,this.aspect,this.near,this.far);
 | 
					        mat4.perspective(this.#proj, this.fovY, this.aspect, this.near, this.far);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    get projectionMatrix():mat4{
 | 
					    get projectionMatrix(): mat4 {
 | 
				
			||||||
        return this.#proj;
 | 
					        return this.#proj;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    get forward(): vec3 {
 | 
				
			||||||
 | 
					        const sinYaw = -Math.sin(this.yaw);
 | 
				
			||||||
 | 
					        const cosYaw = Math.cos(this.yaw);
 | 
				
			||||||
 | 
					        const ret = vec3.fromValues(sinYaw * Math.cos(this.pitch), -Math.sin(this.pitch), cosYaw * Math.cos(this.pitch));
 | 
				
			||||||
 | 
					        vec3.normalize(ret,ret);
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    get up(): vec3 {
 | 
				
			||||||
 | 
					        const right = vec3.cross(vec3.create(),this.forward,[0,1,0]);
 | 
				
			||||||
 | 
					        vec3.normalize(right,right);
 | 
				
			||||||
 | 
					        const ret = vec3.cross(vec3.create(),right,this.forward);
 | 
				
			||||||
 | 
					        vec3.normalize(ret,ret);
 | 
				
			||||||
 | 
					        /*const a = Math.sin(this.yaw);
 | 
				
			||||||
 | 
					        const b = Math.cos(this.yaw);
 | 
				
			||||||
 | 
					        const u = vec3.fromValues(b * Math.sin(this.pitch), Math.cos(this.pitch), a * Math.sin(this.pitch));
 | 
				
			||||||
 | 
					        const v = vec3.create();
 | 
				
			||||||
 | 
					        vec3.cross(v, u, this.forward);
 | 
				
			||||||
 | 
					        const ret = vec3.create();
 | 
				
			||||||
 | 
					        const tmp1 = vec3.create();
 | 
				
			||||||
 | 
					        const tmp2 = vec3.create();
 | 
				
			||||||
 | 
					        vec3.add(ret, vec3.scale(tmp1, u, Math.cos(this.roll)), vec3.scale(tmp2, v, -Math.sin(this.roll)));*/
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    get right(): vec3 {
 | 
				
			||||||
 | 
					        const ret = vec3.create();
 | 
				
			||||||
 | 
					        vec3.cross(ret, this.up, this.forward)
 | 
				
			||||||
 | 
					        return vec3.cross(vec3.create(),this.forward,[0,1,0]);;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ import { Camera } from "./camera";
 | 
				
			||||||
import * as G from "./glWrapper";
 | 
					import * as G from "./glWrapper";
 | 
				
			||||||
import { Drawable, RenderState } from "./drawable";
 | 
					import { Drawable, RenderState } from "./drawable";
 | 
				
			||||||
import { Model } from "./model";
 | 
					import { Model } from "./model";
 | 
				
			||||||
import { mat4 } from "gl-matrix";
 | 
					import { mat4, vec3 } from "gl-matrix";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class Drawer3D implements Drawable{
 | 
					export class Drawer3D implements Drawable{
 | 
				
			||||||
| 
						 | 
					@ -52,9 +52,11 @@ export class Drawer3D implements Drawable{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.program.setUniformMat4f(gl,"viewMat",this.camera.viewMatrix);
 | 
					            this.program.setUniformMat4f(gl,"viewMat",this.camera.viewMatrix);
 | 
				
			||||||
            this.program.setUniformMat4f(gl,"projectionMat",this.camera.projectionMatrix);
 | 
					            this.program.setUniformMat4f(gl,"projectionMat",this.camera.projectionMatrix);
 | 
				
			||||||
            this.program.setUniformMat4f(gl,"modelMat",mat4.fromTranslation(mat4.create(),[0,0,0]));
 | 
					            for(const pos of [[0,0,0],[0,0,25],[40,0,25]]){
 | 
				
			||||||
            
 | 
					                this.program.setUniformMat4f(gl,"modelMat",mat4.fromTranslation(mat4.create(), vec3.fromValues(pos[0],pos[1],pos[2]) ));
 | 
				
			||||||
            this.model.draw(gl);
 | 
					                
 | 
				
			||||||
 | 
					                this.model.draw(gl);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -43,7 +43,9 @@ export class Model{
 | 
				
			||||||
        for(const [name,buf] of Object.entries(this.vertexes)){
 | 
					        for(const [name,buf] of Object.entries(this.vertexes)){
 | 
				
			||||||
            const loc = p.getAttribLocation(gl,name);
 | 
					            const loc = p.getAttribLocation(gl,name);
 | 
				
			||||||
            assertBoolean(loc >= 0,"there is no",name,"attribute");
 | 
					            assertBoolean(loc >= 0,"there is no",name,"attribute");
 | 
				
			||||||
            this.vao.addBuffer(gl,buf,loc,VertexLayouts[name]);
 | 
					            if(loc >= 0){
 | 
				
			||||||
 | 
					                this.vao.addBuffer(gl,buf,loc,VertexLayouts[name]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this.ibo.bind(gl);
 | 
					        this.ibo.bind(gl);
 | 
				
			||||||
        this.vao.unbind(gl);
 | 
					        this.vao.unbind(gl);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue