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 }