Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh_trimesh_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: 10.0 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#define CLASSIFY_TRI_BY_FACE(v1,v2,v3,faceplane,out_of_face)\
32{   \
33    _distances[0] = DISTANCE_PLANE_POINT(faceplane,v1);\
34    _distances[1] =  _distances[0] * DISTANCE_PLANE_POINT(faceplane,v2);\
35    _distances[2] =  _distances[0] * DISTANCE_PLANE_POINT(faceplane,v3); \
36        if(_distances[1]>0.0f && _distances[2]>0.0f)\
37        {\
38            out_of_face = 1;\
39        }\
40        else\
41        {\
42            out_of_face = 0;\
43        }\
44}\
45
46
47//! Receives the 3 edge planes
48#define MOST_DEEP_POINTS(plane,points,point_count,deep_points,deep_points_count,maxdeep)\
49{\
50    maxdeep=-1000.0f;\
51    GUINT _k;\
52        GREAL _dist;\
53        deep_points_count = 0;\
54        for(_k=0;_k<point_count;_k++)\
55        {\
56            _dist = -DISTANCE_PLANE_POINT(plane,points[_k]);\
57                if(_dist>maxdeep)\
58                {\
59                        maxdeep = _dist;\
60                        _max_candidates[0] = _k;\
61                        deep_points_count=1;\
62                }\
63                else if((_dist+G_EPSILON)>=maxdeep)\
64                {\
65                    _max_candidates[deep_points_count] = _k;\
66                        deep_points_count++;\
67                }\
68        }\
69        if(maxdeep<0.0f)\
70    {\
71        deep_points_count = 0;\
72    }\
73    else\
74    {\
75        for(_k=0;_k<deep_points_count;_k++)\
76        {\
77            VEC_COPY(deep_points[_k],points[_max_candidates[_k]]);\
78        }\
79    }\
80}\
81
82//! Receives the 3 edge planes
83#define CLIP_TRI_POINTS_BY_TRI_EDGE_PLANES(tri_points,tri_edge_planes, clipped_points, clipped_point_count)\
84{\
85    clipped_point_count = 0;    \
86    _temp_clip_count = 0;\
87    PLANE_CLIP_POLYGON(tri_edge_planes[0],tri_points,3,_temp_clip,_temp_clip_count,MAX_TRI_CLIPPING);\
88    if(_temp_clip_count>0)\
89    {\
90        _temp_clip_count2 = 0;\
91        PLANE_CLIP_POLYGON(tri_edge_planes[1],_temp_clip,_temp_clip_count,_temp_clip2,_temp_clip_count2,MAX_TRI_CLIPPING);\
92        if(_temp_clip_count2>0)\
93        {\
94            PLANE_CLIP_POLYGON(tri_edge_planes[2],_temp_clip2,_temp_clip_count2,clipped_points,clipped_point_count,MAX_TRI_CLIPPING);\
95        }\
96    }\
97}\
98
99
100
101int _gim_triangle_triangle_collision(
102                                                        GIM_TRIANGLE_DATA *tri1,
103                                                        GIM_TRIANGLE_DATA *tri2,
104                                                        GIM_TRIANGLE_CONTACT_DATA * contact_data)
105{
106    //Cache variables for triangle intersection
107    GUINT _max_candidates[MAX_TRI_CLIPPING];
108    vec3f _temp_clip[MAX_TRI_CLIPPING];
109    GUINT _temp_clip_count = 0;
110    vec3f _temp_clip2[MAX_TRI_CLIPPING];
111    GUINT _temp_clip_count2 = 0;
112    vec3f clipped_points2[MAX_TRI_CLIPPING];
113    vec3f deep_points2[MAX_TRI_CLIPPING];
114    vec3f clipped_points1[MAX_TRI_CLIPPING];
115    vec3f deep_points1[MAX_TRI_CLIPPING];
116
117
118
119    //State variabnles
120        GUINT mostdir=0;
121        GUINT clipped2_count=0;
122
123        //Clip tri2 by tri1 edges
124
125        CLIP_TRI_POINTS_BY_TRI_EDGE_PLANES(tri2->m_vertices,(&tri1->m_planes.m_planes[1]), clipped_points2, clipped2_count);
126
127        if(clipped2_count == 0 )
128        {
129             return 0;//Reject
130        }
131
132        //find most deep interval face1
133        GUINT deep2_count=0;
134
135        GREAL maxdeep;
136
137        MOST_DEEP_POINTS((tri1->m_planes.m_planes[0]), clipped_points2, clipped2_count, deep_points2, deep2_count, maxdeep);
138        if(deep2_count==0)
139        {
140//          *perror = 0.0f;
141             return 0;//Reject
142        }
143
144        //Normal pointing to triangle1
145        VEC_SCALE(contact_data->m_separating_normal,-1.0f,(tri1->m_planes.m_planes[0]));
146
147
148        //Clip tri1 by tri2 edges
149
150        GUINT clipped1_count=0;
151
152        CLIP_TRI_POINTS_BY_TRI_EDGE_PLANES(tri1->m_vertices,(&tri2->m_planes.m_planes[1]), clipped_points1, clipped1_count);
153
154        if(clipped2_count == 0 )
155        {
156//          *perror = 0.0f;
157             return 0;//Reject
158        }
159
160
161        //find interval face2
162        GUINT deep1_count=0;
163
164        GREAL dist;
165
166        MOST_DEEP_POINTS((tri2->m_planes.m_planes[0]), clipped_points1, clipped1_count, deep_points1, deep1_count, dist);
167
168        if(deep1_count==0)
169        {
170//          *perror = 0.0f;
171            return 0;
172        }
173
174        if(dist<maxdeep)
175        {
176                maxdeep = dist;
177                mostdir = 1;
178                VEC_COPY(contact_data->m_separating_normal,(tri2->m_planes.m_planes[0]));
179        }
180        //set deep
181        contact_data->m_penetration_depth = maxdeep;
182
183        ////check most dir for contacts
184        if(mostdir==0)
185        {
186            contact_data->m_point_count = deep2_count;
187            for(mostdir=0;mostdir<deep2_count;mostdir++)
188            {
189                VEC_COPY(contact_data->m_points[mostdir] ,deep_points2[mostdir]);
190            }
191        }
192        else
193        {
194                contact_data->m_point_count = deep1_count;
195            for(mostdir=0;mostdir<deep1_count;mostdir++)
196            {
197                VEC_COPY(contact_data->m_points[mostdir] ,deep_points1[mostdir]);
198            }
199        }
200        return 1;
201}
202
203
204
205//! Finds the contact points from a collision of two triangles
206/*!
207Returns the contact points, the penetration depth and the separating normal of the collision
208between two triangles. The normal is pointing toward triangle 1 from triangle 2
209*/
210int gim_triangle_triangle_collision(
211                                                        GIM_TRIANGLE_DATA *tri1,
212                                                        GIM_TRIANGLE_DATA *tri2,
213                                                        GIM_TRIANGLE_CONTACT_DATA * contact_data)
214{
215    vec3f _distances;
216    char out_of_face=0;
217
218    CLASSIFY_TRI_BY_FACE(tri1->m_vertices[0],tri1->m_vertices[1],tri1->m_vertices[2],tri2->m_planes.m_planes[0],out_of_face);
219    if(out_of_face==1) return 0;
220
221    CLASSIFY_TRI_BY_FACE(tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2],tri1->m_planes.m_planes[0],out_of_face);
222    if(out_of_face==1) return 0;
223
224    return _gim_triangle_triangle_collision(tri1,tri2,contact_data);
225}
226
227//! Trimesh Trimesh Collisions
228/*!
229
230In each contact
231<ul>
232<li> m_handle1 points to trimesh1.
233<li> m_handle2 points to trimesh2.
234<li> m_feature1 Is a triangle index of trimesh1.
235<li> m_feature2 Is a triangle index of trimesh2.
236</ul>
237
238\param trimesh1 Collider
239\param trimesh2 Collidee
240\param contacts A GIM_CONTACT array. Must be initialized
241*/
242void gim_trimesh_trimesh_collision(GIM_TRIMESH * trimesh1, GIM_TRIMESH * trimesh2, GDYNAMIC_ARRAY * contacts)
243{
244    contacts->m_size = 0;
245    GDYNAMIC_ARRAY collision_pairs;
246    GIM_CREATE_PAIR_SET(collision_pairs)
247
248    gim_aabbset_bipartite_intersections(&trimesh1->m_aabbset,&trimesh2->m_aabbset,&collision_pairs);
249
250    if(collision_pairs.m_size==0)
251    {
252        GIM_DYNARRAY_DESTROY(collision_pairs);
253         return; //no collisioin
254    }
255
256    //Locks meshes
257    gim_trimesh_locks_work_data(trimesh1);
258    gim_trimesh_locks_work_data(trimesh2);
259
260
261    //pair pointer
262    GIM_PAIR *pairs = GIM_DYNARRAY_POINTER(GIM_PAIR,collision_pairs);
263    //dummy contacts
264    GDYNAMIC_ARRAY dummycontacts;
265    GIM_CREATE_CONTACT_LIST(dummycontacts);
266
267    //Auxiliary triangle data
268    GIM_TRIANGLE_CONTACT_DATA tri_contact_data;
269    GIM_TRIANGLE_DATA tri1data,tri2data;
270
271
272    GUINT i, ti1,ti2,ci;
273    int colresult;
274    for (i=0;i<collision_pairs.m_size; i++)
275    {
276        ti1 = pairs[i].m_index1;
277        ti2 = pairs[i].m_index2;
278        //Get triangles data
279        gim_trimesh_get_triangle_data(trimesh1,ti1,&tri1data);
280        gim_trimesh_get_triangle_data(trimesh2,ti2,&tri2data);
281
282        //collide triangles
283        colresult = gim_triangle_triangle_collision(&tri1data,&tri2data,&tri_contact_data);
284        if(colresult == 1)
285        {
286            //Add contacts
287            for (ci=0;ci<tri_contact_data.m_point_count ;ci++ )
288            {
289                GIM_PUSH_CONTACT(dummycontacts, tri_contact_data.m_points[ci],tri_contact_data.m_separating_normal ,tri_contact_data.m_penetration_depth,trimesh1, trimesh2, ti1, ti2);
290            }
291        }
292    }
293
294    if(dummycontacts.m_size == 0) //reject
295    {
296        GIM_DYNARRAY_DESTROY(dummycontacts);
297        GIM_DYNARRAY_DESTROY(collision_pairs);
298        return;
299    }
300    //merge contacts
301    gim_merge_contacts(&dummycontacts,contacts);
302
303    //Terminate
304    GIM_DYNARRAY_DESTROY(dummycontacts);
305    GIM_DYNARRAY_DESTROY(collision_pairs);
306
307    //Unlocks meshes
308    gim_trimesh_unlocks_work_data(trimesh1);
309    gim_trimesh_unlocks_work_data(trimesh2);
310}
311
312
313//! Trimesh Plane Collisions
314/*!
315
316\param trimesh
317\param plane vec4f plane
318\param contacts A vec4f array. Must be initialized (~100). Each element have the coordinate point in the first 3 elements, and vec4f[3] has the penetration depth.
319*/
320void gim_trimesh_plane_collision(GIM_TRIMESH * trimesh,vec4f plane, GDYNAMIC_ARRAY * contacts)
321{
322    contacts->m_size = 0;
323    char classify;
324    PLANE_CLASSIFY_BOX(plane,trimesh->m_aabbset.m_global_bound,classify);
325    if(classify>1) return; // in front of plane
326
327    //Locks mesh
328    gim_trimesh_locks_work_data(trimesh);
329    //Get vertices
330    GUINT i, vertcount = trimesh->m_transformed_vertex_buffer.m_element_count;
331    vec3f * vertices = GIM_BUFFER_ARRAY_POINTER(vec3f,trimesh->m_transformed_vertex_buffer,0);
332
333    GREAL dist;
334    vec4f * result_contact;
335
336    for (i=0;i<vertcount;i++)
337    {
338        dist = DISTANCE_PLANE_POINT(plane,vertices[i]);
339        if(dist<=0.0f)
340        {
341             GIM_DYNARRAY_PUSH_EMPTY(vec4f,(*contacts));
342             result_contact = GIM_DYNARRAY_POINTER_LAST(vec4f,(*contacts));
343             VEC_COPY((*result_contact),vertices[i]);
344             (*result_contact)[3] = -dist;
345        }
346    }
347    gim_trimesh_unlocks_work_data(trimesh);
348}
Note: See TracBrowser for help on using the repository browser.