;;; Catbird Game Engine ;;; Copyright © 2022 David Thompson ;;; ;;; Catbird is free software: you can redistribute it and/or modify it ;;; under the terms of the GNU General Public License as published by ;;; the Free Software Foundation, either version 3 of the License, or ;;; (at your option) any later version. ;;; ;;; Catbird is distributed in the hope that it will be useful, but ;;; WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;; General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with Catbird. If not, see . ;;; Commentary: ;; ;; Views into a scene. ;; ;;; Code: (define-module (catbird camera) #:use-module (catbird config) #:use-module (catbird mixins) #:use-module (chickadee math) #:use-module (chickadee math matrix) #:use-module (chickadee math rect) #:use-module (chickadee math vector) #:use-module (oop goops) #:export ( projection-matrix view-matrix current-camera view-bounding-box move-to move-by field-of-vision near-clip far-clip direction up) #:re-export (width height)) (define-root-class () (width #:accessor width #:init-keyword #:width) (height #:accessor height #:init-keyword #:height) (projection-matrix #:getter projection-matrix #:init-thunk make-identity-matrix4) (view-matrix #:getter view-matrix #:init-thunk make-identity-matrix4)) (define-generic refresh-projection) (define-generic refresh-view) (define-method (initialize (camera ) args) (next-method) (refresh-projection camera) (refresh-view camera)) (define current-camera (make-parameter #f)) ;;; ;;; 2D Camera ;;; (define-class ( ) (view-bounding-box #:accessor view-bounding-box #:init-thunk make-null-rect)) (define-method (initialize (camera ) initargs) (next-method) (let ((bb (view-bounding-box camera))) (set-rect-width! bb (width camera)) (set-rect-height! bb (height camera)))) (define-method (refresh-projection (camera )) (orthographic-projection! (projection-matrix camera) 0.0 (width camera) (height camera) 0.0 0.0 1.0)) (define-method (refresh-view (camera )) (let ((p (position camera)) (bb (view-bounding-box camera))) (matrix4-translate! (view-matrix camera) p) (set-rect-x! bb (vec2-x p)) (set-rect-y! bb (vec2-y p)))) (define-method (move-to (camera ) p) (vec2-copy! p (position camera)) (refresh-view camera)) (define-method (move-by (camera ) d) (vec2-add! (position camera) d) (refresh-view camera)) ;;; ;;; 3D Camera ;;; (define-class ( ) (field-of-vision #:getter field-of-vision #:init-keyword #:field-of-vision #:init-value (degrees->radians 60)) (near-clip #:getter near-clip #:init-keyword #:near-clip #:init-value 0.1) (far-clip #:getter far-clip #:init-keyword #:far-clip #:init-value 5.0) (direction #:getter direction #:init-keyword #:direction #:init-form (vec3 0.0 0.0 -1.0)) (up #:getter up #:init-keyword #:up #:init-form (vec3 0.0 1.0 0.0))) (define-method (refresh-projection (camera )) (perspective-projection! (projection-matrix camera) (field-of-vision camera) (/ (width camera) (height camera)) (near-clip camera) (far-clip camera))) (define-method (refresh-view (camera )) (look-at! (view-matrix camera) (position camera) (direction camera) (up camera))) (define-method (move-to (camera ) p) (vec3-copy! p (position camera)) (refresh-view camera)) (define-method (move-by (camera ) d) (vec3-add! (position camera) d) (refresh-view camera))