NLS Engine  v0.1
The Next Logical Step in game engine design.
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Defines
PhysicsModuleMessages.cpp
Go to the documentation of this file.
00001 
00011 #pragma once
00012 
00013 #include "PhysicsModule.h"
00014 
00015 // System Library Includes
00016 
00017 // Application Library Includes
00018 
00019 // Local Includes
00020 #include "../sharedbase/MessageRouter.h"
00021 #include "../sharedbase/Envelope.h"
00022 #include "../sharedbase/Entity.h"
00023 #include "../sharedbase/EntityList.h"
00024 
00025 #include "Messages.h"
00026 #include "Types.h"
00027 
00028 #include "component/InterfaceCollider.h"
00029 
00030 // Classes
00031 namespace Physics {
00032   #define SUBSCRIBE_BASIC(msgid, handler)   {std::shared_ptr<Subscriber> handler_sptr(new Subscriber(boost::bind((&handler), this, _1))); this->msgrouter->Subscribe((msgid), handler_sptr);}
00033   #define UNSUBSCRIBE_BASIC(msgid, handler) {std::shared_ptr<Subscriber> handler_sptr(new Subscriber(boost::bind((&handler), this, _1))); this->msgrouter->Unsubscribe((msgid), handler_sptr);}
00034   #define SUBSCRIBE_DIRECTED(msgid, handler)   {std::shared_ptr<DirectedSubscriber> handler_sptr(new DirectedSubscriber(boost::bind((&handler), this, _1))); this->msgrouter->SubscribeDirected((msgid), handler_sptr);}
00035   #define UNSUBSCRIBE_DIRECTED(msgid, handler) {std::shared_ptr<DirectedSubscriber> handler_sptr(new DirectedSubscriber(boost::bind((&handler), this, _1))); this->msgrouter->UnsubscribeDirected((msgid), handler_sptr);}
00036   
00037   /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00038   void PhysicsModule::RegisterMessageHandlers() {
00039     /* * * * * * * * * * * * * * * * * * * * * */
00040     // General Message Handlers
00041     /* * * * * * * * * * * * * * * * * * * * * */
00042     SUBSCRIBE_BASIC(MSG_MODULE_START, PhysicsModule::HandlerStartup);
00043     
00044     /* * * * * * * * * * * * * * * * * * * * * */
00045     // Directed Message Handlers
00046     /* * * * * * * * * * * * * * * * * * * * * */
00047     SUBSCRIBE_DIRECTED(MSG_RAY_CAST, PhysicsModule::HandleRayCast);
00048   }
00049   
00050   /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00051   void PhysicsModule::HandlerStartup(EnvelopeSPTR envelope) {
00052     bool status = false;
00053     
00054     
00055     // *TODO: actually do a reasonable startup and determeine if this really should be true.
00056     status = true;
00057     
00058     
00059     // Un-register from the startup message, as there's no need to start again.
00060     UNSUBSCRIBE_BASIC(MSG_MODULE_START, PhysicsModule::HandlerStartup);
00061     
00062     // Send notification that the module is started.
00063     {
00064       EnvelopeSPTR e(new Envelope);
00065       e->msgid = ACK_MODULE_START;
00066       e->AddData(status);
00067       this->msgrouter->SendSP(e);
00068     }
00069     
00070     LOG(LOG_PRIORITY::FLOW, "SimplePhysics started.");
00071     
00072     return;
00073   }
00074   
00075   /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00076   EnvelopeSPTR PhysicsModule::HandleRayCast(EnvelopeSPTR envelope) const {
00077     unsigned int type = envelope->GetDataUInt(0);
00078     Vector3D source = envelope->GetDataVector(1);
00079     Vector3D direction = envelope->GetDataVector(2);
00080     
00081     EnvelopeSPTR response(new Envelope());
00082     response->msgid = 0; // Directed response doesn't need an ID.
00083     
00084     EntitySPTR closest_hit_entity(nullptr);
00085     float closest_hit_dist;
00086     
00087     {
00088       Threading::ReadLock r_lock(this->collidableObjectsMutex);
00089       
00090       for (CollidableListType::iterator collider_iterator = this->collidableObjects.begin(); collider_iterator != this->collidableObjects.end(); ++collider_iterator) {
00091         InterfaceCollider* collider = *collider_iterator;
00092         
00093         if (collider->CollideRay(source, direction)) {
00094           EntitySPTR hit_entity(collider->GetOwnerEntity());
00095           
00096           switch (type) {
00097             case RAY_CAST_NEAREST: {
00098               float hit_dist = D3DXVec3LengthSq(&(hit_entity->GetWorldPosition() - source));
00099               
00100               if (closest_hit_entity.get() == nullptr || hit_dist < closest_hit_dist) {
00101                 // *BUG: since this is based on the center coordinates of the objects, not the ray-object intersection point, there are cases where the object returned will not actually be the closest, just very near the closest.
00102                 
00103                 closest_hit_entity = hit_entity;
00104                 closest_hit_dist = hit_dist;
00105               }
00106             }
00107             break;
00108             default: { // assumed RAY_CAST_ALL
00109               std::string hit_entity_name = this->elist->FindName(hit_entity);
00110               
00111               response->AddData(hit_entity_name);
00112             }
00113           }
00114         }
00115       }
00116     }
00117     
00118     if (type == RAY_CAST_NEAREST && closest_hit_entity.get() != nullptr) {
00119       std::string hit_entity_name = this->elist->FindName(closest_hit_entity);
00120       
00121       response->AddData(hit_entity_name);
00122     }
00123     
00124     return response;
00125   }
00126 }