Refactor the game module and rethink the way to import symbols
From now on, import symbols from other packages when it makes sense.
This commit is contained in:
parent
9faa777972
commit
d8df41dbe4
9 changed files with 169 additions and 132 deletions
40
src/camera.lisp
Normal file
40
src/camera.lisp
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#|
|
||||||
|
This file is a part of stoe project.
|
||||||
|
Copyright (c) 2014 Renaud Casenave-Péré (renaud@casenave-pere.fr)
|
||||||
|
|#
|
||||||
|
|
||||||
|
(in-package :cl-user)
|
||||||
|
(defpackage stoe.camera
|
||||||
|
(:nicknames :camera)
|
||||||
|
(:use :cl)
|
||||||
|
(:export :camera :view :proj
|
||||||
|
:make-camera
|
||||||
|
:update-view)
|
||||||
|
(:import-from :object
|
||||||
|
:object :pos :dir))
|
||||||
|
(in-package :stoe.camera)
|
||||||
|
|
||||||
|
(defclass camera (object)
|
||||||
|
((fovy :initarg :fovy :accessor fovy)
|
||||||
|
(aspect :initarg :aspect :accessor aspect)
|
||||||
|
(near :initarg :near :accessor near)
|
||||||
|
(far :initarg :far :accessor far)
|
||||||
|
(projection :initarg :projection :accessor proj :type 'f44:float44)
|
||||||
|
(view :accessor view :type 'f44:float44))
|
||||||
|
(:documentation "Base class for a camera representing a view of the game world."))
|
||||||
|
|
||||||
|
(defun make-camera (fovy aspect near far)
|
||||||
|
(let ((camera (make-instance 'camera :position (v:vec 0 0 2)
|
||||||
|
:direction (q:from-axis-and-angle (v:vec 0 0 1) 0)
|
||||||
|
:fovy fovy
|
||||||
|
:aspect aspect
|
||||||
|
:near near
|
||||||
|
:far far
|
||||||
|
:projection (geom:make-persp-matrix fovy aspect near far))))
|
||||||
|
(update-view camera)
|
||||||
|
camera))
|
||||||
|
|
||||||
|
(defun update-view (camera)
|
||||||
|
"Compute the world to view matrix from the position and the direction of `camera'."
|
||||||
|
(with-accessors ((pos pos) (dir dir) (view view)) camera
|
||||||
|
(setf view (m:* (m::transpose (q:to-float44 dir)) (geom:mat-trans (v:- pos))))))
|
||||||
|
|
@ -10,7 +10,9 @@
|
||||||
(:export :get-world-origin
|
(:export :get-world-origin
|
||||||
:get-current-camera)
|
:get-current-camera)
|
||||||
(:import-from :modules
|
(:import-from :modules
|
||||||
:defmodule))
|
:defmodule)
|
||||||
|
(:import-from :camera
|
||||||
|
:make-camera :update-view))
|
||||||
(in-package :stoe.game)
|
(in-package :stoe.game)
|
||||||
|
|
||||||
(defconstant +loop-step-time+ 16000.0
|
(defconstant +loop-step-time+ 16000.0
|
||||||
|
|
@ -31,9 +33,9 @@ we need to keep the remaining time.")
|
||||||
(declare (ignore argv))
|
(declare (ignore argv))
|
||||||
(format t "Initialize Game module~%")
|
(format t "Initialize Game module~%")
|
||||||
(input:initialize)
|
(input:initialize)
|
||||||
(setf *world-origin* (go:make-object))
|
(setf *world-origin* (object:make-object))
|
||||||
(setf *current-camera* (go:make-camera 90 (/ 16 9) 1.0 1000.0))
|
(setf *current-camera* (make-camera 90 (/ 16 9) 1.0 1000.0))
|
||||||
(go:attach *current-camera* *world-origin*))
|
(scene:attach *current-camera* *world-origin*))
|
||||||
|
|
||||||
(defun finalize ()
|
(defun finalize ()
|
||||||
"Finalize the game module."
|
"Finalize the game module."
|
||||||
|
|
@ -48,7 +50,7 @@ Advance the world by `delta-time', +loop-step-time+ at a time."
|
||||||
(loop while (> delta-time +loop-step-time+)
|
(loop while (> delta-time +loop-step-time+)
|
||||||
do (progn
|
do (progn
|
||||||
(when *current-camera*
|
(when *current-camera*
|
||||||
(go:update-view *current-camera*))
|
(update-view *current-camera*))
|
||||||
(input:update +loop-step-time+)
|
(input:update +loop-step-time+)
|
||||||
(decf delta-time +loop-step-time+)))
|
(decf delta-time +loop-step-time+)))
|
||||||
(setf *last-frame-remaining-time* delta-time))
|
(setf *last-frame-remaining-time* delta-time))
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
#|
|
|
||||||
This file is a part of stoe project.
|
|
||||||
Copyright (c) 2014 Renaud Casenave-Péré (renaud@casenave-pere.fr)
|
|
||||||
|#
|
|
||||||
|
|
||||||
(in-package :cl-user)
|
|
||||||
(defpackage stoe.game.game-object
|
|
||||||
(:use :cl)
|
|
||||||
(:nicknames :game-object :go)
|
|
||||||
(:shadow :position)
|
|
||||||
(:export :node
|
|
||||||
:parent
|
|
||||||
:children
|
|
||||||
:attach
|
|
||||||
:detach
|
|
||||||
:walk
|
|
||||||
:position
|
|
||||||
:direction
|
|
||||||
:make-object
|
|
||||||
:update-trans-matrix
|
|
||||||
:make-camera
|
|
||||||
:view
|
|
||||||
:update-view))
|
|
||||||
(in-package :stoe.game.game-object)
|
|
||||||
|
|
||||||
(defclass scene-node ()
|
|
||||||
((parent :initform nil :reader parent)
|
|
||||||
(children :initform nil :reader children))
|
|
||||||
(:documentation "Base class for a node in the scene graph."))
|
|
||||||
|
|
||||||
(defgeneric attach (scene-node parent)
|
|
||||||
(:documentation "Attach a new node to the scene graph to be rendered."))
|
|
||||||
|
|
||||||
(defmethod attach ((scene-node scene-node) (parent scene-node))
|
|
||||||
(with-slots (children) parent
|
|
||||||
(with-slots ((new-parent parent)) scene-node
|
|
||||||
(push scene-node children)
|
|
||||||
(setf new-parent parent))))
|
|
||||||
|
|
||||||
(defgeneric detach (scene-node)
|
|
||||||
(:documentation "Detach a node from the scene graph to prevent it and its
|
|
||||||
children from being rendered."))
|
|
||||||
|
|
||||||
(defmethod detach ((scene-node scene-node))
|
|
||||||
(with-slots (parent) scene-node
|
|
||||||
(with-slots (children) parent
|
|
||||||
(setf children (remove scene-node children))
|
|
||||||
(setf parent nil))))
|
|
||||||
|
|
||||||
(defun walk (fun node)
|
|
||||||
"Walk through the scene graph and apply `fun' at each node."
|
|
||||||
(with-slots (children) node
|
|
||||||
(loop for child in children
|
|
||||||
do (progn
|
|
||||||
(apply fun child)
|
|
||||||
(walk fun child)))))
|
|
||||||
|
|
||||||
(defclass game-object (scene-node)
|
|
||||||
((position :initarg :position :accessor position :type 'f3:float3)
|
|
||||||
(direction :initarg :direction :accessor direction :type 'q:quaternion)
|
|
||||||
(trans-matrix :initform (f44:mat-ident) :accessor trans-matrix :type 'f44:float44)
|
|
||||||
(components :initform nil))
|
|
||||||
(:documentation "Base class for all objects existing in the game world."))
|
|
||||||
|
|
||||||
(defclass camera (game-object)
|
|
||||||
((fovy :initarg :fovy :accessor fovy)
|
|
||||||
(aspect :initarg :aspect :accessor aspect)
|
|
||||||
(near :initarg :near :accessor near)
|
|
||||||
(far :initarg :far :accessor far)
|
|
||||||
(projection :initarg :projection :accessor projection :type 'f44:float44)
|
|
||||||
(view :accessor view :type 'f44:float44))
|
|
||||||
(:documentation "Base class for a camera representing a view of the game world."))
|
|
||||||
|
|
||||||
(defun make-object (&key (pos (v:vec 0 0 0)) (dir (q:from-axis-and-angle (v:vec 0 0 1) 0)) mesh)
|
|
||||||
(let ((obj (make-instance 'game-object :position pos :direction dir)))
|
|
||||||
(when mesh
|
|
||||||
(with-slots (components) obj
|
|
||||||
(push mesh components)))
|
|
||||||
obj))
|
|
||||||
|
|
||||||
(defun update-trans-matrix (node)
|
|
||||||
(setf (trans-matrix node) (m:* (trans-matrix (parent node))
|
|
||||||
(geom:mat-trans (position node))
|
|
||||||
(q:to-float44 (direction node)))))
|
|
||||||
|
|
||||||
(defun make-camera (fovy aspect near far)
|
|
||||||
(let ((camera (make-instance 'camera :position (v:vec 0 0 2)
|
|
||||||
:direction (q:from-axis-and-angle (v:vec 0 0 1) 0)
|
|
||||||
:fovy fovy
|
|
||||||
:aspect aspect
|
|
||||||
:near near
|
|
||||||
:far far
|
|
||||||
:projection (geom:make-persp-matrix fovy aspect near far))))
|
|
||||||
(update-view camera)
|
|
||||||
camera))
|
|
||||||
|
|
||||||
(defun update-view (camera)
|
|
||||||
"Compute the world to view matrix from the position and the direction of `camera'."
|
|
||||||
(with-accessors ((pos go:position) (dir go:direction) (view view)) camera
|
|
||||||
(setf view (m:* (m::transpose (q:to-float44 dir)) (geom:mat-trans (v:- pos))))))
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|#
|
|#
|
||||||
|
|
||||||
(in-package :cl-user)
|
(in-package :cl-user)
|
||||||
(defpackage stoe.game.input
|
(defpackage stoe.input
|
||||||
(:nicknames :input)
|
(:nicknames :input)
|
||||||
(:use :cl :alexandria
|
(:use :cl :alexandria
|
||||||
:utils :containers)
|
:utils :containers)
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
:make-keymap :set-global-keymap
|
:make-keymap :set-global-keymap
|
||||||
:define-key :global-set-key
|
:define-key :global-set-key
|
||||||
:define-motion :global-set-motion))
|
:define-motion :global-set-motion))
|
||||||
(in-package :stoe.game.input)
|
(in-package :stoe.input)
|
||||||
|
|
||||||
(define-constant +keyevent-classes+ '(:press :release :repeat :continuous)
|
(define-constant +keyevent-classes+ '(:press :release :repeat :continuous)
|
||||||
:test #'equal :documentation "List of the available key event classes.")
|
:test #'equal :documentation "List of the available key event classes.")
|
||||||
33
src/object.lisp
Normal file
33
src/object.lisp
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#|
|
||||||
|
This file is a part of stoe project.
|
||||||
|
Copyright (c) 2014 Renaud Casenave-Péré (renaud@casenave-pere.fr)
|
||||||
|
|#
|
||||||
|
|
||||||
|
(in-package :cl-user)
|
||||||
|
(defpackage stoe.object
|
||||||
|
(:use :cl)
|
||||||
|
(:nicknames :object)
|
||||||
|
(:export :object :pos :dir :trans-mat :components
|
||||||
|
:make-object :update-trans-matrix)
|
||||||
|
(:import-from :scene
|
||||||
|
:scene-node :parent))
|
||||||
|
(in-package :stoe.object)
|
||||||
|
|
||||||
|
(defclass object (scene-node)
|
||||||
|
((position :initarg :position :accessor pos :type 'f3:float3)
|
||||||
|
(direction :initarg :direction :accessor dir :type 'q:quaternion)
|
||||||
|
(trans-matrix :initform (f44:mat-ident) :accessor trans-mat :type 'f44:float44)
|
||||||
|
(components :initform nil :reader components))
|
||||||
|
(:documentation "Base class for all objects existing in the game world."))
|
||||||
|
|
||||||
|
(defun make-object (&key (pos (v:vec 0 0 0)) (dir (q:from-axis-and-angle (v:vec 0 0 1) 0)) mesh)
|
||||||
|
(let ((obj (make-instance 'object :position pos :direction dir)))
|
||||||
|
(when mesh
|
||||||
|
(with-slots (components) obj
|
||||||
|
(push mesh components)))
|
||||||
|
obj))
|
||||||
|
|
||||||
|
(defun update-trans-matrix (node)
|
||||||
|
(setf (trans-mat node) (m:* (trans-mat (parent node))
|
||||||
|
(geom:mat-trans (pos node))
|
||||||
|
(q:to-float44 (dir node)))))
|
||||||
|
|
@ -10,7 +10,15 @@
|
||||||
:utils)
|
:utils)
|
||||||
(:export :poll-events)
|
(:export :poll-events)
|
||||||
(:import-from :modules
|
(:import-from :modules
|
||||||
:defmodule))
|
:defmodule)
|
||||||
|
(:import-from :game
|
||||||
|
:get-current-camera)
|
||||||
|
(:import-from :scene
|
||||||
|
:children)
|
||||||
|
(:import-from :object
|
||||||
|
:trans-mat :components :update-trans-matrix)
|
||||||
|
(:import-from :camera
|
||||||
|
:proj :view))
|
||||||
(in-package :stoe.render)
|
(in-package :stoe.render)
|
||||||
|
|
||||||
(defvar *window* nil)
|
(defvar *window* nil)
|
||||||
|
|
@ -84,7 +92,7 @@ This needs to be called once per frame, at the beginning of the loop."
|
||||||
(defvar *height* 0)
|
(defvar *height* 0)
|
||||||
|
|
||||||
(defun on-resize-event (width height)
|
(defun on-resize-event (width height)
|
||||||
(setf (go::projection (game:get-current-camera)) (geom:make-persp-matrix 30 (/ width height) 1.0 1000.0))
|
(setf (proj (get-current-camera)) (geom:make-persp-matrix 30 (/ width height) 1.0 1000.0))
|
||||||
(setf *width* width)
|
(setf *width* width)
|
||||||
(setf *height* height)
|
(setf *height* height)
|
||||||
(gl:viewport 0 0 width height))
|
(gl:viewport 0 0 width height))
|
||||||
|
|
@ -94,9 +102,9 @@ This needs to be called once per frame, at the beginning of the loop."
|
||||||
(loop for stream in (mesh::mesh-streams mesh)
|
(loop for stream in (mesh::mesh-streams mesh)
|
||||||
do (shader::using-program (program (mesh::mesh-stream-program stream))
|
do (shader::using-program (program (mesh::mesh-stream-program stream))
|
||||||
(shader::with-uniforms (model-to-camera camera-to-clip) program
|
(shader::with-uniforms (model-to-camera camera-to-clip) program
|
||||||
(gl:uniform-matrix model-to-camera 4 (vector (m:* (go::view (game:get-current-camera))
|
(gl:uniform-matrix model-to-camera 4 (vector (m:* (view (get-current-camera))
|
||||||
(go::trans-matrix node))))
|
(trans-mat node))))
|
||||||
(gl:uniform-matrix camera-to-clip 4 (vector (go::projection (game:get-current-camera)))))
|
(gl:uniform-matrix camera-to-clip 4 (vector (proj (get-current-camera)))))
|
||||||
(let* ((vertex-buffer (mesh::mesh-stream-vertex-buffer stream))
|
(let* ((vertex-buffer (mesh::mesh-stream-vertex-buffer stream))
|
||||||
(index-buffer (mesh::mesh-stream-index-buffer stream))
|
(index-buffer (mesh::mesh-stream-index-buffer stream))
|
||||||
(attribs (mesh::vertex-buffer-attribs vertex-buffer)))
|
(attribs (mesh::vertex-buffer-attribs vertex-buffer)))
|
||||||
|
|
@ -118,16 +126,16 @@ This needs to be called once per frame, at the beginning of the loop."
|
||||||
|
|
||||||
(defun render-node (node)
|
(defun render-node (node)
|
||||||
"Render a single node."
|
"Render a single node."
|
||||||
(with-slots ((components go::components)) node
|
(with-accessors ((components components)) node
|
||||||
(let ((mesh (car (member-if (lambda (c) (typep c 'mesh::mesh)) components))))
|
(let ((mesh (car (member-if (lambda (c) (typep c 'mesh::mesh)) components))))
|
||||||
(when mesh
|
(when mesh
|
||||||
(render-mesh node mesh)))))
|
(render-mesh node mesh)))))
|
||||||
|
|
||||||
(defun render-scene (node)
|
(defun render-scene (node)
|
||||||
"Walk the scene graph and render the graphical components."
|
"Walk the scene graph and render the graphical components."
|
||||||
(with-slots ((children go::children)) node
|
(with-accessors ((children children)) node
|
||||||
(loop for child in children
|
(loop for child in children
|
||||||
do (progn
|
do (progn
|
||||||
(go:update-trans-matrix child)
|
(update-trans-matrix child)
|
||||||
(render-node child)
|
(render-node child)
|
||||||
(render-scene child)))))
|
(render-scene child)))))
|
||||||
|
|
|
||||||
45
src/scene.lisp
Normal file
45
src/scene.lisp
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
#|
|
||||||
|
This file is a part of stoe project.
|
||||||
|
Copyright (c) 2014 Renaud Casenave-Péré (renaud@casenave-pere.fr)
|
||||||
|
|#
|
||||||
|
|
||||||
|
(in-package :cl-user)
|
||||||
|
(defpackage stoe.scene
|
||||||
|
(:use :cl)
|
||||||
|
(:nicknames :scene)
|
||||||
|
(:export :scene-node :parent :children
|
||||||
|
:attach :detach
|
||||||
|
:walk))
|
||||||
|
(in-package :stoe.scene)
|
||||||
|
|
||||||
|
(defclass scene-node ()
|
||||||
|
((parent :initform nil :reader parent)
|
||||||
|
(children :initform nil :reader children))
|
||||||
|
(:documentation "Base class for a node in the scene graph."))
|
||||||
|
|
||||||
|
(defgeneric attach (scene-node parent)
|
||||||
|
(:documentation "Attach a new node to the scene graph to be rendered."))
|
||||||
|
|
||||||
|
(defmethod attach ((scene-node scene-node) (parent scene-node))
|
||||||
|
(with-slots (children) parent
|
||||||
|
(with-slots ((new-parent parent)) scene-node
|
||||||
|
(push scene-node children)
|
||||||
|
(setf new-parent parent))))
|
||||||
|
|
||||||
|
(defgeneric detach (scene-node)
|
||||||
|
(:documentation "Detach a node from the scene graph to prevent it and its
|
||||||
|
children from being rendered."))
|
||||||
|
|
||||||
|
(defmethod detach ((scene-node scene-node))
|
||||||
|
(with-slots (parent) scene-node
|
||||||
|
(with-slots (children) parent
|
||||||
|
(setf children (remove scene-node children))
|
||||||
|
(setf parent nil))))
|
||||||
|
|
||||||
|
(defun walk (fun node)
|
||||||
|
"Walk through the scene graph and apply `fun' at each node."
|
||||||
|
(with-slots (children) node
|
||||||
|
(loop for child in children
|
||||||
|
do (progn
|
||||||
|
(apply fun child)
|
||||||
|
(walk fun child)))))
|
||||||
|
|
@ -6,8 +6,17 @@
|
||||||
(in-package :cl-user)
|
(in-package :cl-user)
|
||||||
(defpackage stoe
|
(defpackage stoe
|
||||||
(:use :cl
|
(:use :cl
|
||||||
:utils :input)
|
:utils)
|
||||||
(:export :main :quit))
|
(:import-from :scene
|
||||||
|
:attach)
|
||||||
|
(:import-from :object
|
||||||
|
:make-object :dir)
|
||||||
|
(:import-from :game
|
||||||
|
:get-current-camera
|
||||||
|
:get-world-origin)
|
||||||
|
(:import-from :input
|
||||||
|
:global-set-key
|
||||||
|
:global-set-motion))
|
||||||
(in-package :stoe)
|
(in-package :stoe)
|
||||||
|
|
||||||
(let ((exit-main-loop nil))
|
(let ((exit-main-loop nil))
|
||||||
|
|
@ -35,25 +44,25 @@ continue unless `unprotected' is t."
|
||||||
(start-coords '(0.0 . 0.0)))
|
(start-coords '(0.0 . 0.0)))
|
||||||
(defun set-freelook (enable)
|
(defun set-freelook (enable)
|
||||||
(setf freelook-mode enable)
|
(setf freelook-mode enable)
|
||||||
(setf start-orient (go:direction (game:get-current-camera))))
|
(setf start-orient (dir (get-current-camera))))
|
||||||
|
|
||||||
(defun freelook-move (x y)
|
(defun freelook-move (x y)
|
||||||
(if freelook-mode
|
(if freelook-mode
|
||||||
(let ((dx (- (car start-coords) x))
|
(let ((dx (- (car start-coords) x))
|
||||||
(dy (- (cdr start-coords) y)))
|
(dy (- (cdr start-coords) y)))
|
||||||
(setf (go:direction (game:get-current-camera)) (q:* (q:from-axis-and-angle (v:vec 0 1 0) (maths:deg-to-rad dx))
|
(setf (dir (get-current-camera)) (q:* (q:from-axis-and-angle (v:vec 0 1 0) (maths:deg-to-rad (- dx)))
|
||||||
start-orient
|
start-orient
|
||||||
(q:from-axis-and-angle (v:vec 1 0 0) (maths:deg-to-rad dy)))))
|
(q:from-axis-and-angle (v:vec 1 0 0) (maths:deg-to-rad dy)))))
|
||||||
(setf start-coords (cons x y)))))
|
(setf start-coords (cons x y))))
|
||||||
|
|
||||||
(global-set-key 3 #'set-freelook t)
|
(global-set-key 3 #'set-freelook t)
|
||||||
(global-set-key (3 :release) #'set-freelook nil)
|
(global-set-key (3 :release) #'set-freelook nil)
|
||||||
(global-set-motion #'freelook-move :x :y)
|
(global-set-motion #'freelook-move :x :y))
|
||||||
|
|
||||||
(defun game-start ()
|
(defun game-start ()
|
||||||
(let ((f (file:load-file #P"../data/cube.lisp" :sync t :type 'character)))
|
(let ((f (file:load-file #P"../data/cube.lisp" :sync t :type 'character)))
|
||||||
(go:attach (go:make-object :mesh (with-input-from-string (s f)
|
(attach (make-object :mesh (with-input-from-string (s f)
|
||||||
(mesh:make-mesh (read s)))) (game:get-world-origin))))
|
(mesh:make-mesh (read s)))) (get-world-origin))))
|
||||||
|
|
||||||
(defun initialize (&optional argv)
|
(defun initialize (&optional argv)
|
||||||
"Initialize all the modules passing the optional argv"
|
"Initialize all the modules passing the optional argv"
|
||||||
|
|
|
||||||
10
stoe.asd
10
stoe.asd
|
|
@ -49,11 +49,11 @@
|
||||||
:depends-on ("thread" "containers" "utils"))
|
:depends-on ("thread" "containers" "utils"))
|
||||||
(:file "file"
|
(:file "file"
|
||||||
:depends-on ("jobs"))
|
:depends-on ("jobs"))
|
||||||
(:module "game"
|
(:file "scene")
|
||||||
:components
|
(:file "object")
|
||||||
((:file "game-object")
|
(:file "camera")
|
||||||
(:file "input")
|
(:file "input")
|
||||||
(:file "game")))
|
(:file "game")
|
||||||
(:module "render"
|
(:module "render"
|
||||||
:components
|
:components
|
||||||
((:file "gl-utils")
|
((:file "gl-utils")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue