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 }