Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ode/ode-0.9/OPCODE/OPC_Picking.cpp @ 216

Last change on this file since 216 was 216, checked in by mathiask, 16 years ago

[Physik] add ode-0.9

File size: 5.2 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 *      OPCODE - Optimized Collision Detection
4 *      Copyright (C) 2001 Pierre Terdiman
5 *      Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 *      Contains code to perform "picking".
12 *      \file           OPC_Picking.cpp
13 *      \author         Pierre Terdiman
14 *      \date           March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Precompiled Header
20#include "Stdafx.h"
21
22using 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
35bool Opcode::SetupAllHits(RayCollider& collider, CollisionFaces& contacts)
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
52bool 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
70bool Opcode::SetupShadowFeeler(RayCollider& collider)
71{
72        collider.SetFirstContact(true);
73        collider.SetHitCallback(null);
74        return true;
75}
76
77bool Opcode::SetupInOutTest(RayCollider& collider)
78{
79        collider.SetFirstContact(false);
80        collider.SetHitCallback(null);
81        // Results with collider.GetNbIntersections()
82        return true;
83}
84
85bool Opcode::Picking(
86CollisionFace& picked_face,
87const Ray& world_ray, const Model& model, const Matrix4x4* world,
88float 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
Note: See TracBrowser for help on using the repository browser.