blobt
4 years ago
22 changed files with 2281 additions and 0 deletions
-
1src/render/common.ts
-
400src/render/core/Application.ts
-
88src/render/core/Event.ts
-
42src/render/core/Timer.ts
-
0src/render/ds/AdapterBase.ts
-
0src/render/ds/Dictionary.ts
-
0src/render/ds/IAdapter.ts
-
0src/render/ds/IEnumerator.ts
-
0src/render/ds/List.ts
-
0src/render/ds/ListNode.ts
-
0src/render/ds/NodeB2TEnumberator.ts
-
0src/render/ds/NodeEnumeratorFactory.ts
-
0src/render/ds/NodeT2BEnumerator.ts
-
0src/render/ds/Queue.ts
-
0src/render/ds/Stack.ts
-
0src/render/ds/TreeNode.ts
-
0src/render/ds/TypedArrayList.ts
-
0src/render/ds/index.ts
-
1537src/render/math/TSM.ts
-
42src/render/math/Vec2.ts
-
161src/render/math/Vec3.ts
-
10src/render/webgl/WebGLApplication.ts
@ -0,0 +1 @@ |
|||||
|
export let EPSILON: number = 0.0001; |
@ -0,0 +1,400 @@ |
|||||
|
import { vec2 } from "../math/TSM"; |
||||
|
import { CanvasKeyBoardEvent, CanvasMouseEvent, EInputEventType } from "./Event"; |
||||
|
import { Timer, TimerCallback } from "./Timer"; |
||||
|
|
||||
|
|
||||
|
export class Application implements EventListenerObject { |
||||
|
|
||||
|
/** |
||||
|
* @var 定时器数组 |
||||
|
*/ |
||||
|
public timers: Timer[] = []; |
||||
|
|
||||
|
/** |
||||
|
* @var 定时器id |
||||
|
*/ |
||||
|
private _timerId: number = -1; |
||||
|
|
||||
|
/** |
||||
|
* @var 帧率 |
||||
|
*/ |
||||
|
private _fps: number = 0; |
||||
|
|
||||
|
/** |
||||
|
* @var |
||||
|
*/ |
||||
|
public isFlipYCoord: boolean = false; |
||||
|
|
||||
|
/** |
||||
|
* @var |
||||
|
*/ |
||||
|
public canvas: HTMLCanvasElement; |
||||
|
|
||||
|
/** |
||||
|
* @var 是否每次移动都会触发mouse事件 |
||||
|
*/ |
||||
|
public isSupportMouseMove: boolean; |
||||
|
|
||||
|
/** |
||||
|
* @var 鼠标是否被按下 |
||||
|
*/ |
||||
|
protected _isMouseDown: boolean; |
||||
|
|
||||
|
/** |
||||
|
* @var 是否按下鼠标右键 |
||||
|
*/ |
||||
|
protected _isRightMouseDown: boolean = false; |
||||
|
|
||||
|
/** |
||||
|
* @var 是否进入循环 |
||||
|
*/ |
||||
|
protected _start: boolean = false; |
||||
|
|
||||
|
/** |
||||
|
* @var 由Window对象的requestAnimationFrame返回的大于0的id号, |
||||
|
* 我们可以使用cancelAnimationFrame ( this ._requestId )来取消动画循环. |
||||
|
*/ |
||||
|
protected _requestId: number = -1; |
||||
|
|
||||
|
/** |
||||
|
* @var 计算当前更新与上一次更新之间的时间差 |
||||
|
*/ |
||||
|
protected _lastTime !: number; |
||||
|
protected _startTime !: number; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* @function 渲染每帧画面的回调函数 |
||||
|
*/ |
||||
|
public frameCallback: ((app: Application) => void) | null; |
||||
|
|
||||
|
|
||||
|
|
||||
|
public constructor(canvas: HTMLCanvasElement) { |
||||
|
this.canvas = canvas; |
||||
|
|
||||
|
//设置鼠标的监听事件
|
||||
|
this.canvas.addEventListener("mousedown", this, false); |
||||
|
this.canvas.addEventListener("mouseup", this, false); |
||||
|
this.canvas.addEventListener("mousemove", this, false); |
||||
|
|
||||
|
//设置键盘监听事件
|
||||
|
window.addEventListener("keydown", this, false); |
||||
|
window.addEventListener("keyup", this, false); |
||||
|
window.addEventListener("keypress", this, false); |
||||
|
|
||||
|
//初始化时候mousedown 和 mousemvoe不开启
|
||||
|
this._isMouseDown = false; |
||||
|
this.isSupportMouseMove = false; |
||||
|
|
||||
|
this.frameCallback = null; |
||||
|
|
||||
|
//禁止右键菜单
|
||||
|
document.oncontextmenu = function () { return false }; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 判断当前Application是否一直在调用requestAnimationFrame |
||||
|
* @returns boolean |
||||
|
*/ |
||||
|
public isRunning(): boolean { |
||||
|
return this._start; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取当前帧率 |
||||
|
*/ |
||||
|
public get fps() { |
||||
|
return this._fps; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 启动渲染 |
||||
|
*/ |
||||
|
public start(): void { |
||||
|
if (this._start === false) { |
||||
|
this._start = true; |
||||
|
|
||||
|
this._startTime = -1; |
||||
|
this._lastTime = -1; |
||||
|
|
||||
|
this._requestId = requestAnimationFrame((msec: number): void => { |
||||
|
this.step(msec); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 循环函数 |
||||
|
* @param timeStamp |
||||
|
*/ |
||||
|
protected step(timeStamp: number): void { |
||||
|
|
||||
|
if (this._startTime === -1) { |
||||
|
this._startTime = timeStamp; |
||||
|
} |
||||
|
|
||||
|
if (this._lastTime === -1) { |
||||
|
this._lastTime = timeStamp; |
||||
|
} |
||||
|
|
||||
|
//计算当前时间和第一次调用step时候的时间差
|
||||
|
let elapsedMsec = timeStamp - this._startTime; |
||||
|
|
||||
|
//计算当前时间和上一次调用step时候的时间差
|
||||
|
let intervalSec = timeStamp - this._lastTime; |
||||
|
this._lastTime = timeStamp; |
||||
|
|
||||
|
//计算帧率
|
||||
|
if (intervalSec !== 0) { |
||||
|
this._fps = 1000 / intervalSec; |
||||
|
} |
||||
|
|
||||
|
intervalSec /= 1000.0; //转成秒
|
||||
|
|
||||
|
//处理timer
|
||||
|
this._handleTimers(intervalSec); |
||||
|
|
||||
|
//更新
|
||||
|
this.update(elapsedMsec, intervalSec); |
||||
|
|
||||
|
//渲染
|
||||
|
this.render(); |
||||
|
|
||||
|
if (this.frameCallback !== null) { |
||||
|
this.frameCallback(this); |
||||
|
} |
||||
|
|
||||
|
requestAnimationFrame((elapsedMsec: number): void => { |
||||
|
this.step(elapsedMsec); |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
public stop(): void { |
||||
|
if (this._start) { |
||||
|
cancelAnimationFrame(this._requestId); |
||||
|
this._startTime = -1; |
||||
|
this._lastTime = -1; |
||||
|
this._start = false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 虚函数 |
||||
|
* @param elapsedMsec 毫秒 |
||||
|
* @param intervalSec 秒 |
||||
|
*/ |
||||
|
public update(elapsedMsec: number, intervalSec: number): void { } |
||||
|
|
||||
|
/** |
||||
|
* 虚函数 |
||||
|
*/ |
||||
|
public render(): void { } |
||||
|
|
||||
|
public async run(): Promise<void> { |
||||
|
this.start(); |
||||
|
} |
||||
|
|
||||
|
handleEvent(evt: Event): void { |
||||
|
switch (evt.type) { |
||||
|
case "mousedown": |
||||
|
this._isMouseDown = true; |
||||
|
this.onMouseDown(this._toCanvasMouseEvent(evt, EInputEventType.MOUSEDOWN)); |
||||
|
break; |
||||
|
case "mouseup": |
||||
|
this._isMouseDown = false; |
||||
|
this.onMouseDown(this._toCanvasMouseEvent(evt, EInputEventType.MOUSEUP)); |
||||
|
break; |
||||
|
case "mousemove": |
||||
|
if (this.isSupportMouseMove) { |
||||
|
this.onMouseMove(this._toCanvasMouseEvent(evt, EInputEventType.MOUSEMOVE)); |
||||
|
} |
||||
|
if (this._isMouseDown) { |
||||
|
this.onMouseDrag(this._toCanvasMouseEvent(evt, EInputEventType.MOUSEDRAG)); |
||||
|
} |
||||
|
break; |
||||
|
case "keypress": |
||||
|
this.onKeyPress(this._toCanvasKeyBoardEvent(evt, EInputEventType.KEYPRESS)); |
||||
|
break; |
||||
|
case "keydown": |
||||
|
this.onKeyDown(this._toCanvasKeyBoardEvent(evt, EInputEventType.MOUSEDOWN)); |
||||
|
break; |
||||
|
case "keyup": |
||||
|
this.onKeyUp(this._toCanvasKeyBoardEvent(evt, EInputEventType.KEYUP)); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected onMouseDown(evt: CanvasMouseEvent): void { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
protected onMouseUp(evt: CanvasMouseEvent): void { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
protected onMouseMove(evt: CanvasMouseEvent): void { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
protected onMouseDrag(evt: CanvasMouseEvent): void { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
protected onKeyDown(evt: CanvasKeyBoardEvent): void { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
protected onKeyUp(evt: CanvasKeyBoardEvent): void { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
protected onKeyPress(evt: CanvasKeyBoardEvent): void { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
protected getMouseCanvas(): HTMLCanvasElement { |
||||
|
return this.canvas; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 将鼠标的指针位置变换为当前canvas的位置 |
||||
|
* @param evt |
||||
|
*/ |
||||
|
private viewportToCanvasCoordinate(evt: MouseEvent): vec2 { |
||||
|
let rect: ClientRect = this.getMouseCanvas().getBoundingClientRect(); |
||||
|
|
||||
|
//target是触发事件的元素,这里是canvas
|
||||
|
if (evt.target) { |
||||
|
let x: number = evt.clientX - rect.left; |
||||
|
let y: number = evt.clientY - rect.top; |
||||
|
|
||||
|
if (this.isFlipYCoord) { |
||||
|
y = this.getMouseCanvas().height - y; |
||||
|
} |
||||
|
let pos: vec2 = new vec2([x, y]); |
||||
|
return pos; |
||||
|
} |
||||
|
|
||||
|
throw new Error("evt.target is null"); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 把DOM 事件转成自己的事件 |
||||
|
* @param evt |
||||
|
* @param type |
||||
|
*/ |
||||
|
private _toCanvasMouseEvent(evt: Event, type: EInputEventType): CanvasMouseEvent { |
||||
|
let event: MouseEvent = evt as MouseEvent;//向下转型,将Event转换为MouseEvent
|
||||
|
|
||||
|
if (type === EInputEventType.MOUSEDOWN && event.button === 2) { |
||||
|
this._isRightMouseDown = true; |
||||
|
} else if (type === EInputEventType.MOUSEUP && event.button === 2) { |
||||
|
this._isRightMouseDown = false; |
||||
|
} |
||||
|
|
||||
|
let buttonNum: number = event.button; |
||||
|
|
||||
|
if (this._isRightMouseDown && type === EInputEventType.MOUSEDRAG) { |
||||
|
buttonNum = 2; |
||||
|
} |
||||
|
|
||||
|
//将鼠标位置变换到canvas坐标系位置
|
||||
|
let mousePosition: vec2 = this.viewportToCanvasCoordinate(event); |
||||
|
|
||||
|
let ret: CanvasMouseEvent = new CanvasMouseEvent(type, mousePosition, buttonNum, event.altKey, event.ctrlKey, event.shiftKey); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 把DOM 事件转成自己的事件 |
||||
|
* @param evt |
||||
|
* @param type |
||||
|
*/ |
||||
|
private _toCanvasKeyBoardEvent(evt: Event, type: EInputEventType): CanvasKeyBoardEvent { |
||||
|
let event: KeyboardEvent = evt as KeyboardEvent; |
||||
|
let ret: CanvasKeyBoardEvent = new CanvasKeyBoardEvent(type, event.key, event.keyCode, event.repeat, event.altKey, event.ctrlKey, event.shiftKey); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 添加一个定时器 |
||||
|
* @param callback |
||||
|
* @param timeout |
||||
|
* @param onlyOnce |
||||
|
* @param data |
||||
|
* @returns |
||||
|
*/ |
||||
|
public addTimer(callback: TimerCallback, timeout: number = 1.0, onlyOnce: boolean = false, data: any = undefined): number { |
||||
|
let timer: Timer; |
||||
|
|
||||
|
for (let i = 0; i < this.timers.length; i++) { |
||||
|
timer = this.timers[i]; |
||||
|
if (timer.enabled === false) { |
||||
|
timer.callback = callback; |
||||
|
timer.callbackData = data; |
||||
|
timer.timeout = timeout; |
||||
|
timer.enabled = true; |
||||
|
timer.onlyOnce = onlyOnce; |
||||
|
return timer.id; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
timer = new Timer(callback); |
||||
|
timer.callback = callback; |
||||
|
timer.callbackData = data; |
||||
|
timer.timeout = timeout; |
||||
|
timer.enabled = true; |
||||
|
timer.onlyOnce = onlyOnce; |
||||
|
|
||||
|
this.timers.push(timer); |
||||
|
timer.id = ++this._timerId; |
||||
|
|
||||
|
return timer.id; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 清除定时器 |
||||
|
* @param id |
||||
|
* @returns |
||||
|
*/ |
||||
|
public removeTimer(id: number): boolean { |
||||
|
let ret: boolean = false; |
||||
|
for (let i = 0; i < this.timers.length; i++) { |
||||
|
if (this.timers[i].id === id) { |
||||
|
let timer: Timer = this.timers[i]; |
||||
|
timer.enabled = false; |
||||
|
ret = true; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @param intervalSec 秒 |
||||
|
*/ |
||||
|
private _handleTimers(intervalSec: number): void { |
||||
|
for (let i = 0; i < this.timers.length; i++) { |
||||
|
let timer: Timer = this.timers[i]; |
||||
|
|
||||
|
if (timer.enabled === false) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
//countdown 初始化为timeout, 每次减少渲染时间
|
||||
|
timer.countdown -= intervalSec; |
||||
|
|
||||
|
if (timer.countdown <= 0.0) { |
||||
|
timer.callback(timer.id, timer.callbackData); |
||||
|
if (timer.onlyOnce) { |
||||
|
this.removeTimer(timer.id); |
||||
|
} else { |
||||
|
timer.callbackData = timer.timeout; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,88 @@ |
|||||
|
import { vec2 } from "../math/TSM"; |
||||
|
|
||||
|
/** |
||||
|
* appliaction所有事件 |
||||
|
*/ |
||||
|
export enum EInputEventType { |
||||
|
MOUSEEVENT, //总类。表示鼠标事件
|
||||
|
MOUSEDOWN, |
||||
|
MOUSEUP, |
||||
|
MOUSEMOVE, |
||||
|
MOUSEDRAG, |
||||
|
KEYBOARDEVENT, //总类,表示键盘事件
|
||||
|
KEYUP, |
||||
|
KEYDOWN, |
||||
|
KEYPRESS |
||||
|
} |
||||
|
|
||||
|
export class CanvasInputEvent { |
||||
|
/** |
||||
|
* @var alt键是否被按下 |
||||
|
*/ |
||||
|
public altKey: boolean; |
||||
|
|
||||
|
/** |
||||
|
* @var ctrl键是否被按下 |
||||
|
*/ |
||||
|
public ctrlKey: boolean; |
||||
|
|
||||
|
/** |
||||
|
* @var shift键是否被按下 |
||||
|
*/ |
||||
|
public shiftKey: boolean; |
||||
|
|
||||
|
/** |
||||
|
* @var 当前事件类型 |
||||
|
*/ |
||||
|
public type: EInputEventType; |
||||
|
|
||||
|
public constructor(type: EInputEventType, altKey: boolean = false, ctrlKey: boolean = false, shiftKey: boolean = false) { |
||||
|
this.type = type; |
||||
|
this.altKey = altKey; |
||||
|
this.ctrlKey = ctrlKey; |
||||
|
this.shiftKey = shiftKey; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
export class CanvasMouseEvent extends CanvasInputEvent { |
||||
|
/** |
||||
|
* @var 0 : 鼠标左键 ,1 : 鼠标中键,2 : 鼠标右键 |
||||
|
*/ |
||||
|
public button: number; |
||||
|
|
||||
|
/** |
||||
|
* @var canvas 坐标系的位置 |
||||
|
*/ |
||||
|
public canvasPosition: vec2; |
||||
|
|
||||
|
public constructor(type: EInputEventType, canvasPos: vec2, button: number, altKey: boolean = false, ctrlKey: boolean = false, shiftKey:boolean = false){ |
||||
|
super(type,altKey, ctrlKey, shiftKey); |
||||
|
this.canvasPosition = canvasPos; |
||||
|
this.button = button; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export class CanvasKeyBoardEvent extends CanvasInputEvent { |
||||
|
/** |
||||
|
* @var 当前按下按键的字符 |
||||
|
*/ |
||||
|
public key:string; |
||||
|
|
||||
|
/** |
||||
|
* @var 当前按下按键的ascii码 |
||||
|
*/ |
||||
|
public keyCode:number; |
||||
|
|
||||
|
/** |
||||
|
* @var 是否不停触发 |
||||
|
*/ |
||||
|
public repeat:boolean; |
||||
|
|
||||
|
public constructor(type: EInputEventType, key:string, keyCode:number, repeat: boolean, altKey: boolean = false, ctrlKey: boolean = false, shiftKey:boolean = false){ |
||||
|
super(type,altKey, ctrlKey, shiftKey); |
||||
|
this.key = key; |
||||
|
this.keyCode = keyCode; |
||||
|
this.repeat = repeat; |
||||
|
} |
||||
|
} |
@ -0,0 +1,42 @@ |
|||||
|
export type TimerCallback = (id: number, data: any) => void; |
||||
|
|
||||
|
export class Timer { |
||||
|
/** |
||||
|
* @var 计时器id |
||||
|
*/ |
||||
|
public id: number = -1; |
||||
|
|
||||
|
/** |
||||
|
* @var 计时器是否开启 |
||||
|
*/ |
||||
|
public enabled: boolean = false; |
||||
|
|
||||
|
/** |
||||
|
* @function 回调函数,到时间后自动调用 |
||||
|
*/ |
||||
|
public callback: TimerCallback; |
||||
|
|
||||
|
/** |
||||
|
* @var 回调函数参数 |
||||
|
*/ |
||||
|
public callbackData: any = undefined; |
||||
|
|
||||
|
/** |
||||
|
* @var update次数 |
||||
|
*/ |
||||
|
public countdown: number = 0; |
||||
|
|
||||
|
/** |
||||
|
* @var 超时次数??? |
||||
|
*/ |
||||
|
public timeout: number = 0; |
||||
|
|
||||
|
/** |
||||
|
* @var 是否只执行一次 |
||||
|
*/ |
||||
|
public onlyOnce: boolean = false; |
||||
|
|
||||
|
constructor(callback: TimerCallback){ |
||||
|
this.callback = callback; |
||||
|
} |
||||
|
} |
1537
src/render/math/TSM.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,42 @@ |
|||||
|
/** |
||||
|
* 二维向量 |
||||
|
*/ |
||||
|
export class Vec2 { |
||||
|
|
||||
|
/** |
||||
|
* @var 数据存储内存 |
||||
|
*/ |
||||
|
public values = new Float32Array(2); |
||||
|
|
||||
|
public get x(): number { |
||||
|
return this.values[0]; |
||||
|
} |
||||
|
|
||||
|
public get y(): number { |
||||
|
return this.values[1]; |
||||
|
} |
||||
|
|
||||
|
public set x(value: number) { |
||||
|
this.values[0] = value; |
||||
|
} |
||||
|
|
||||
|
public set y(value: number) { |
||||
|
this.values[1] = value; |
||||
|
} |
||||
|
|
||||
|
public constructor(values: number[] | null = null) { |
||||
|
if (values) { |
||||
|
this.x = values[0]; |
||||
|
this.y = values[1]; |
||||
|
} else { |
||||
|
this.x = this.y = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
copy(dest: Vec2 | null = null): Vec2 { |
||||
|
if (!dest) dest = new Vec2(); |
||||
|
dest.x = this.x; |
||||
|
dest.y = this.y; |
||||
|
return dest; |
||||
|
} |
||||
|
} |
@ -0,0 +1,161 @@ |
|||||
|
import { EPSILON } from "../common"; |
||||
|
|
||||
|
export class Vec3 { |
||||
|
/** |
||||
|
* @var |
||||
|
*/ |
||||
|
public values = new Float32Array(3); |
||||
|
|
||||
|
public get x(): number { |
||||
|
return this.values[0]; |
||||
|
} |
||||
|
|
||||
|
public get y(): number { |
||||
|
return this.values[1]; |
||||
|
} |
||||
|
|
||||
|
public get z(): number { |
||||
|
return this.values[2]; |
||||
|
} |
||||
|
|
||||
|
public set x(value: number) { |
||||
|
this.values[0] = value; |
||||
|
} |
||||
|
|
||||
|
public set y(value: number) { |
||||
|
this.values[1] = value; |
||||
|
} |
||||
|
|
||||
|
public set z(value: number) { |
||||
|
this.values[2] = value; |
||||
|
} |
||||
|
|
||||
|
public constructor(values: number[] | null = null) { |
||||
|
if (values !== null) { |
||||
|
this.x = values[0]; |
||||
|
this.y = values[1]; |
||||
|
this.z = values[2]; |
||||
|
} else { |
||||
|
this.x = this.y = this.z = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public at(index: number): number { |
||||
|
return this.values[index]; |
||||
|
} |
||||
|
|
||||
|
public reset(x: number = 0, y: number = 0, z: number = 0): void { |
||||
|
this.x = x; |
||||
|
this.y = y; |
||||
|
this.z = z; |
||||
|
} |
||||
|
|
||||
|
public copy(dest: Vec3 | null = null): Vec3 { |
||||
|
if (!dest) dest = new Vec3(); |
||||
|
|
||||
|
dest.x = this.x; |
||||
|
dest.y = this.y; |
||||
|
dest.z = this.z; |
||||
|
|
||||
|
return dest; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 取负向量 |
||||
|
* @param dest |
||||
|
* @returns |
||||
|
*/ |
||||
|
public negate(dest: Vec3 | null = null): Vec3 { |
||||
|
if (!dest) dest = this; |
||||
|
|
||||
|
dest.x = -this.x; |
||||
|
dest.y = -this.y; |
||||
|
dest.z = -this.z; |
||||
|
|
||||
|
return dest; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 判断是否相等 |
||||
|
* @param vector |
||||
|
* @param threshold |
||||
|
* @returns |
||||
|
*/ |
||||
|
public equals(vector: Vec3, threshold = EPSILON): boolean { |
||||
|
if (Math.abs(this.x - vector.x) > threshold) |
||||
|
return false; |
||||
|
|
||||
|
if (Math.abs(this.y - vector.y) > threshold) |
||||
|
return false; |
||||
|
|
||||
|
if (Math.abs(this.z - vector.z) > threshold) |
||||
|
return false; |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取向量的模 |
||||
|
*/ |
||||
|
public get length(): number { |
||||
|
return Math.sqrt(this.length2); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 向量模的平方 |
||||
|
*/ |
||||
|
public get length2(): number { |
||||
|
let x = this.x, |
||||
|
y = this.y, |
||||
|
z = this.z; |
||||
|
|
||||
|
return (x * x + y * y + z * z); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 向量相加 |
||||
|
* @param vector |
||||
|
* @returns |
||||
|
*/ |
||||
|
add(vector: Vec3): Vec3 { |
||||
|
this.x += vector.x; |
||||
|
this.y += vector.y; |
||||
|
this.z += vector.z; |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 向量相减 |
||||
|
* @param vector |
||||
|
* @returns |
||||
|
*/ |
||||
|
subtract(vector: Vec3): Vec3 { |
||||
|
this.x -= vector.x; |
||||
|
this.y -= vector.y; |
||||
|
this.z -= vector.z; |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 向量缩放 |
||||
|
* @param value |
||||
|
* @param dest |
||||
|
* @returns |
||||
|
*/ |
||||
|
public scale(value: number, dest: Vec3 | null = null): Vec3 { |
||||
|
if (!dest) { |
||||
|
dest = this; |
||||
|
} else { |
||||
|
this.copy(dest); |
||||
|
} |
||||
|
|
||||
|
dest.x *= value; |
||||
|
dest.y *= value; |
||||
|
dest.z *= value; |
||||
|
|
||||
|
return dest; |
||||
|
} |
||||
|
} |
@ -0,0 +1,10 @@ |
|||||
|
import { Application } from "../core/Application"; |
||||
|
|
||||
|
export class WebGLApplication extends Application { |
||||
|
/** |
||||
|
* @var WebGL |
||||
|
*/ |
||||
|
//public gl: WebGLRenderingContext;
|
||||
|
|
||||
|
|
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue