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:
Renaud Casenave-Péré 2014-11-14 21:46:30 +09:00
parent 9faa777972
commit d8df41dbe4
9 changed files with 169 additions and 132 deletions

40
src/camera.lisp Normal file
View 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))))))

View file

@ -10,7 +10,9 @@
(:export :get-world-origin
:get-current-camera)
(:import-from :modules
:defmodule))
:defmodule)
(:import-from :camera
:make-camera :update-view))
(in-package :stoe.game)
(defconstant +loop-step-time+ 16000.0
@ -31,9 +33,9 @@ we need to keep the remaining time.")
(declare (ignore argv))
(format t "Initialize Game module~%")
(input:initialize)
(setf *world-origin* (go:make-object))
(setf *current-camera* (go:make-camera 90 (/ 16 9) 1.0 1000.0))
(go:attach *current-camera* *world-origin*))
(setf *world-origin* (object:make-object))
(setf *current-camera* (make-camera 90 (/ 16 9) 1.0 1000.0))
(scene:attach *current-camera* *world-origin*))
(defun finalize ()
"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+)
do (progn
(when *current-camera*
(go:update-view *current-camera*))
(update-view *current-camera*))
(input:update +loop-step-time+)
(decf delta-time +loop-step-time+)))
(setf *last-frame-remaining-time* delta-time))

View file

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

View file

@ -4,7 +4,7 @@
|#
(in-package :cl-user)
(defpackage stoe.game.input
(defpackage stoe.input
(:nicknames :input)
(:use :cl :alexandria
:utils :containers)
@ -13,7 +13,7 @@
:make-keymap :set-global-keymap
:define-key :global-set-key
:define-motion :global-set-motion))
(in-package :stoe.game.input)
(in-package :stoe.input)
(define-constant +keyevent-classes+ '(:press :release :repeat :continuous)
:test #'equal :documentation "List of the available key event classes.")

33
src/object.lisp Normal file
View 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)))))

View file

@ -10,7 +10,15 @@
:utils)
(:export :poll-events)
(: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)
(defvar *window* nil)
@ -84,7 +92,7 @@ This needs to be called once per frame, at the beginning of the loop."
(defvar *height* 0)
(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 *height* 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)
do (shader::using-program (program (mesh::mesh-stream-program stream))
(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))
(go::trans-matrix node))))
(gl:uniform-matrix camera-to-clip 4 (vector (go::projection (game:get-current-camera)))))
(gl:uniform-matrix model-to-camera 4 (vector (m:* (view (get-current-camera))
(trans-mat node))))
(gl:uniform-matrix camera-to-clip 4 (vector (proj (get-current-camera)))))
(let* ((vertex-buffer (mesh::mesh-stream-vertex-buffer stream))
(index-buffer (mesh::mesh-stream-index-buffer stream))
(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)
"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))))
(when mesh
(render-mesh node mesh)))))
(defun render-scene (node)
"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
do (progn
(go:update-trans-matrix child)
(update-trans-matrix child)
(render-node child)
(render-scene child)))))

45
src/scene.lisp Normal file
View 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)))))

View file

@ -6,8 +6,17 @@
(in-package :cl-user)
(defpackage stoe
(:use :cl
:utils :input)
(:export :main :quit))
:utils)
(: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)
(let ((exit-main-loop nil))
@ -35,25 +44,25 @@ continue unless `unprotected' is t."
(start-coords '(0.0 . 0.0)))
(defun set-freelook (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)
(if freelook-mode
(let ((dx (- (car start-coords) x))
(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
(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 :release) #'set-freelook nil)
(global-set-motion #'freelook-move :x :y)
(global-set-motion #'freelook-move :x :y))
(defun game-start ()
(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)
(mesh:make-mesh (read s)))) (game:get-world-origin))))
(attach (make-object :mesh (with-input-from-string (s f)
(mesh:make-mesh (read s)))) (get-world-origin))))
(defun initialize (&optional argv)
"Initialize all the modules passing the optional argv"

View file

@ -49,11 +49,11 @@
:depends-on ("thread" "containers" "utils"))
(:file "file"
:depends-on ("jobs"))
(:module "game"
:components
((:file "game-object")
(:file "scene")
(:file "object")
(:file "camera")
(:file "input")
(:file "game")))
(:file "game")
(:module "render"
:components
((:file "gl-utils")