1 module unecht.core.components.physics.collider;
2 
3 import derelict.ode.ode;
4 import derelict.util.system;
5 
6 import unecht.core.component;
7 import unecht.core.components.physics.system;
8 import unecht.core.components.physics.dynamic;
9 import unecht.core.defaultInspector;
10 
11 import gl3n.linalg;
12 
13 abstract class UEPhysicsGeometry : UEComponent
14 {
15     mixin(UERegisterObject!());
16 
17     protected dGeomID _geom;
18 
19     ///
20     override void onDestroy() {
21         super.onDestroy;
22 
23         if(_geom)
24             dGeomDestroy(_geom);
25 
26         _geom = null;
27     }
28 }
29 
30 ///
31 @UEDefaultInspector!UEPhysicsColliderPlane
32 final class UEPhysicsColliderPlane : UEPhysicsGeometry
33 {
34     mixin(UERegisterObject!());
35     
36     override void onCreate() {
37         super.onCreate;
38         
39         // Create a ground plane in our collision space by passing Space as the first argument to dCreatePlane.
40         // The next four parameters are the planes normal (a, b, c) and distance (d) according to the plane
41         // equation a*x+b*y+c*z=d and must have length 1
42         _geom = dCreatePlane(UEPhysicsSystem.space, 0, 1, 0, 0);
43     }
44 }
45 
46 ///
47 @UEDefaultInspector!UEPhysicsColliderBox
48 final class UEPhysicsColliderBox : UEPhysicsGeometry
49 {
50     mixin(UERegisterObject!());
51     
52     vec3 size = vec3(2);
53 
54     ///
55     override void onCreate() {
56         super.onCreate;
57         
58         _rigidBody = entity.getComponent!UEPhysicsBody;
59         //TODO: logging
60         
61         // Here we create the actual geom object using dCreateBox. Note that this also adds the geom to our 
62         // collision space and sets the size of the geom to that of our box mass.
63         _geom = dCreateBox(UEPhysicsSystem.space, size.x*sceneNode.scaling.x, size.y*sceneNode.scaling.y, size.z*sceneNode.scaling.z);
64         
65         dGeomSetData(_geom, cast(void*)this);
66         
67         if(_rigidBody)
68         {
69             // And lastly we want to associate the body with the geom using dGeomSetBody. Setting a body on a geom automatically
70             // combines the position vector and rotation matrix of the body and geom so that setting the position or orientation
71             // of one will set the value for both objects. The ODE docs have a lot more to say about the geom functions.
72             dGeomSetBody(_geom, _rigidBody.Body);
73         }
74         else
75         {
76             auto pos = _lastPos = this.sceneNode.position;
77             dGeomSetPosition(_geom, pos.x, pos.y, pos.z);
78         }
79     }
80 
81     ///
82     override void onUpdate() {
83         if(!_rigidBody)
84         {
85             auto posNow = sceneNode.position;
86             auto rotNow = sceneNode.rotation;
87             if(_lastPos != posNow)
88                 dGeomSetPosition(_geom, posNow.x, posNow.y, posNow.z);
89             if(_lastRot != rotNow)
90                 dGeomSetQuaternion(_geom, rotNow.quaternion);
91             
92             auto pos = dGeomGetPosition(_geom);
93             float[4] qrot;
94             dGeomGetQuaternion(_geom,qrot);
95             
96             quat rot = quat(qrot[0],qrot[1],qrot[2],qrot[3]);
97             
98             this.sceneNode.position = _lastPos = vec3(pos[0..3]);
99             this.sceneNode.rotation = _lastRot = rot;
100         }
101     }
102     
103 private:
104     UEPhysicsBody _rigidBody;
105     vec3 _lastPos;
106     quat _lastRot;
107 }
108 
109 ///
110 @UEDefaultInspector!UEPhysicsColliderSphere
111 final class UEPhysicsColliderSphere : UEPhysicsGeometry
112 {
113     mixin(UERegisterObject!());
114     
115     float rad=1.0f;
116     
117     override void onCreate() {
118         super.onCreate;
119         
120         auto rigidBody = entity.getComponent!UEPhysicsBody;
121         
122         _geom = dCreateSphere(UEPhysicsSystem.space, rad);
123         
124         dGeomSetData(_geom, cast(void*)this);
125         
126         if(rigidBody)
127             dGeomSetBody(_geom, rigidBody.Body);
128     }
129 }