Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00008
00010
00016
00017
00019
00020 #include "Stdafx.h"
00021
00022 using namespace Opcode;
00023
00024 #ifdef OPC_RAYHIT_CALLBACK
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 bool Opcode::SetupAllHits(RayCollider& collider, CollisionFaces& contacts)
00036 {
00037 struct Local
00038 {
00039 static void AllContacts(const CollisionFace& hit, void* user_data)
00040 {
00041 CollisionFaces* CF = (CollisionFaces*)user_data;
00042 CF->AddFace(hit);
00043 }
00044 };
00045
00046 collider.SetFirstContact(false);
00047 collider.SetHitCallback(Local::AllContacts);
00048 collider.SetUserData(&contacts);
00049 return true;
00050 }
00051
00052 bool Opcode::SetupClosestHit(RayCollider& collider, CollisionFace& closest_contact)
00053 {
00054 struct Local
00055 {
00056 static void ClosestContact(const CollisionFace& hit, void* user_data)
00057 {
00058 CollisionFace* CF = (CollisionFace*)user_data;
00059 if(hit.mDistance<CF->mDistance) *CF = hit;
00060 }
00061 };
00062
00063 collider.SetFirstContact(false);
00064 collider.SetHitCallback(Local::ClosestContact);
00065 collider.SetUserData(&closest_contact);
00066 closest_contact.mDistance = MAX_FLOAT;
00067 return true;
00068 }
00069
00070 bool Opcode::SetupShadowFeeler(RayCollider& collider)
00071 {
00072 collider.SetFirstContact(true);
00073 collider.SetHitCallback(null);
00074 return true;
00075 }
00076
00077 bool Opcode::SetupInOutTest(RayCollider& collider)
00078 {
00079 collider.SetFirstContact(false);
00080 collider.SetHitCallback(null);
00081
00082 return true;
00083 }
00084
00085 bool Opcode::Picking(
00086 CollisionFace& picked_face,
00087 const Ray& world_ray, const Model& model, const Matrix4x4* world,
00088 float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data)
00089 {
00090 struct Local
00091 {
00092 struct CullData
00093 {
00094 CollisionFace* Closest;
00095 float MinLimit;
00096 CullModeCallback Callback;
00097 void* UserData;
00098 Point ViewPoint;
00099 const MeshInterface* IMesh;
00100 };
00101
00102
00103 static void RenderCullingCallback(const CollisionFace& hit, void* user_data)
00104 {
00105 CullData* Data = (CullData*)user_data;
00106
00107
00108 if(hit.mDistance>=Data->Closest->mDistance) return;
00109
00110
00111
00112
00113 if(hit.mDistance<=Data->MinLimit) return;
00114
00115
00116 udword StabbedFaceIndex = hit.mFaceID;
00117
00118
00119 bool KeepIt = true;
00120
00121
00122 CullMode CM = (Data->Callback)(StabbedFaceIndex, Data->UserData);
00123
00124 if(CM!=CULLMODE_NONE)
00125 {
00126
00127
00128 VertexPointers VP;
00129 Data->IMesh->GetTriangle(VP, StabbedFaceIndex);
00130 if(VP.BackfaceCulling(Data->ViewPoint))
00131 {
00132 if(CM==CULLMODE_CW) KeepIt = false;
00133 }
00134 else
00135 {
00136 if(CM==CULLMODE_CCW) KeepIt = false;
00137 }
00138 }
00139
00140 if(KeepIt) *Data->Closest = hit;
00141 }
00142 };
00143
00144 RayCollider RC;
00145 RC.SetMaxDist(max_dist);
00146 RC.SetTemporalCoherence(false);
00147 RC.SetCulling(false);
00148 RC.SetFirstContact(false);
00149 RC.SetHitCallback(Local::RenderCullingCallback);
00150
00151 picked_face.mFaceID = INVALID_ID;
00152 picked_face.mDistance = MAX_FLOAT;
00153 picked_face.mU = 0.0f;
00154 picked_face.mV = 0.0f;
00155
00156 Local::CullData Data;
00157 Data.Closest = &picked_face;
00158 Data.MinLimit = min_dist;
00159 Data.Callback = callback;
00160 Data.UserData = user_data;
00161 Data.ViewPoint = view_point;
00162 Data.IMesh = model.GetMeshInterface();
00163
00164 if(world)
00165 {
00166
00167 Matrix4x4 InvWorld;
00168 InvertPRMatrix(InvWorld, *world);
00169
00170
00171 Data.ViewPoint *= InvWorld;
00172 }
00173
00174 RC.SetUserData(&Data);
00175 if(RC.Collide(world_ray, model, world))
00176 {
00177 return picked_face.mFaceID!=INVALID_ID;
00178 }
00179 return false;
00180 }
00181
00182 #endif