-
Notifications
You must be signed in to change notification settings - Fork 1
/
body.lisp
69 lines (56 loc) · 2.53 KB
/
body.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
(in-package #:cl-dynamics-engine)
(defclass body ()
((id :initarg :id
:reader id)))
(defclass dynamic-body (body)
((geometries :accessor geometries
:initform nil)
(body-position :initform nil
:accessor body-position)
(quaternion :initform nil
:accessor quaternion)))
(defmethod print-object ((body dynamic-body) stream)
(format stream "Position: ~A~%" (body-position body)))
(defmethod body-position ((body dynamic-body))
(let ((pos (%ode:body-get-position (id body))))
(apply 'vec (loop :for x :below 3
:collect (cffi:mem-aref pos '%ode:dreal x)))))
(defmethod (setf body-position) (new-value (body dynamic-body))
(%ode:body-set-position (id body)
(vec-x new-value)
(vec-y new-value)
(vec-z new-value))
(setf (slot-value body 'body-position) new-value))
(defun add-geometry (body geometry)
(%ode:geom-set-body (id geometry) (id body))
(setf (geometries body) (append (list geometry) (geometries body))))
(defmethod add-force ((body body) direction)
(%ode:body-set-linear-vel (id body) (vec-x direction) (vec-y direction) (vec-z direction)))
(defmethod quaternion ((body dynamic-body))
(let ((quat (%ode:body-get-quaternion (id body))))
(make-array 4 :element-type 'single-float
:initial-contents (loop :for i :below 4
:collect (cffi:mem-aref quat '%ode:dreal i)))))
(defmethod (setf quaternion) (new-value (body dynamic-body))
(cffi:with-foreign-object (quat '%ode:dreal 4)
(loop
:for i :below 4
:for x :across new-value
:do (setf (cffi:mem-aref quat '%ode:dreal i) x)))
new-value)
(defmacro with-body-of-mass-as-output ((body-sym mass-sym) world &body body)
`(let ((,body-sym (make-instance 'dynamic-body :id (%ode:body-create (id ,world)))))
(cffi:with-foreign-object (,mass-sym '(:struct %ode:mass))
,@body
(%ode:body-set-mass (id ,body-sym) ,mass-sym))
,body-sym))
(defun make-sphere-body-of-mass (world density radius &optional (position (vec 0.0 0.0 0.0)))
(with-body-of-mass-as-output (body mass)
world
(%ode:mass-set-sphere mass density radius)
(setf (body-position body) position)))
(defun make-box-body-of-mass (world density dimensions &optional (position (vec 0.0 0.0 0.0)))
(with-body-of-mass-as-output (body mass)
world
(%ode:mass-set-box mass density (vec-x dimensions) (vec-y dimensions) (vec-z dimensions))
(setf (body-position body) position)))