Skip to content
Snippets Groups Projects
Commit 60f55585 authored by Alexander Rose's avatar Alexander Rose
Browse files

wip, camera as a data-only object

parent 07a97e6e
No related branches found
No related tags found
No related merge requests found
......@@ -6,7 +6,7 @@
import { Mat4, Vec3, Vec4 } from 'mol-math/linear-algebra'
import { cameraProject, cameraUnproject, cameraLookAt, Viewport } from './util';
import { Object3D, createObject3D } from 'mol-gl/object3d';
import { Object3D } from 'mol-gl/object3d';
export interface Camera extends Object3D {
readonly projection: Mat4,
......@@ -18,12 +18,6 @@ export interface Camera extends Object3D {
far: number,
fogNear: number,
fogFar: number,
translate: (v: Vec3) => void,
reset: () => void,
lookAt: (target: Vec3) => void,
project: (out: Vec4, point: Vec3) => Vec4,
unproject: (out: Vec3, point: Vec3) => Vec3
}
export const DefaultCameraProps = {
......@@ -31,18 +25,19 @@ export const DefaultCameraProps = {
direction: Vec3.create(0, 0, -1),
up: Vec3.create(0, 1, 0),
viewport: Viewport.create(-1, -1, 1, 1),
near: 0.1,
far: 10000,
fogNear: 0.1,
fogFar: 10000,
}
export type CameraProps = Partial<typeof DefaultCameraProps>
export type CameraProps = typeof DefaultCameraProps
export namespace Camera {
export function create(props?: CameraProps): Camera {
export function create(props?: Partial<CameraProps>): Camera {
const p = { ...DefaultCameraProps, ...props };
const { view, position, direction, up } = createObject3D()
const { view, position, direction, up } = Object3D.create()
Vec3.copy(position, p.position)
Vec3.copy(direction, p.direction)
Vec3.copy(up, p.up)
......@@ -52,63 +47,53 @@ export namespace Camera {
const projectionView = Mat4.identity()
const inverseProjectionView = Mat4.identity()
function update () {
Mat4.mul(projectionView, projection, view)
Mat4.invert(inverseProjectionView, projectionView)
}
function lookAt (target: Vec3) {
cameraLookAt(direction, up, position, target)
}
function reset () {
Vec3.copy(position, p.position)
Vec3.copy(direction, p.direction)
Vec3.copy(up, p.up)
Mat4.setIdentity(view)
Mat4.setIdentity(projection)
Mat4.setIdentity(projectionView)
Mat4.setIdentity(inverseProjectionView)
}
function translate (v: Vec3) {
Vec3.add(position, position, v)
}
function project (out: Vec4, point: Vec3) {
return cameraProject(out, point, viewport, projectionView)
}
function unproject (out: Vec3, point: Vec3) {
return cameraUnproject(out, point, viewport, inverseProjectionView)
}
return {
view,
projection,
projectionView,
inverseProjectionView,
viewport,
view,
position,
direction,
up,
get near() { return p.near },
set near(value: number) { p.near = value },
get far() { return p.far },
set far(value: number) { p.far = value },
get fogNear() { return p.fogNear },
set fogNear(value: number) { p.fogNear = value },
get fogFar() { return p.fogFar },
set fogFar(value: number) { p.fogFar = value },
translate,
reset,
lookAt,
update,
project,
unproject
near: p.near,
far: p.far,
fogNear: p.fogNear,
fogFar: p.fogFar,
}
}
export function update (camera: Camera) {
Mat4.mul(camera.projectionView, camera.projection, camera.view)
Mat4.invert(camera.inverseProjectionView, camera.projectionView)
return camera
}
export function lookAt (camera: Camera, target: Vec3) {
cameraLookAt(camera.direction, camera.up, camera.position, target)
}
export function reset (camera: Camera, props: CameraProps) {
Vec3.copy(camera.position, props.position)
Vec3.copy(camera.direction, props.direction)
Vec3.copy(camera.up, props.up)
Mat4.setIdentity(camera.view)
Mat4.setIdentity(camera.projection)
Mat4.setIdentity(camera.projectionView)
Mat4.setIdentity(camera.inverseProjectionView)
}
export function translate (camera: Camera, v: Vec3) {
Vec3.add(camera.position, camera.position, v)
}
export function project (camera: Camera, out: Vec4, point: Vec3) {
return cameraProject(out, point, camera.viewport, camera.projectionView)
}
export function unproject (camera: Camera, out: Vec3, point: Vec3) {
return cameraUnproject(out, point, camera.viewport, camera.inverseProjectionView)
}
}
\ No newline at end of file
......@@ -9,8 +9,6 @@ import { DefaultCameraProps, Camera } from './base'
export interface PerspectiveCamera extends Camera {
fov: number,
near: number,
far: number
}
export const DefaultPerspectiveCameraProps = {
......@@ -21,33 +19,30 @@ export type PerspectiveCameraProps = Partial<typeof DefaultPerspectiveCameraProp
export namespace PerspectiveCamera {
export function create(props: PerspectiveCameraProps = {}): PerspectiveCamera {
let { fov, near, far } = { ...DefaultPerspectiveCameraProps, ...props };
let { fov } = { ...DefaultPerspectiveCameraProps, ...props };
const camera = Camera.create(props)
const center = Vec3.zero()
const camera = {
...Camera.create(props),
fov
}
function update () {
const aspect = camera.viewport.width / camera.viewport.height
update(camera)
// build projection matrix
Mat4.perspective(camera.projection, fov, aspect, Math.abs(near), Math.abs(far))
return camera
}
// build view matrix
Vec3.add(center, camera.position, camera.direction)
Mat4.lookAt(camera.view, camera.position, center, camera.up)
const center = Vec3.zero()
export function update(camera: PerspectiveCamera) {
const aspect = camera.viewport.width / camera.viewport.height
// update projection * view and invert
camera.update()
}
// build projection matrix
Mat4.perspective(camera.projection, camera.fov, aspect, Math.abs(camera.near), Math.abs(camera.far))
update()
// build view matrix
Vec3.add(center, camera.position, camera.direction)
Mat4.lookAt(camera.view, camera.position, center, camera.up)
return {
...camera,
update,
get fov() { return fov },
set fov(value: number) { fov = value },
}
// update projection * view and invert
Camera.update(camera)
}
}
\ No newline at end of file
......@@ -132,13 +132,13 @@ namespace Canvas3D {
}
}
let nearPlaneDelta = 0
function computeNearDistance() {
const focusRadius = scene.boundingSphere.radius
let dist = Vec3.distance(controls.target, camera.position)
if (dist > focusRadius) return dist - focusRadius
return 0
}
// let nearPlaneDelta = 0
// function computeNearDistance() {
// const focusRadius = scene.boundingSphere.radius
// let dist = Vec3.distance(controls.target, camera.position)
// if (dist > focusRadius) return dist - focusRadius
// return 0
// }
function render(variant: RenderVariant, force?: boolean) {
if (isPicking) return false
......@@ -146,18 +146,19 @@ namespace Canvas3D {
// console.log(p[0], p[1], p[2])
// Vec3.set(controls.target, p[0], p[1], p[2])
const focusRadius = scene.boundingSphere.radius
const targetDistance = Vec3.distance(controls.target, camera.position)
// TODO update near/far
// const focusRadius = scene.boundingSphere.radius
// const targetDistance = Vec3.distance(controls.target, camera.position)
// console.log(targetDistance, controls.target, camera.position)
let near = computeNearDistance() + nearPlaneDelta
camera.near = Math.max(0.01, Math.min(near, targetDistance - 0.5))
// let near = computeNearDistance() + nearPlaneDelta
// camera.near = Math.max(0.01, Math.min(near, targetDistance - 0.5))
let fogNear = targetDistance - camera.near + 1 * focusRadius - nearPlaneDelta;
let fogFar = targetDistance - camera.near + 2 * focusRadius - nearPlaneDelta;
// let fogNear = targetDistance - camera.near + 1 * focusRadius - nearPlaneDelta;
// let fogFar = targetDistance - camera.near + 2 * focusRadius - nearPlaneDelta;
// console.log(fogNear, fogFar);
camera.fogNear = Math.max(fogNear, 0.1);
camera.fogFar = Math.max(fogFar, 0.2);
// // console.log(fogNear, fogFar);
// camera.fogNear = Math.max(fogNear, 0.1);
// camera.fogFar = Math.max(fogFar, 0.2);
// console.log(camera.fogNear, camera.fogFar, targetDistance)
......@@ -172,7 +173,7 @@ namespace Canvas3D {
}
let didRender = false
controls.update()
camera.update()
PerspectiveCamera.update(camera)
if (force || !Mat4.areEqual(camera.projectionView, prevProjectionView, EPSILON.Value) || !Mat4.areEqual(scene.view, prevSceneView, EPSILON.Value)) {
// console.log('foo', force, prevSceneView, scene.view)
Mat4.copy(prevProjectionView, camera.projectionView)
......
......@@ -7,36 +7,25 @@
import { Vec3, Mat4 } from 'mol-math/linear-algebra';
export interface Object3D {
readonly view: Mat4,
readonly position: Vec3,
readonly direction: Vec3,
readonly up: Vec3,
update: () => void
readonly view: Mat4
readonly position: Vec3
readonly direction: Vec3
readonly up: Vec3
}
export function createObject3D(): Object3D {
const view = Mat4.identity()
const position = Vec3.create(0, 0, 0)
const direction = Vec3.create(0, 0, -1)
const up = Vec3.create(0, 1, 0)
export namespace Object3D {
export function create(): Object3D {
return {
view: Mat4.identity(),
position: Vec3.create(0, 0, 0),
direction: Vec3.create(0, 0, -1),
up: Vec3.create(0, 1, 0),
}
}
const center = Vec3.zero()
return {
view,
position,
direction,
up,
update() {
// console.log('position', position)
// console.log('direction', direction)
// console.log('up', up)
Vec3.add(center, position, direction)
Mat4.lookAt(view, position, center, up)
// Mat4.lookAt(view, center, position, up)
// console.log('view', view)
}
export function update(object3d: Object3D) {
Vec3.add(center, object3d.position, object3d.direction)
Mat4.lookAt(object3d.view, object3d.position, center, object3d.up)
}
}
\ No newline at end of file
......@@ -8,7 +8,7 @@ import { Renderable } from './renderable'
import { WebGLContext } from './webgl/context';
import { RenderableValues, BaseValues } from './renderable/schema';
import { RenderObject, createRenderable } from './render-object';
import { Object3D, createObject3D } from './object3d';
import { Object3D } from './object3d';
import { Sphere3D } from 'mol-math/geometry';
import { Vec3 } from 'mol-math/linear-algebra';
......@@ -39,6 +39,7 @@ interface Scene extends Object3D {
readonly count: number
readonly boundingSphere: Sphere3D
update: () => void
add: (o: RenderObject) => void
remove: (o: RenderObject) => void
clear: () => void
......@@ -52,14 +53,13 @@ namespace Scene {
const renderableMap = new Map<RenderObject, Renderable<RenderableValues & BaseValues>>()
let boundingSphere: Sphere3D | undefined
const { view, position, up, direction, update } = createObject3D()
const object3d = Object3D.create()
return {
// ...createObject3D(), // TODO does not work in conjunction with getter
view, position, up, direction,
...object3d,
update: () => {
update()
Object3D.update(object3d)
renderableMap.forEach(r => r.update())
boundingSphere = undefined
},
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment