OPC_Picking.cpp
Go to the documentation of this file.
1 /*
3  * OPCODE - Optimized Collision Detection
4  * Copyright (C) 2001 Pierre Terdiman
5  * Homepage: http://www.codercorner.com/Opcode.htm
6  */
8 
10 
16 
19 // Precompiled Header
20 #include "Stdafx.h"
21 
22 using namespace Opcode;
23 
24 #ifdef OPC_RAYHIT_CALLBACK
25 
26 /*
27  Possible RayCollider usages:
28  - boolean query (shadow feeler)
29  - closest hit
30  - all hits
31  - number of intersection (boolean)
32 
33 */
34 
36 {
37  struct Local
38  {
39  static void AllContacts(const CollisionFace& hit, void* user_data)
40  {
41  CollisionFaces* CF = (CollisionFaces*)user_data;
42  CF->AddFace(hit);
43  }
44  };
45 
46  collider.SetFirstContact(false);
47  collider.SetHitCallback(Local::AllContacts);
48  collider.SetUserData(&contacts);
49  return true;
50 }
51 
52 bool Opcode::SetupClosestHit(RayCollider& collider, CollisionFace& closest_contact)
53 {
54  struct Local
55  {
56  static void ClosestContact(const CollisionFace& hit, void* user_data)
57  {
58  CollisionFace* CF = (CollisionFace*)user_data;
59  if(hit.mDistance<CF->mDistance) *CF = hit;
60  }
61  };
62 
63  collider.SetFirstContact(false);
64  collider.SetHitCallback(Local::ClosestContact);
65  collider.SetUserData(&closest_contact);
66  closest_contact.mDistance = MAX_FLOAT;
67  return true;
68 }
69 
71 {
72  collider.SetFirstContact(true);
73  collider.SetHitCallback(null);
74  return true;
75 }
76 
78 {
79  collider.SetFirstContact(false);
80  collider.SetHitCallback(null);
81  // Results with collider.GetNbIntersections()
82  return true;
83 }
84 
86 CollisionFace& picked_face,
87 const Ray& world_ray, const Model& model, const Matrix4x4* world,
88 float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data)
89 {
90  struct Local
91  {
92  struct CullData
93  {
94  CollisionFace* Closest;
95  float MinLimit;
96  CullModeCallback Callback;
97  void* UserData;
98  Point ViewPoint;
99  const MeshInterface* IMesh;
100  };
101 
102  // Called for each stabbed face
103  static void RenderCullingCallback(const CollisionFace& hit, void* user_data)
104  {
105  CullData* Data = (CullData*)user_data;
106 
107  // Discard face if we already have a closer hit
108  if(hit.mDistance>=Data->Closest->mDistance) return;
109 
110  // Discard face if hit point is smaller than min limit. This mainly happens when the face is in front
111  // of the near clip plane (or straddles it). If we keep the face nonetheless, the user can select an
112  // object that he may not even be able to see, which is very annoying.
113  if(hit.mDistance<=Data->MinLimit) return;
114 
115  // This is the index of currently stabbed triangle.
116  udword StabbedFaceIndex = hit.mFaceID;
117 
118  // We may keep it or not, depending on backface culling
119  bool KeepIt = true;
120 
121  // Catch *render* cull mode for this face
122  CullMode CM = (Data->Callback)(StabbedFaceIndex, Data->UserData);
123 
124  if(CM!=CULLMODE_NONE) // Don't even compute culling for double-sided triangles
125  {
126  // Compute backface culling for current face
127 
128  VertexPointers VP;
129  Data->IMesh->GetTriangle(VP, StabbedFaceIndex);
130  if(VP.BackfaceCulling(Data->ViewPoint))
131  {
132  if(CM==CULLMODE_CW) KeepIt = false;
133  }
134  else
135  {
136  if(CM==CULLMODE_CCW) KeepIt = false;
137  }
138  }
139 
140  if(KeepIt) *Data->Closest = hit;
141  }
142  };
143 
144  RayCollider RC;
145  RC.SetMaxDist(max_dist);
146  RC.SetTemporalCoherence(false);
147  RC.SetCulling(false); // We need all faces since some of them can be double-sided
148  RC.SetFirstContact(false);
149  RC.SetHitCallback(Local::RenderCullingCallback);
150 
151  picked_face.mFaceID = INVALID_ID;
152  picked_face.mDistance = MAX_FLOAT;
153  picked_face.mU = 0.0f;
154  picked_face.mV = 0.0f;
155 
156  Local::CullData Data;
157  Data.Closest = &picked_face;
158  Data.MinLimit = min_dist;
159  Data.Callback = callback;
160  Data.UserData = user_data;
161  Data.ViewPoint = view_point;
162  Data.IMesh = model.GetMeshInterface();
163 
164  if(world)
165  {
166  // Get matrices
167  Matrix4x4 InvWorld;
168  InvertPRMatrix(InvWorld, *world);
169 
170  // Compute camera position in mesh space
171  Data.ViewPoint *= InvWorld;
172  }
173 
174  RC.SetUserData(&Data);
175  if(RC.Collide(world_ray, model, world))
176  {
177  return picked_face.mFaceID!=INVALID_ID;
178  }
179  return false;
180 }
181 
182 #endif
OPCODE_API bool SetupAllHits(RayCollider &collider, CollisionFaces &contacts)
Definition: OPC_Picking.cpp:35
#define null
our own NULL pointer
Definition: IceTypes.h:57
bool Collide(const Ray &world_ray, const Model &model, const Matrix4x4 *world=null, udword *cache=null)
inline_ void SetHitCallback(HitCallback cb)
Definition: Opcode.h:125
inline_ void SetMaxDist(float max_dist=MAX_FLOAT)
Definition: Opcode.h:122
CullMode(* CullModeCallback)(udword triangle_index, void *user_data)
Definition: Opcode.h:33
inline_ void SetTemporalCoherence(bool flag)
Definition: Opcode.h:119
OPCODE_API bool SetupShadowFeeler(RayCollider &collider)
Definition: OPC_Picking.cpp:70
OPCODE_API bool SetupClosestHit(RayCollider &collider, CollisionFace &closest_contact)
Definition: OPC_Picking.cpp:52
inline_ void SetFirstContact(bool flag)
Definition: Opcode.h:105
unsigned int udword
sizeof(udword) must be 4
Definition: IceTypes.h:65
OPCODE_API bool SetupInOutTest(RayCollider &collider)
Definition: OPC_Picking.cpp:77
inline_ void AddFace(const CollisionFace &face)
Definition: Opcode.h:50
#define MAX_FLOAT
max possible float value
Definition: IceTypes.h:130
CullMode
Definition: Opcode.h:26
inline_ void SetUserData(void *user_data)
Definition: Opcode.h:126
float mV
Impact barycentric coordinates.
Definition: Opcode.h:34
float mDistance
Distance from collider to hitpoint.
Definition: Opcode.h:33
bool BackfaceCulling(const Point &source)
Definition: Opcode.h:28
ICEMATHS_API void InvertPRMatrix(Matrix4x4 &dest, const Matrix4x4 &src)
OPCODE_API bool Picking(CollisionFace &picked_face, const Ray &world_ray, const Model &model, const Matrix4x4 *world, float min_dist, float max_dist, const Point &view_point, CullModeCallback callback, void *user_data)
Definition: OPC_Picking.cpp:85
udword mFaceID
Index of touched face.
Definition: Opcode.h:32
#define INVALID_ID
Invalid dword ID (counterpart of null pointers)
Definition: IceTypes.h:92
inline_ void SetCulling(bool flag)
Definition: Opcode.h:111
inline_ const MeshInterface * GetMeshInterface() const
Definition: Opcode.h:156


openhrp3
Author(s): AIST, General Robotix Inc., Nakamura Lab of Dept. of Mechano Informatics at University of Tokyo
autogenerated on Thu Sep 8 2022 02:24:04