blobt
4 years ago
3 changed files with 515 additions and 0 deletions
@ -0,0 +1,488 @@ |
|||||
|
import { vec3, mat4, Util } from "../math" |
||||
|
import { EMatrixMode } from "../common"; |
||||
|
|
||||
|
export class GLMatrixStack { |
||||
|
/** |
||||
|
* @var |
||||
|
* model view matrix stack |
||||
|
*/ |
||||
|
private _mvStack: mat4[]; |
||||
|
|
||||
|
/** |
||||
|
* @var |
||||
|
* projection matrix stack |
||||
|
*/ |
||||
|
private _projStack: mat4[]; |
||||
|
|
||||
|
/** |
||||
|
* @var |
||||
|
*/ |
||||
|
private _texStack: mat4[]; |
||||
|
|
||||
|
/** |
||||
|
* @var |
||||
|
*/ |
||||
|
public matrixMode: EMatrixMode; |
||||
|
|
||||
|
public constructor() { |
||||
|
this._mvStack = []; |
||||
|
this._mvStack.push(new mat4()); |
||||
|
|
||||
|
this._projStack = []; |
||||
|
this._projStack.push(new mat4()); |
||||
|
|
||||
|
this._texStack = []; |
||||
|
this._texStack.push(new mat4()); |
||||
|
|
||||
|
this.matrixMode = EMatrixMode.MODELVIEW; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取 最后一个model view矩阵 |
||||
|
*/ |
||||
|
public get modelViewMatrix(): mat4 { |
||||
|
if (this._mvStack.length <= 0) { |
||||
|
throw new Error("model view matrix stack empty!"); |
||||
|
} |
||||
|
return this._mvStack[this._mvStack.length - 1]; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取最后一个projection 矩阵 |
||||
|
*/ |
||||
|
public get projectionMatrix(): mat4 { |
||||
|
if (this._projStack.length <= 0) { |
||||
|
throw new Error("projection matrix stack empty!"); |
||||
|
} |
||||
|
return this._projStack[this._mvStack.length - 1]; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取最后一个projection 矩阵 |
||||
|
*/ |
||||
|
public get textureMatrix(): mat4 { |
||||
|
if (this._texStack.length <= 0) { |
||||
|
throw new Error("texture matrix stack empty!"); |
||||
|
} |
||||
|
return this._texStack[this._mvStack.length - 1]; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取视图投影矩阵 |
||||
|
*/ |
||||
|
public get modelViewProjectionMatrix(): mat4 { |
||||
|
let ret: mat4 = new mat4(); |
||||
|
this.projectionMatrix.copy(ret); |
||||
|
ret.multiply(this.modelViewMatrix); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取法向矩阵 |
||||
|
*/ |
||||
|
public get normalMatrix(): mat4 { |
||||
|
let ret: mat4 = new mat4(); |
||||
|
this.modelViewMatrix.copy(ret); |
||||
|
this.modelViewMatrix.inverse(ret); |
||||
|
ret.transpose(); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @returns |
||||
|
*/ |
||||
|
public pushMatrix(): GLMatrixStack { |
||||
|
switch (this.matrixMode) { |
||||
|
case EMatrixMode.MODELVIEW: |
||||
|
let mv: mat4 = new mat4(); |
||||
|
this.modelViewMatrix.copy(mv); |
||||
|
this._mvStack.push(mv); |
||||
|
break; |
||||
|
case EMatrixMode.PROJECTION: |
||||
|
let proj = new mat4(); |
||||
|
this.projectionMatrix.copy(proj); |
||||
|
this._projStack.push(proj); |
||||
|
break; |
||||
|
case EMatrixMode.TEXTURE: |
||||
|
let tex: mat4 = new mat4(); |
||||
|
this.textureMatrix.copy(tex); |
||||
|
this._texStack.push(tex); |
||||
|
break; |
||||
|
} |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @returns |
||||
|
*/ |
||||
|
public popMatrix(): GLMatrixStack { |
||||
|
switch (this.matrixMode) { |
||||
|
case EMatrixMode.MODELVIEW: |
||||
|
this._mvStack.pop(); |
||||
|
break; |
||||
|
case EMatrixMode.PROJECTION: |
||||
|
this._projStack.pop(); |
||||
|
break; |
||||
|
case EMatrixMode.TEXTURE: |
||||
|
this._texStack.pop(); |
||||
|
break; |
||||
|
} |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @param mat |
||||
|
* @returns |
||||
|
*/ |
||||
|
public loadIdentity(): GLMatrixStack { |
||||
|
switch (this.matrixMode) { |
||||
|
case EMatrixMode.MODELVIEW: |
||||
|
this.modelViewMatrix.setIdentity(); |
||||
|
break; |
||||
|
case EMatrixMode.PROJECTION: |
||||
|
this.projectionMatrix.setIdentity(); |
||||
|
break; |
||||
|
case EMatrixMode.TEXTURE: |
||||
|
this.textureMatrix.setIdentity(); |
||||
|
break; |
||||
|
} |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 载入矩阵 |
||||
|
* @param mat |
||||
|
* @returns |
||||
|
*/ |
||||
|
public loadMatrix(mat: mat4): GLMatrixStack { |
||||
|
switch (this.matrixMode) { |
||||
|
case EMatrixMode.MODELVIEW: |
||||
|
mat.copy(this.modelViewMatrix); |
||||
|
break; |
||||
|
case EMatrixMode.PROJECTION: |
||||
|
mat.copy(this.projectionMatrix); |
||||
|
break; |
||||
|
case EMatrixMode.TEXTURE: |
||||
|
mat.copy(this.textureMatrix); |
||||
|
break; |
||||
|
} |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成透视投影 |
||||
|
* @param fov |
||||
|
* @param aspect |
||||
|
* @param near |
||||
|
* @param far |
||||
|
* @param isRadians |
||||
|
* @returns |
||||
|
*/ |
||||
|
public perspective(fov: number, aspect: number, near: number, far: number, isRadians: boolean = false): GLMatrixStack { |
||||
|
this.matrixMode = EMatrixMode.PROJECTION; |
||||
|
if (isRadians == false) { |
||||
|
fov = Util.toRadian(fov); |
||||
|
} |
||||
|
let mat: mat4 = mat4.perspective(fov, aspect, near, far); |
||||
|
this.loadMatrix(mat); |
||||
|
this.matrixMode = EMatrixMode.MODELVIEW; |
||||
|
// 是否要调用loadIdentity方法???
|
||||
|
this.loadIdentity(); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成视锥体 |
||||
|
* @param left |
||||
|
* @param right |
||||
|
* @param bottom |
||||
|
* @param top |
||||
|
* @param near |
||||
|
* @param far |
||||
|
* @returns |
||||
|
*/ |
||||
|
public frustum(left: number, right: number, bottom: number, top: number, near: number, far: number): GLMatrixStack { |
||||
|
this.matrixMode = EMatrixMode.PROJECTION; |
||||
|
let mat: mat4 = mat4.frustum(left, right, bottom, top, near, far); |
||||
|
this.matrixMode = EMatrixMode.MODELVIEW; |
||||
|
// 是否要调用loadIdentity方法???
|
||||
|
this.loadIdentity(); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成正交投影 |
||||
|
* @param left |
||||
|
* @param right |
||||
|
* @param bottom |
||||
|
* @param top |
||||
|
* @param near |
||||
|
* @param far |
||||
|
* @returns |
||||
|
*/ |
||||
|
public ortho(left: number, right: number, bottom: number, top: number, near: number, far: number): GLMatrixStack { |
||||
|
this.matrixMode = EMatrixMode.PROJECTION; |
||||
|
let mat: mat4 = mat4.orthographic(left, right, bottom, top, near, far); |
||||
|
this.loadMatrix(mat); |
||||
|
this.matrixMode = EMatrixMode.MODELVIEW; |
||||
|
// 是否要调用loadIdentity方法???
|
||||
|
this.loadIdentity(); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成lookat矩阵 |
||||
|
* @param pos |
||||
|
* @param target |
||||
|
* @param up |
||||
|
* @returns |
||||
|
*/ |
||||
|
public lookAt(pos: vec3, target: vec3, up: vec3 = vec3.up): GLMatrixStack { |
||||
|
this.matrixMode = EMatrixMode.MODELVIEW; |
||||
|
let mat: mat4 = mat4.lookAt(pos, target, up); |
||||
|
this.loadMatrix(mat); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 创建视图矩阵 |
||||
|
* @param pos |
||||
|
* @param xAxis |
||||
|
* @param yAxis |
||||
|
* @param zAxis |
||||
|
* @returns |
||||
|
*/ |
||||
|
public makeView(pos: vec3, xAxis: vec3, yAxis: vec3, zAxis: vec3): GLMatrixStack { |
||||
|
|
||||
|
zAxis.normalize(); |
||||
|
|
||||
|
vec3.cross(zAxis, xAxis, yAxis); |
||||
|
yAxis.normalize(); |
||||
|
|
||||
|
vec3.cross(yAxis, zAxis, xAxis); |
||||
|
xAxis.normalize(); |
||||
|
|
||||
|
let x: number = -vec3.dot(xAxis, pos); |
||||
|
let y: number = -vec3.dot(yAxis, pos); |
||||
|
let z: number = -vec3.dot(zAxis, pos); |
||||
|
|
||||
|
let mat: mat4 = this._mvStack[this._mvStack.length - 1]; |
||||
|
|
||||
|
mat.values[0] = xAxis.x; |
||||
|
mat.values[1] = yAxis.x; |
||||
|
mat.values[2] = zAxis.x; |
||||
|
mat.values[3] = 0.0; |
||||
|
|
||||
|
mat.values[4] = xAxis.y; |
||||
|
mat.values[5] = yAxis.y; |
||||
|
mat.values[6] = zAxis.y; |
||||
|
mat.values[7] = 0.0; |
||||
|
|
||||
|
mat.values[8] = xAxis.z; |
||||
|
mat.values[9] = yAxis.z; |
||||
|
mat.values[10] = zAxis.z; |
||||
|
mat.values[11] = 0.0; |
||||
|
|
||||
|
mat.values[12] = x; |
||||
|
mat.values[13] = y; |
||||
|
mat.values[14] = z; |
||||
|
mat.values[15] = 1.0; |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 矩阵乘 |
||||
|
* @param mat |
||||
|
* @returns |
||||
|
*/ |
||||
|
public multMatrix(mat: mat4): GLMatrixStack { |
||||
|
switch (this.matrixMode) { |
||||
|
case EMatrixMode.MODELVIEW: |
||||
|
this.modelViewMatrix.multiply(mat); |
||||
|
break; |
||||
|
case EMatrixMode.PROJECTION: |
||||
|
this.projectionMatrix.multiply(mat); |
||||
|
break; |
||||
|
case EMatrixMode.TEXTURE: |
||||
|
this.textureMatrix.multiply(mat); |
||||
|
break; |
||||
|
} |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 变换 |
||||
|
* @param pos |
||||
|
* @returns |
||||
|
*/ |
||||
|
public translate(pos: vec3): GLMatrixStack { |
||||
|
switch (this.matrixMode) { |
||||
|
case EMatrixMode.MODELVIEW: |
||||
|
this.modelViewMatrix.translate(pos); |
||||
|
break; |
||||
|
case EMatrixMode.PROJECTION: |
||||
|
this.projectionMatrix.translate(pos); |
||||
|
break; |
||||
|
case EMatrixMode.TEXTURE: |
||||
|
this.textureMatrix.translate(pos); |
||||
|
break; |
||||
|
} |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 旋转 |
||||
|
* @param angle |
||||
|
* @param axis |
||||
|
* @param isRadians |
||||
|
* @returns |
||||
|
*/ |
||||
|
public rotate(angle: number, axis: vec3, isRadians: boolean = false): GLMatrixStack { |
||||
|
if (isRadians === false) { |
||||
|
angle = Util.toRadian(angle); |
||||
|
} |
||||
|
|
||||
|
switch (this.matrixMode) { |
||||
|
case EMatrixMode.MODELVIEW: |
||||
|
this.modelViewMatrix.rotate(angle, axis); |
||||
|
break; |
||||
|
case EMatrixMode.PROJECTION: |
||||
|
this.projectionMatrix.rotate(angle, axis); |
||||
|
break; |
||||
|
case EMatrixMode.TEXTURE: |
||||
|
this.textureMatrix.rotate(angle, axis); |
||||
|
break; |
||||
|
} |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 缩放 |
||||
|
* @param s |
||||
|
* @returns |
||||
|
*/ |
||||
|
public scale(s: vec3): GLMatrixStack { |
||||
|
switch (this.matrixMode) { |
||||
|
case EMatrixMode.MODELVIEW: |
||||
|
this.modelViewMatrix.scale(s); |
||||
|
break; |
||||
|
case EMatrixMode.PROJECTION: |
||||
|
this.projectionMatrix.scale(s); |
||||
|
break; |
||||
|
case EMatrixMode.TEXTURE: |
||||
|
this.textureMatrix.scale(s); |
||||
|
break; |
||||
|
} |
||||
|
return this; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export class GLWordMatrixStack { |
||||
|
/** |
||||
|
* @var |
||||
|
*/ |
||||
|
private _worldMatrixStack: mat4[]; |
||||
|
|
||||
|
public constructor() { |
||||
|
this._worldMatrixStack = []; |
||||
|
this._worldMatrixStack.push(new mat4()); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取视图矩阵 |
||||
|
*/ |
||||
|
public get modelViewMatrix(): mat4 { |
||||
|
if (this._worldMatrixStack.length <= 0) { |
||||
|
throw new Error("model matrix stack is empty!"); |
||||
|
} |
||||
|
return this._worldMatrixStack[this._worldMatrixStack.length - 1]; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @returns |
||||
|
*/ |
||||
|
public pushMatrix(): GLWordMatrixStack { |
||||
|
let mv: mat4 = new mat4(); |
||||
|
this.modelViewMatrix.copy(mv); |
||||
|
this._worldMatrixStack.push(mv); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @returns |
||||
|
*/ |
||||
|
public popMatrix(): GLWordMatrixStack { |
||||
|
this._worldMatrixStack.pop(); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @returns |
||||
|
*/ |
||||
|
public loadIdentity(): GLWordMatrixStack { |
||||
|
this.modelViewMatrix.setIdentity(); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @param mat |
||||
|
* @returns |
||||
|
*/ |
||||
|
public loadMatrix(mat: mat4): GLWordMatrixStack { |
||||
|
mat.copy(this.modelViewMatrix); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @param mat |
||||
|
* @returns |
||||
|
*/ |
||||
|
public multMatrix(mat: mat4): GLWordMatrixStack { |
||||
|
this.modelViewMatrix.multiply(mat); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @param pos |
||||
|
* @returns |
||||
|
*/ |
||||
|
public translate(pos: vec3): GLWordMatrixStack { |
||||
|
this.modelViewMatrix.translate(pos); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @param angle |
||||
|
* @param axis |
||||
|
* @param isRadians |
||||
|
* @returns |
||||
|
*/ |
||||
|
public rotate(angle: number, axis: vec3, isRadians: boolean = false): GLWordMatrixStack { |
||||
|
if (isRadians === false) { |
||||
|
angle = Util.toRadian(angle); |
||||
|
} |
||||
|
this.modelViewMatrix.rotate(angle, axis); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @param s |
||||
|
* @returns |
||||
|
*/ |
||||
|
public scale(s: vec3): GLWordMatrixStack { |
||||
|
this.modelViewMatrix.scale(s); |
||||
|
return this; |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue