From e6023d2ef7df6137eba7b45fc24d41df1c3c7dd9 Mon Sep 17 00:00:00 2001 From: MrKBear Date: Tue, 15 Feb 2022 21:44:27 +0800 Subject: [PATCH] Cause camera move scale with inertia --- source/GLRender/Camera.ts | 54 ++++++++++++++++++++++++++++-- source/GLRender/ClassicRenderer.ts | 39 +++++++++++---------- 2 files changed, 73 insertions(+), 20 deletions(-) diff --git a/source/GLRender/Camera.ts b/source/GLRender/Camera.ts index 72f6dd0..fdf66ee 100644 --- a/source/GLRender/Camera.ts +++ b/source/GLRender/Camera.ts @@ -191,15 +191,17 @@ class Camera{ /** * 控制灵敏度 */ - public sensitivity:number = .5; + public sensitivity: number[] = [.5, .5]; + public sensitivityInertia: number[] = [20, 20]; + public scaleSensitivity: number = .001; /** * 摄像机控制函数 */ public ctrl(x:number, y:number) { - this.angleX += x * this.sensitivity; - this.angleY += y * this.sensitivity; + this.angleX += x * this.sensitivity[0]; + this.angleY += y * this.sensitivity[1]; if (this.angleX > 360) this.angleX = this.angleX - 360; if (this.angleX < 0) this.angleX = 360 + this.angleX; @@ -210,6 +212,52 @@ class Camera{ this.setEyeFromAngle(); } + /** + * 摄像机动力学 + */ + private angleSpeed = [0, 0]; + private scaleSpeed = 0; + + /** + * 惯性控制 + */ + public ctrlInertia(x: number, y: number) { + this.angleSpeed[0] += x * this.sensitivityInertia[0]; + this.angleSpeed[1] += y * this.sensitivityInertia[1]; + } + + /** + * 惯性缩放 + */ + public eyeInertia(x: number) { + this.scaleSpeed += x * this.scaleSensitivity; + } + + /** + * 摄像机动力学 + */ + public dynamics(t: number) { + // 阻力 + this.angleSpeed[0] /= 1.2; + this.angleSpeed[1] /= 1.2; + this.scaleSpeed /= 1.2; + + // 防抖 + const e = .000001; + if (Math.abs(this.angleSpeed[0]) <= e) { + this.angleSpeed[0] = 0; + } + if (Math.abs(this.angleSpeed[1]) <= e) { + this.angleSpeed[1] = 0; + } + if (Math.abs(this.scaleSpeed) <= e) { + this.scaleSpeed = 0; + } + + this.ctrl(this.angleSpeed[0] * t, this.angleSpeed[1] * t); + this.eyeScale(this.scaleSpeed); + } + /** * 射线追踪 */ diff --git a/source/GLRender/ClassicRenderer.ts b/source/GLRender/ClassicRenderer.ts index 9b31055..519872b 100644 --- a/source/GLRender/ClassicRenderer.ts +++ b/source/GLRender/ClassicRenderer.ts @@ -16,6 +16,13 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { private groupShader: GroupShader = undefined as any; private basicGroup: BasicGroup = undefined as any; + /** + * 是否完成缩放 + */ + private lastScale: number = 0; + private readonly cubeRadius = 2**.5; + private readonly farFogLine = 2.5; + public onLoad(): void { // 自动调节分辨率 @@ -28,14 +35,13 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { this.basicGroup = new BasicGroup().bindRenderer(this); // 生成随机数据测试 - this.basicGroup.upLoadData(new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2)); + this.basicGroup.upLoadData(new Array(1000 * 3).fill(0).map(() => (Math.random() - .5) * 2)); this.canvas.on("mousemove", () => { // 相机旋转 if (this.canvas.mouseDown) - this.camera.ctrl(this.canvas.mouseMotionX, this.canvas.mouseMotionY); - + this.camera.ctrlInertia(this.canvas.mouseMotionX, this.canvas.mouseMotionY); }); this.canvas.on("mousedown", () => { @@ -46,20 +52,8 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { this.canvas.can.style.cursor = "grab" }); - const cubeRadius = 2**.5; - const farFogLine = 2.5; - this.fogDensity = [ - this.fogDensity[0], this.camera.eye[2] - cubeRadius, - this.camera.eye[2] + cubeRadius + farFogLine - ]; - this.canvas.on("mousewheel", () => { - this.camera.eyeScale(this.canvas.wheelDelta / 100); - let dist = this.camera.eyeDist; - this.fogDensity = [ - this.fogDensity[0], dist - cubeRadius, - dist + cubeRadius + farFogLine - ]; + this.camera.eyeInertia(this.canvas.wheelDelta); }); // 运行 @@ -72,8 +66,19 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { } loop(t: number): void { - this.cleanCanvas(); + this.camera.dynamics(t); + + let dist = this.camera.eyeDist; + if (Math.abs(this.lastScale - dist) > this.camera.EL) { + this.lastScale = dist; + this.fogDensity[1] = dist - this.cubeRadius; + this.fogDensity[2] = dist + this.cubeRadius + this.farFogLine; + } + this.camera.generateMat(); + + this.cleanCanvas(); + this.axisObject.draw(this.basicShader); this.cubeObject.draw(this.basicShader); this.basicGroup.draw(this.groupShader);