Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh_capsule_collision.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: 9.1 KB
Line 
1
2/*
3-----------------------------------------------------------------------------
4This source file is part of GIMPACT Library.
5
6For the latest info, see http://gimpact.sourceforge.net/
7
8Copyright (c) 2006 Francisco Leon. C.C. 80087371.
9email: projectileman@yahoo.com
10
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of EITHER:
13   (1) The GNU Lesser General Public License as published by the Free
14       Software Foundation; either version 2.1 of the License, or (at
15       your option) any later version. The text of the GNU Lesser
16       General Public License is included with this library in the
17       file GIMPACT-LICENSE-LGPL.TXT.
18   (2) The BSD-style license that is included with this library in
19       the file GIMPACT-LICENSE-BSD.TXT.
20
21 This library is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
24 GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
25
26-----------------------------------------------------------------------------
27*/
28
29#include "GIMPACT/gim_trimesh.h"
30
31//! Utility function for find the closest point between a segment and a triangle
32/*!
33
34\param triangle
35\param s1
36\param s2
37\param contacts Contains the closest points on the segment (1,2), and the normal points to segment, and m_depth contains the distance
38
39\post The contacts array is not set to 0. It adds aditional contacts
40*/
41void gim_closest_point_triangle_segment(GIM_TRIANGLE_DATA * triangle, vec3f s1,vec3f s2, GDYNAMIC_ARRAY * contacts)
42{
43    vec3f segment_points[4];
44    vec3f closest_points[2];
45    GUINT intersection_type, out_edge= 10;
46    GREAL dis, dis_temp,perpend;
47    vec4f sdiff;
48
49    dis = DISTANCE_PLANE_POINT(triangle->m_planes.m_planes[0],s1);
50    dis_temp = DISTANCE_PLANE_POINT(triangle->m_planes.m_planes[0],s2);
51
52    if(dis<=0.0f && dis_temp<=0.0f) return;
53
54    VEC_DIFF(sdiff,s2,s1);
55    perpend = VEC_DOT(sdiff,triangle->m_planes.m_planes[0]);
56
57    if(!IS_ZERO(perpend)) // Not perpendicular
58    {
59        if(dis<dis_temp)
60        {
61            VEC_COPY(closest_points[0],s1);
62        }
63        else
64        {
65            dis = dis_temp;
66            VEC_COPY(closest_points[0],s2);
67        }
68
69        //Testing segment vertices over triangle
70        if(dis>=0.0f && dis_temp>=0.0f)
71        {
72            POINT_IN_HULL(closest_points[0],(&triangle->m_planes.m_planes[1]),3,out_edge);
73
74            if(out_edge==0)//Point over face
75            {
76                GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
77                return;
78            }
79        }
80        else
81        {
82
83            PLANE_CLIP_SEGMENT(s1,s2,triangle->m_planes.m_planes[0],closest_points[1]);
84
85            POINT_IN_HULL(closest_points[1],(&triangle->m_planes.m_planes[1]),3,out_edge);
86
87            if(out_edge==0)//Point over face
88            {
89                GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
90                return;
91            }
92        }
93
94    }
95    else // Perpendicular Face
96    {
97        //out_edge=10
98        //Clip segment by triangle
99    //    Edge1
100        PLANE_CLIP_SEGMENT_CLOSEST(s1,s2,triangle->m_planes.m_planes[1],segment_points[0],segment_points[1],intersection_type);
101        if(intersection_type==0||intersection_type==1)
102        {
103            out_edge = 0;
104            VEC_COPY(closest_points[0],segment_points[0]);
105        }
106        else
107        {
108            //Edge2
109            PLANE_CLIP_SEGMENT_CLOSEST(segment_points[0],segment_points[1],triangle->m_planes.m_planes[2],segment_points[2],segment_points[3],intersection_type);
110            if(intersection_type==0||intersection_type==1)
111            {
112                out_edge = 1;
113                VEC_COPY(closest_points[0],segment_points[3]);
114            }
115            else
116            {
117                //Edge3
118                PLANE_CLIP_SEGMENT_CLOSEST(segment_points[2],segment_points[3],triangle->m_planes.m_planes[3],closest_points[0],closest_points[1],intersection_type);
119                if(intersection_type==0||intersection_type==1)
120                {
121                    out_edge = 2;
122                }
123            }
124        }
125        //POST closest_points[0] and closest_points[1] are inside the triangle, if out_edge>2
126        if(out_edge>2) // Over triangle
127        {
128            dis = VEC_DOT(closest_points[0],triangle->m_planes.m_planes[0]);
129            GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
130            GIM_PUSH_CONTACT((*contacts),closest_points[1] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
131            return;
132        }
133    }
134
135    //Find closest edges
136    out_edge = 10;
137    dis = G_REAL_INFINITY;
138    GUINT i;
139    for(i=0;i<3;i++)
140    {
141        SEGMENT_COLLISION(s1,s2,triangle->m_vertices[i],triangle->m_vertices[(i+1)%3],segment_points[0],segment_points[1]);
142        VEC_DIFF(sdiff,segment_points[0],segment_points[1]);
143        dis_temp = VEC_DOT(sdiff,sdiff);
144        if(dis_temp< dis)
145        {
146            dis = dis_temp;
147            out_edge = i;
148            VEC_COPY(closest_points[0],segment_points[0]);
149            VEC_COPY(closest_points[1],sdiff);//normal
150        }
151    }
152    if(out_edge>2) return ;// ???? ASSERT this please
153
154    if(IS_ZERO(dis))
155    {
156        //Set face plane
157        GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,0.0f,0, 0, 0,0);
158
159    }
160    else
161    {
162        GIM_SQRT(dis,dis);
163        VEC_SCALE(closest_points[1],(1.0f/dis),closest_points[1]);//normal
164        GIM_PUSH_CONTACT((*contacts),closest_points[0] ,closest_points[1],dis,0, 0, 0,0);
165    }
166}
167
168
169//! Utility function for find the closest point between a capsule and a triangle
170/*!
171
172\param triangle
173\param capsule
174\param contacts Contains the closest points on the capsule, and the normal points to triangle
175
176\post The contacts array is not set to 0. It adds aditional contacts
177*/
178int gim_triangle_capsule_collision(GIM_TRIANGLE_DATA * triangle, GIM_CAPSULE_DATA * capsule, GDYNAMIC_ARRAY * contacts)
179{
180    GUINT old_contact_size = contacts->m_size;
181    gim_closest_point_triangle_segment(triangle,capsule->m_point1,capsule->m_point2,contacts);
182    GIM_CONTACT * pcontact = GIM_DYNARRAY_POINTER(GIM_CONTACT ,(*contacts));
183    pcontact+= old_contact_size;
184
185    if(pcontact->m_depth > capsule->m_radius)
186    {
187        contacts->m_size = old_contact_size;
188        return 0;
189    }
190
191    vec3f vec;
192    while(old_contact_size<contacts->m_size)
193    {
194        //Scale the normal for pointing to triangle
195        VEC_SCALE(pcontact->m_normal,-1.0f,pcontact->m_normal);
196        //Fix the contact point
197        VEC_SCALE(vec,capsule->m_radius,pcontact->m_normal);
198        VEC_SUM(pcontact->m_point,vec,pcontact->m_point);
199        //Fix the depth
200        pcontact->m_depth = capsule->m_radius - pcontact->m_depth;
201
202        pcontact++;
203        old_contact_size++;
204    }
205
206    return 1;
207}
208
209
210//! Trimesh Capsule collision
211/*!
212Find the closest primitive collided by the ray
213\param trimesh
214\param capsule
215\param contact
216\param contacts A GIM_CONTACT array. Must be initialized
217*/
218void gim_trimesh_capsule_collision(GIM_TRIMESH * trimesh, GIM_CAPSULE_DATA * capsule, GDYNAMIC_ARRAY * contacts)
219{
220    contacts->m_size = 0;
221
222    aabb3f test_aabb;
223    CALC_CAPSULE_AABB((*capsule),test_aabb);
224
225        GDYNAMIC_ARRAY collision_result;
226        GIM_CREATE_BOXQUERY_LIST(collision_result);
227
228        gim_aabbset_box_collision(&test_aabb, &trimesh->m_aabbset , &collision_result);
229
230        if(collision_result.m_size==0)
231        {
232            GIM_DYNARRAY_DESTROY(collision_result);
233        }
234
235        //collide triangles
236        //Locks trimesh
237        gim_trimesh_locks_work_data(trimesh);
238         //dummy contacts
239    GDYNAMIC_ARRAY dummycontacts;
240    GIM_CREATE_CONTACT_LIST(dummycontacts);
241
242        int cresult;
243        unsigned int i;
244        GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
245        GIM_TRIANGLE_DATA tri_data;
246        GUINT old_contact_size;
247        GIM_CONTACT * pcontact;
248
249        for(i=0;i<collision_result.m_size;i++)
250        {
251            old_contact_size = dummycontacts.m_size;
252                gim_trimesh_get_triangle_data(trimesh,boxesresult[i],&tri_data);
253                cresult = gim_triangle_capsule_collision(&tri_data, capsule, &dummycontacts);
254                if(cresult!=0)
255                {
256                    pcontact = GIM_DYNARRAY_POINTER(GIM_CONTACT ,dummycontacts);
257            pcontact+= old_contact_size;
258                    while(old_contact_size<dummycontacts.m_size)
259            {
260                pcontact->m_handle1 = trimesh;
261                pcontact->m_handle2 = capsule;
262                pcontact->m_feature1 = boxesresult[i];
263                pcontact->m_feature2 = 0;
264                pcontact++;
265                old_contact_size++;
266            }
267                }
268        }
269        ///unlocks
270        gim_trimesh_unlocks_work_data(trimesh);
271        ///Destroy box result
272        GIM_DYNARRAY_DESTROY(collision_result);
273
274         //merge contacts
275    gim_merge_contacts(&dummycontacts,contacts);
276
277    //Destroy dummy
278    GIM_DYNARRAY_DESTROY(dummycontacts);
279}
Note: See TracBrowser for help on using the repository browser.