Bladeren bron

wip, camera as a data-only object

Alexander Rose 6 jaren geleden
bovenliggende
commit
60f5558545
5 gewijzigde bestanden met toevoegingen van 100 en 130 verwijderingen
  1. 43 58
      src/mol-canvas3d/camera/base.ts
  2. 18 23
      src/mol-canvas3d/camera/perspective.ts
  3. 18 17
      src/mol-canvas3d/canvas3d.ts
  4. 16 27
      src/mol-gl/object3d.ts
  5. 5 5
      src/mol-gl/scene.ts

+ 43 - 58
src/mol-canvas3d/camera/base.ts

@@ -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)
+    }
 }

+ 18 - 23
src/mol-canvas3d/camera/perspective.ts

@@ -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)
     }
 }

+ 18 - 17
src/mol-canvas3d/canvas3d.ts

@@ -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)

+ 16 - 27
src/mol-gl/object3d.ts

@@ -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)
     }
 }

+ 5 - 5
src/mol-gl/scene.ts

@@ -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
             },