diff --git a/package.json b/package.json index 5a5b5d0..7a33dc8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "webglobe", - "version": "0.3.1", + "version": "0.3.2", "description": "A WebGL virtual globe and map engine.", "main": "require.js", "scripts": { diff --git a/src/world/Camera.ts b/src/world/Camera.ts index e1d94f9..e96fb62 100644 --- a/src/world/Camera.ts +++ b/src/world/Camera.ts @@ -17,14 +17,20 @@ class Camera extends Object3D { private readonly baseTheoryDistanceFromCamera2EarthSurface = 1.23 * Kernel.EARTH_RADIUS; private readonly maxPitch = 40; - private level: number = -1; //当前渲染等级 - - private animationLevel: number = -1;//非整数,表示缩放动画过程中的level - //旋转的时候,绕着视线与地球交点进行旋转 //定义抬头时,旋转角为正值 private isZeroPitch: boolean = true;//表示当前Camera视线有没有发生倾斜 + private level: number = -1; //当前渲染等级 + private realLevel: number = -2;//可能是正数,可能是非整数,非整数表示缩放动画过程中的level + + private lastRealLevel: number = -3;//上次render()时所用到的this.realLevel + private lastMatrix: Matrix;//上次render()时的this.matrix + private lastFov: number = -1; + private lastAspect: number = -1; + private lastNear: number = -1; + private lastFar: number = -1; + private viewMatrix: Matrix;//视点矩阵,即Camera模型矩阵的逆矩阵 private projMatrix: Matrix;//当Matrix变化的时候,需要重新计算this.far private projViewMatrix: Matrix;//获取投影矩阵与视点矩阵的乘积 @@ -36,11 +42,6 @@ class Camera extends Object3D { private animating: boolean = false; - Enum: any = { - EARTH_FULL_OVERSPREAD_SCREEN: "EARTH_FULL_OVERSPREAD_SCREEN", //Canvas内全部被地球充满 - EARTH_NOT_FULL_OVERSPREAD_SCREEN: "EARTH_NOT_FULL_OVERSPREAD_SCREEN" //Canvas没有全部被地球充满 - }; - //this.near一旦初始化之后就不应该再修改 //this.far可以动态计算 //this.aspect在Viewport改变后重新计算 @@ -48,6 +49,8 @@ class Camera extends Object3D { constructor(private fov = 45, private aspect = 1, private near = 1, private far = 100) { super(); this.initFov = this.fov; + this.lastMatrix = new Matrix(); + this.lastMatrix.setUniqueValue(0); this.projMatrix = new Matrix(); this._rawSetPerspectiveMatrix(this.fov, this.aspect, this.near, this.far); this._initCameraPosition(); @@ -121,11 +124,27 @@ class Camera extends Object3D { return far; } - //更新各种矩阵,保守起见,可以在每帧绘制之前调用 - //理论上只在用户交互的时候调用就可以 - update(): void { - this._normalUpdate(); - this._updateProjViewMatrixForDraw(); + //更新各种矩阵,理论上只在用户交互的时候调用就可以 + update(force: boolean = false): void { + if(force || this._isNeedUpdate()){ + this._normalUpdate(); + this._updateProjViewMatrixForDraw(); + } + this.lastFov = this.fov; + this.lastAspect = this.aspect; + this.lastNear = this.near; + this.lastFar = this.far; + this.lastRealLevel = this.realLevel; + this.lastMatrix.setMatrixByOther(this.matrix); + } + + private _isNeedUpdate(): boolean{ + return (this.fov !== this.lastFov) || + (this.aspect !== this.lastAspect) || + (this.near !== this.lastNear) || + (this.far !== this.lastFar) || + (this.realLevel !== this.lastRealLevel) || + (!this.matrix.equals(this.lastMatrix)); } getProjViewMatrixForDraw(): Matrix { @@ -168,9 +187,8 @@ class Camera extends Object3D { //返回更新后的fov值,如果返回结果 < 0,说明无需更新fov private _updatePositionAndFov(cameraMatrix: Matrix): number { - //是否满足near值,和fov没有关系,和position有关 - //但是改变position的话,fov也要相应变动以满足对应的缩放效果 - const currentLevel = this.animating ? this.animationLevel : this.level; + //是否满足near值,和fov没有关系,和position有关,但是改变position的话,fov也要相应变动以满足对应的缩放效果 + const currentLevel = this.animating ? this.realLevel : this.level; //safeLevel不是整数 var safeLevel = this._getSafeThresholdLevelForNear(); @@ -260,8 +278,9 @@ class Camera extends Object3D { return; } var isLevelChanged = this._updatePositionByLevel(level, this.matrix); - //不要在this._setLevel()方法中更新this.level,因为这会影响animateToLevel()方法 + //不要在this._updatePositionByLevel()方法中更新this.level,因为这会影响animateToLevel()方法 this.level = level; + this.realLevel = level; Kernel.globe.refresh(); } @@ -431,7 +450,7 @@ class Camera extends Object3D { var deltaZ = (newPosition.z - oldPosition.z) / count; var deltaLevel = (newLevel - this.level) / count; var start: number = -1; - this.animationLevel = this.level; + this.realLevel = this.level; this.animating = true; var callback = (timestap: number) => { @@ -441,10 +460,10 @@ class Camera extends Object3D { var a = timestap - start; if (a >= span) { this.animating = false; - this.animationLevel = -1; + this.realLevel = newLevel; this.setLevel(newLevel); } else { - this.animationLevel += deltaLevel; + this.realLevel += deltaLevel; var p = this.getPosition(); this.setPosition(p.x + deltaX, p.y + deltaY, p.z + deltaZ); requestAnimationFrame(callback); diff --git a/src/world/math/Matrix.ts b/src/world/math/Matrix.ts index 63d8274..948e69e 100644 --- a/src/world/math/Matrix.ts +++ b/src/world/math/Matrix.ts @@ -14,6 +14,15 @@ class Matrix{ this.setElements(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44); } + equals(matrix: Matrix): boolean{ + if(this === matrix){ + return true; + } + return this.elements.every((ele: number, index: number) => { + return ele === matrix.elements[index]; + }); + } + setElements(m11: number, m12: number, m13: number, m14: number, m21: number, m22: number, m23: number, m24: number, m31: number, m32: number, m33: number, m34: number, @@ -185,9 +194,6 @@ class Matrix{ } setMatrixByOther(otherMatrix: Matrix): void { - if (!(otherMatrix instanceof Matrix)) { - throw "invalid otherMatrix"; - } for (var i = 0; i < otherMatrix.elements.length; i++) { this.elements[i] = otherMatrix.elements[i]; } @@ -201,7 +207,14 @@ class Matrix{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 1); + 0, 0, 0, 1 + ); + } + + setUniqueValue(value: number){ + this.elements.forEach((ele, index) => { + this.elements[index] = value; + }); } /** @@ -231,7 +244,8 @@ class Matrix{ this.elements[0], this.elements[4], this.elements[8], this.elements[12], this.elements[1], this.elements[5], this.elements[9], this.elements[13], this.elements[2], this.elements[6], this.elements[10], this.elements[14], - this.elements[3], this.elements[7], this.elements[11], this.elements[15]); + this.elements[3], this.elements[7], this.elements[11], this.elements[15] + ); } multiplyMatrix(otherMatrix: Matrix): Matrix { diff --git a/versions.txt b/versions.txt index da58fb2..ab43142 100644 --- a/versions.txt +++ b/versions.txt @@ -101,4 +101,6 @@ 但是实际传递给shader用于绘图的是projViewMatrixForDraw。Camera.getPickCartesianCoordInEarthByCanvas()方法也是基于projViewMatrixForDraw系列矩阵的。 该版本提高了深度值的精度,基本解决了z值精度问题。在update()方法中会计算projViewMatrixForDraw系列矩阵。 -0.3.1 使得Globe.animateToLevel()可以在0.3.0的版本上运行,解决办法是引入了camera.animationLevel,其值是非整数。 \ No newline at end of file +0.3.1 使得Globe.animateToLevel()可以在0.3.0的版本上运行,解决办法是引入了camera.animationLevel,其值是非整数。 + +0.3.2 优化了Camera.update()方法,只有发生用户交互的情况下才实际进行计算。 \ No newline at end of file