Commit 8bccaed5 authored by David Kouřil's avatar David Kouřil
Browse files

refactor smooth camera

should also fix the rotation
parent 7a42fb37
...@@ -11,6 +11,30 @@ function deg_to_rad(degrees: number): number { ...@@ -11,6 +11,30 @@ function deg_to_rad(degrees: number): number {
function easeOutExp(t: number): number { function easeOutExp(t: number): number {
return -Math.pow(2, -10 * t) + 1; return -Math.pow(2, -10 * t) + 1;
} }
//~ LOL, these definitions are useless actually...
type OrbitingParams = {
currentLerpTime: number;
lastFrameAngleX: number;
lastFrameAngleY: number;
endAngleY: number;
endAngleX: number;
pivot: vec3;
}
type ZoomingParams = {
currentLerpTime: number;
endAmount: number;
lastFrameZoomAmount: number;
}
type PanningParams = {
currentLerpTime: number;
startPosition: vec3;
endPosition: vec3;
lastFramePosition: vec3;
}
export class SmoothCamera extends Camera { export class SmoothCamera extends Camera {
private currentMousePos = { x: 0, y: 0 }; private currentMousePos = { x: 0, y: 0 };
private lastMousePos = { x: 0, y: 0 }; private lastMousePos = { x: 0, y: 0 };
...@@ -22,32 +46,39 @@ export class SmoothCamera extends Camera { ...@@ -22,32 +46,39 @@ export class SmoothCamera extends Camera {
//~ general //~ general
animTime = 1000.0; animTime = 1000.0;
zoomToCursor = false; zoomToCursor = false;
//~ orbiting
orbitCurrentLerpTime = 0;
orbitLastFrameAngleX = 0;
orbitLastFrameAngleY = 0;
orbitEndAngleY = 0;
orbitEndAngleX = 0;
orbitingSpeed = 0.5; orbitingSpeed = 0.5;
orbitingPivot = vec3.fromValues(0, 0, 0); zoomingSpeed = 0.0015;
//~ zooming
zoomCurrentLerpTime = 0.0;
zoomEndAmount = 0.0;
lastFrameZoomAmount = 0.0;
scrollingSpeed = 0.0015;
//~ panning
panStartPosition = vec3.fromValues(0, 0, 0);
lastFramePosition = vec3.fromValues(0, 0, 0);
panEndPosition = vec3.fromValues(0, 0, 0);
panCurrentLerpTime = 0.0;
panningSpeed = 0.005; panningSpeed = 0.005;
//~ orbiting params
orbiting: OrbitingParams = {
currentLerpTime: 0,
lastFrameAngleX: 0,
lastFrameAngleY: 0,
endAngleY: 0,
endAngleX: 0,
pivot: vec3.fromValues(0, 0, 0)
}
//~ zooming params
zooming: ZoomingParams = {
currentLerpTime: 0.0,
endAmount: 0.0,
lastFrameZoomAmount: 0.0,
}
//~ panning params
panning: PanningParams = {
currentLerpTime: 0.0,
startPosition: vec3.fromValues(0, 0, 0),
endPosition: vec3.fromValues(0, 0, 0),
lastFramePosition: vec3.fromValues(0, 0, 0),
}
constructor(device: GPUDevice, width: number, height: number, near = 0.01, fieldOfView = 45.0) { constructor(device: GPUDevice, width: number, height: number, near = 0.01, fieldOfView = 45.0) {
super(device, width, height, near, fieldOfView); super(device, width, height, near, fieldOfView);
this.updateCPU(0); this.updateCPU(0);
} }
...@@ -58,20 +89,20 @@ export class SmoothCamera extends Camera { ...@@ -58,20 +89,20 @@ export class SmoothCamera extends Camera {
this.updateOrbiting(dt); this.updateOrbiting(dt);
this.updatePanning(dt); this.updatePanning(dt);
const mvm = this.computeModelViewMatrix(this.position, this.orbitingPivot); const mvm = this.computeModelViewMatrix(this.position, this.orbiting.pivot);
mat4.copy(this._viewMatrix, mvm); mat4.copy(this._viewMatrix, mvm);
super.updateCPU(dt); super.updateCPU(dt);
} }
protected updateZooming(dt: number): void { protected updateZooming(dt: number): void {
this.zoomCurrentLerpTime += dt; this.zooming.currentLerpTime += dt;
if (this.zoomCurrentLerpTime > this.animTime) this.zoomCurrentLerpTime = this.animTime; if (this.zooming.currentLerpTime > this.animTime) this.zooming.currentLerpTime = this.animTime;
const perc = this.zoomCurrentLerpTime / this.animTime; const perc = this.zooming.currentLerpTime / this.animTime;
const currentZoom = this.lerpNumber(0.0, this.zoomEndAmount, easeOutExp(perc)); const currentZoom = this.lerpNumber(0.0, this.zooming.endAmount, easeOutExp(perc));
const change = currentZoom - this.lastFrameZoomAmount; const change = currentZoom - this.zooming.lastFrameZoomAmount;
this.lastFrameZoomAmount = currentZoom; this.zooming.lastFrameZoomAmount = currentZoom;
if (!this.zoomToCursor) { if (!this.zoomToCursor) {
//~ zoom in => move the camera by the current frame change //~ zoom in => move the camera by the current frame change
...@@ -115,35 +146,37 @@ export class SmoothCamera extends Camera { ...@@ -115,35 +146,37 @@ export class SmoothCamera extends Camera {
//~ move camera by offset //~ move camera by offset
vec3.sub(this.position, this.position, offset); vec3.sub(this.position, this.position, offset);
vec3.sub(this.orbitingPivot, this.orbitingPivot, offset); vec3.sub(this.orbiting.pivot, this.orbiting.pivot, offset);
} }
protected updateOrbiting(dt: number): void { protected updateOrbiting(dt: number): void {
this.orbitCurrentLerpTime += dt; this.orbiting.currentLerpTime += dt;
if (this.orbitCurrentLerpTime > this.animTime) this.orbitCurrentLerpTime = this.animTime; if (this.orbiting.currentLerpTime > this.animTime) this.orbiting.currentLerpTime = this.animTime;
const perc = this.orbitCurrentLerpTime / this.animTime; const perc = this.orbiting.currentLerpTime / this.animTime;
const currentAngleX = this.lerpNumber(0.0, this.orbitEndAngleX, easeOutExp(perc)); const currentAngleX = this.lerpNumber(0.0, this.orbiting.endAngleX, easeOutExp(perc));
const currentAngleY = this.lerpNumber(0.0, this.orbitEndAngleY, easeOutExp(perc)); const currentAngleY = this.lerpNumber(0.0, this.orbiting.endAngleY, easeOutExp(perc));
const rotIncrementX = currentAngleX - this.orbitLastFrameAngleX; const rotIncrementX = currentAngleX - this.orbiting.lastFrameAngleX;
const rotIncrementY = currentAngleY - this.orbitLastFrameAngleY; const rotIncrementY = currentAngleY - this.orbiting.lastFrameAngleY;
this.orbitLastFrameAngleX = currentAngleX; this.orbiting.lastFrameAngleX = currentAngleX;
this.orbitLastFrameAngleY = currentAngleY; this.orbiting.lastFrameAngleY = currentAngleY;
const horizRot = quat.create(); const horizRot = quat.create();
quat.setAxisAngle(horizRot, this.up(), deg_to_rad(-rotIncrementY)); // quat.setAxisAngle(horizRot, this.up(), deg_to_rad(-rotIncrementY));
quat.setAxisAngle(horizRot, vec3.fromValues(0, 1, 0), deg_to_rad(-rotIncrementY));
const vertRot = quat.create(); const vertRot = quat.create();
quat.setAxisAngle(vertRot, this.right(), deg_to_rad(rotIncrementX)); // quat.setAxisAngle(vertRot, this.right(), deg_to_rad(rotIncrementX));
quat.setAxisAngle(vertRot, vec3.fromValues(1, 0, 0), deg_to_rad(rotIncrementX));
const newRot = quat.create(); const newRot = quat.create();
quat.mul(newRot, horizRot, vertRot); quat.mul(newRot, horizRot, vertRot);
const v = vec3.create(); const v = vec3.create();
vec3.sub(v, this.position, this.orbitingPivot); vec3.sub(v, this.position, this.orbiting.pivot);
const newPos = vec3.create(); const newPos = vec3.create();
const shift = vec3.create(); const shift = vec3.create();
vec3.transformQuat(shift, v, newRot); vec3.transformQuat(shift, v, newRot);
vec3.add(newPos, this.orbitingPivot, shift); vec3.add(newPos, this.orbiting.pivot, shift);
vec3.copy(this.position, newPos); vec3.copy(this.position, newPos);
quat.mul(this.rotation, newRot, this.rotation); quat.mul(this.rotation, newRot, this.rotation);
...@@ -153,19 +186,19 @@ export class SmoothCamera extends Camera { ...@@ -153,19 +186,19 @@ export class SmoothCamera extends Camera {
} }
protected updatePanning(dt: number): void { protected updatePanning(dt: number): void {
this.panCurrentLerpTime += dt; this.panning.currentLerpTime += dt;
if (this.panCurrentLerpTime > this.animTime) this.panCurrentLerpTime = this.animTime; if (this.panning.currentLerpTime > this.animTime) this.panning.currentLerpTime = this.animTime;
const perc = this.panCurrentLerpTime / this.animTime; const perc = this.panning.currentLerpTime / this.animTime;
const currentFramePosition = vec3.create(); const currentFramePosition = vec3.create();
vec3.lerp(currentFramePosition, this.panStartPosition, this.panEndPosition, easeOutExp(perc)); vec3.lerp(currentFramePosition, this.panning.startPosition, this.panning.endPosition, easeOutExp(perc));
const frameOffset = vec3.create(); const frameOffset = vec3.create();
vec3.sub(frameOffset, currentFramePosition, this.lastFramePosition); vec3.sub(frameOffset, currentFramePosition, this.panning.lastFramePosition);
vec3.copy(this.lastFramePosition, currentFramePosition); vec3.copy(this.panning.lastFramePosition, currentFramePosition);
vec3.add(this.position, this.position, frameOffset); vec3.add(this.position, this.position, frameOffset);
//~ Seems like I should also add this, otherwise orbiting will be weird... //~ Seems like I should also add this, otherwise orbiting will be weird...
vec3.add(this.orbitingPivot, this.orbitingPivot, frameOffset); vec3.add(this.orbiting.pivot, this.orbiting.pivot, frameOffset);
this.isMoving = this.isMoving || (perc < 1.0); this.isMoving = this.isMoving || (perc < 1.0);
...@@ -178,7 +211,7 @@ export class SmoothCamera extends Camera { ...@@ -178,7 +211,7 @@ export class SmoothCamera extends Camera {
type: CameraConfigurationType.Smooth, type: CameraConfigurationType.Smooth,
position: { x: this.position[0], y: this.position[1], z: this.position[2] }, position: { x: this.position[0], y: this.position[1], z: this.position[2] },
lookAtPosition: { x: this.orbitingPivot[0], y: this.orbitingPivot[1], z: this.orbitingPivot[2] }, lookAtPosition: { x: this.orbiting.pivot[0], y: this.orbiting.pivot[1], z: this.orbiting.pivot[2] },
rotationQuat: { x: this.rotation[0], y: this.rotation[1], z: this.rotation[2], w: this.rotation[3] } rotationQuat: { x: this.rotation[0], y: this.rotation[1], z: this.rotation[2], w: this.rotation[3] }
}; };
} }
...@@ -198,6 +231,14 @@ export class SmoothCamera extends Camera { ...@@ -198,6 +231,14 @@ export class SmoothCamera extends Camera {
public get rotation(): quat { public get rotation(): quat {
return this._rotation; return this._rotation;
} }
public get orbitingPivot(): vec3 {
return this.orbiting.pivot;
}
public set orbitingPivot(pivot: vec3) {
this.orbiting.pivot = pivot;
}
//#endregion //#endregion
protected computeModelViewMatrix(camPosition: vec3, lookAtPosition: vec3): mat4 { protected computeModelViewMatrix(camPosition: vec3, lookAtPosition: vec3): mat4 {
...@@ -209,7 +250,7 @@ export class SmoothCamera extends Camera { ...@@ -209,7 +250,7 @@ export class SmoothCamera extends Camera {
protected getModelViewMatrix(): mat4 { protected getModelViewMatrix(): mat4 {
let mvm = mat4.create(); let mvm = mat4.create();
mvm = this.computeModelViewMatrix(this.position, this.orbitingPivot); mvm = this.computeModelViewMatrix(this.position, this.orbiting.pivot);
return mvm; return mvm;
} }
...@@ -255,11 +296,11 @@ export class SmoothCamera extends Camera { ...@@ -255,11 +296,11 @@ export class SmoothCamera extends Camera {
this.dragging = true; this.dragging = true;
} }
this.orbitCurrentLerpTime = 0.0; this.orbiting.currentLerpTime = 0.0;
this.orbitLastFrameAngleX = 0.0; this.orbiting.lastFrameAngleX = 0.0;
this.orbitLastFrameAngleY = 0.0; this.orbiting.lastFrameAngleY = 0.0;
this.orbitEndAngleY = delta.x * this.orbitingSpeed; this.orbiting.endAngleY = delta.x * this.orbitingSpeed;
this.orbitEndAngleX = delta.y * this.orbitingSpeed; this.orbiting.endAngleX = delta.y * this.orbitingSpeed;
this.lastMousePos = { x: event.screenX, y: event.screenY }; this.lastMousePos = { x: event.screenX, y: event.screenY };
} }
...@@ -267,17 +308,17 @@ export class SmoothCamera extends Camera { ...@@ -267,17 +308,17 @@ export class SmoothCamera extends Camera {
{ {
const delta = { x: event.screenX - this.lastMousePos.x, y: event.screenY - this.lastMousePos.y }; const delta = { x: event.screenX - this.lastMousePos.x, y: event.screenY - this.lastMousePos.y };
vec3.copy(this.panStartPosition, this.position); vec3.copy(this.panning.startPosition, this.position);
vec3.copy(this.lastFramePosition, this.position); vec3.copy(this.panning.lastFramePosition, this.position);
vec3.copy(this.panEndPosition, this.position); vec3.copy(this.panning.endPosition, this.position);
const incrVec = vec3.create(); const incrVec = vec3.create();
vec3.scale(incrVec, this.up(), delta.y * this.panningSpeed); vec3.scale(incrVec, this.up(), delta.y * this.panningSpeed);
vec3.add(this.panEndPosition, this.panEndPosition, incrVec); vec3.add(this.panning.endPosition, this.panning.endPosition, incrVec);
vec3.scale(incrVec, this.right(), delta.x * this.panningSpeed); vec3.scale(incrVec, this.right(), delta.x * this.panningSpeed);
vec3.add(this.panEndPosition, this.panEndPosition, incrVec); vec3.add(this.panning.endPosition, this.panning.endPosition, incrVec);
this.panCurrentLerpTime = 0.0; this.panning.currentLerpTime = 0.0;
this.lastMousePos = { x: event.screenX, y: event.screenY }; this.lastMousePos = { x: event.screenX, y: event.screenY };
} }
...@@ -308,11 +349,11 @@ export class SmoothCamera extends Camera { ...@@ -308,11 +349,11 @@ export class SmoothCamera extends Camera {
if (this.ignoreEvents) return; if (this.ignoreEvents) return;
const speed = this.scrollingSpeed; const speed = this.zoomingSpeed;
this.zoomEndAmount = event.deltaY * speed; this.zooming.endAmount = event.deltaY * speed;
this.lastFrameZoomAmount = 0.0; this.zooming.lastFrameZoomAmount = 0.0;
this.zoomCurrentLerpTime = 0.0; this.zooming.currentLerpTime = 0.0;
this.currentMousePos = { x: event.offsetX, y: event.offsetY }; this.currentMousePos = { x: event.offsetX, y: event.offsetY };
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment