1 #ifndef GIM_TRIMESH_H_INCLUDED
2 #define GIM_TRIMESH_H_INCLUDED
3 /*! \file gim_trimesh.h
4 \author Francisco Le�n
5 */
6 /*
7 -----------------------------------------------------------------------------
8 This source file is part of GIMPACT Library.
9 
10 For the latest info, see http://gimpact.sourceforge.net/
11 
12 Copyright (c) 2006 Francisco Leon. C.C. 80087371.
13 email: projectileman@yahoo.com
14 
15  This library is free software; you can redistribute it and/or
16  modify it under the terms of EITHER:
17    (1) The GNU Lesser General Public License as published by the Free
18        Software Foundation; either version 2.1 of the License, or (at
19        your option) any later version. The text of the GNU Lesser
20        General Public License is included with this library in the
21        file GIMPACT-LICENSE-LGPL.TXT.
22    (2) The BSD-style license that is included with this library in
23        the file GIMPACT-LICENSE-BSD.TXT.
24 
25  This library is distributed in the hope that it will be useful,
26  but WITHOUT ANY WARRANTY; without even the implied warranty of
27  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
28  GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
29 
30 -----------------------------------------------------------------------------
31 */
32 
33 #include "GIMPACT/gim_boxpruning.h"
34 #include "GIMPACT/gim_contact.h"
35 
36 
37 ///MAsk defines
38 #define GIM_TRIMESH_TRANSFORMED_REPLY 1
39 #define GIM_TRIMESH_NEED_UPDATE 2
40 
41 /*! \addtogroup TRIMESH
42 \brief
43 A Trimesh is the basic geometric structure for representing solid objects.
44 <p><strong>CREATING TRIMESHES</strong></p>
45 <ul>
46 <li> For creating trimeshes, you must initialize Buffer managers by calling \ref gimpact_init
47 <li> Then you must define the vertex and index sources by creating them with \ref BUFFER_ARRAYS routines, and then call  \ref gim_trimesh_create_from_arrays.
48 <li> An alternative way for creaing trimesh objects is calling  \ref gim_trimesh_create_from_data.
49 <li> For access to the trimesh data (vertices, triangle indices), you must call  \ref gim_trimesh_locks_work_data , and  \ref gim_trimesh_unlocks_work_data for finish the access.
50 <li> Each time when the trimesh data is modified, you must call  \ref gim_trimesh_update after.
51 <li> When a trimesh is no longer needed, you must call \ref gim_trimesh_destroy.
52 </ul>
53 
54 <p>This is an example of how to create a deformable trimesh that shares vertices with the user application:</p>
55 \code
56 //Declaration of vertices
57 vec3f trimeshvertices[200];
58 //Declaration of indices
59 GUINT trimeshindices[100];
60 
61 ... Initializing vertices and triangle indices at beginning
62 
63 //Then create trimesh
64 GIM_TRIMESH mytrimesh;
65 
66 //Calling trimesh create function
67 
68 gim_trimesh_create_from_data(
69 &mytrimesh,
70 trimeshvertices,200,
71 0 ,//copy_vertices is 0
72 trimeshindices,
73 100,
74 0, //copy_indices is 0
75 0 //transformed_reply is 0
76 );
77 \endcode
78 <p>Note that parameter transformed_reply is 0, that means that m_transformed_vertex_buffer is a reference to m_source_vertex on the trimesh, and transformations are not avaliable. Use that configuration if you have to simulate a deformable trimesh like cloth or elastic bodies.</p>
79 <p>When the trimesh is no longer needed, destroy it safely with gim_trimesh_destroy()</p>
80 <p><strong>UPDATING TRIMESHES</strong></p>
81 <p>On simulation loops, is needed to update trimeshes every time for update vertices althought updating triangle boxes and planes cache. There is two ways for update trimeshes: </p>
82 <ul>
83 <li> Updating vertices directly. You need to access to the \ref GIM_TRIMESH.m_source_vertex_buffer member; a vertex buffer which has access to the source vertices.
84 \code
85 // Access to the source vertices
86 gim_buffer_array_lock(&mytrimesh.m_source_vertex_buffer, G_MA_READ_WRITE);
87 
88 //Get a pointer to the vertex buffer
89 vec3f * vertexpointer = GIM_BUFFER_ARRAY_POINTER(vec3f,mytrimesh.m_source_vertex_buffer,0);
90 
91 //Get the amount of vertices
92 int veccount = mytrimesh.m_source_vertex_buffer.m_element_count;
93 
94 //Modify vertices
95 for (int i=0;i<veccount ;i++ )
96 {
97     .....
98     .....
99     processing vertices
100     .....
101 	.....
102 }
103 
104 // Don't forget to unlock the source vertex array
105 gim_buffer_array_unlock(&mytrimesh.m_source_vertex_buffer);
106 
107 // Notify that the state of the trimesh is changed
108 gim_trimesh_post_update(&mytrimesh.m_source_vertex_buffer);
109 
110 \endcode
111 For making trimeshes that allow to update their vertices, use \ref gim_trimesh_create_from_data with parameter <strong>transformed_reply</strong> = 0.
112 </ul>
113 <ul>
114 <li> Aplying a transformation. Simply use \ref gim_trimesh_set_tranform . Remember that with this method trimeshes must be created with \ref gim_trimesh_create_from_data with parameter <strong>transformed_reply</strong> = 1.
115 </ul>
116 <p> After updating vertices, you must call \ref gim_trimesh_update()</p>
117 <p><strong>TRIMESHES COLLISION</strong></p>
118 <p>Before collide trimeshes, you need to update them first.</p>
119 <p>Then you must use \ref gim_trimesh_trimesh_collision().</p>
120 
121 */
122 //! @{
123 
124 //! Prototype for updating vertices
125 typedef void * gim_update_trimesh_function(struct _GIM_TRIMESH *);
126 
127 //! Trimesh
128 struct GIM_TRIMESH
129 {
130     ///Original
131     //@{
132     GBUFFER_ARRAY m_source_vertex_buffer;//!< Buffer of vec3f coordinates
133 
134     //! (GUINT) Indices of triangles,groups of three elements.
135     /*!
136     Array of GUINT. Triangle indices. Each triple contains indices of the vertices for each triangle.
137     \invariant must be aligned
138     */
139     GBUFFER_ARRAY m_tri_index_buffer;
140     //@}
141     ///Allocated
142     //@{
143     char m_mask;//!< Don't use directly
144 
145     //! Allocated transformed vertices vec3f
146     /*!
147     Array of vec3f.If gim_trimesh_has_tranformed_reply(this) == 1 then it refers to the m_source_vertex_buffer
148     \invariant must be aligned
149     */
150     GBUFFER_ARRAY m_transformed_vertex_buffer;
151     //@}
152     ///Auxiliary data
153     //@{
154     GIM_AABB_SET m_aabbset;
155     GDYNAMIC_ARRAY m_planes_cache_buffer;//! Allocated GIM_TRIPLANES_CACHE
156     GDYNAMIC_ARRAY m_planes_cache_bitset;
157     gim_update_trimesh_function * m_update_callback;//! If null, then m_transform is applied.
158     mat4f m_transform;
159     //@}
160 };
161 //typedef struct _GIM_TRIMESH GIM_TRIMESH;
162 
163 /// Info about mesh
164 //! Return the trimesh triangle count
165 GUINT32 gim_trimesh_get_triangle_count(GIM_TRIMESH * trimesh);
166 
167 //! Returns 1 if the m_transformed_vertex_buffer is a reply of m_source_vertex_buffer
168 char gim_trimesh_has_tranformed_reply(GIM_TRIMESH * trimesh);
169 
170 //! Returns 1 if the trimesh needs to update their aabbset and the planes cache.
171 char gim_trimesh_needs_update(GIM_TRIMESH * trimesh);
172 
173 //! Change the state of the trimesh for force it to update
174 /*!
175 Call it after made changes to the trimesh.
176 \post gim_trimesh_need_update(trimesh) will return 1
177 \sa gim_trimesh_needs_update,gim_trimesh_has_tranformed_reply
178 */
179 void gim_trimesh_post_update(GIM_TRIMESH * trimesh);
180 
181 //! Creates the aabb set and the triangles cache
182 /*!
183 
184 \param trimesh
185 \param vertex_array
186 \param triindex_array
187 \param transformed_reply If 1, then the m_transformed_vertices is a reply of the source vertices. Else it just be a reference to the original array.
188 \post it copies the arrays by reference, and creates the auxiliary data (m_aabbset,m_planes_cache_buffer)
189 */
190 void gim_trimesh_create_from_arrays(GBUFFER_MANAGER_DATA buffer_managers[],
191 	GIM_TRIMESH * trimesh, GBUFFER_ARRAY * vertex_array, GBUFFER_ARRAY * triindex_array,char transformed_reply);
192 
193 
194 
195 //! Create a trimesh from vertex array and an index array
196 /*!
197 \param trimesh An uninitialized GIM_TRIMESH  structure
198 \param vertex_array A buffer to a vec3f array
199 \param vertex_count
200 \param triindex_array
201 \param index_count
202 \param copy_vertices If 1, it copies the source vertices in another buffer. Else (0) it constructs a reference to the data.
203 \param copy_indices If 1, it copies the source vertices in another buffer. Else (0) it constructs a reference to the data.
204 \param transformed_reply If 1, then the m_transformed_vertices is a reply of the source vertices. Else it just be a reference to the original array. Use 1 if you will apply transformations to the trimesh. See \ref gim_trimesh_set_tranform().
205 */
206 void gim_trimesh_create_from_data(GBUFFER_MANAGER_DATA buffer_managers[],
207 	GIM_TRIMESH * trimesh, vec3f * vertex_array, GUINT32 vertex_count,char copy_vertices,
208 	GUINT32 * triindex_array, GUINT32 index_count,char copy_indices,char transformed_reply);
209 
210 //! Clears auxiliary data and releases buffer arrays
211 void gim_trimesh_destroy(GIM_TRIMESH * trimesh);
212 
213 //! Copies two meshes
214 /*!
215 \param source_trimesh
216 \param dest_trimesh
217 \param copy_by_reference If 1, it attach a reference to the source vertices, else it copies the vertices
218 \param transformed_reply If 1, transformed vertices are reply of source vertives. 1 Is recommended
219 */
220 void gim_trimesh_copy(GIM_TRIMESH * source_trimesh,
221 	GBUFFER_MANAGER_DATA dest_buffer_managers[], GIM_TRIMESH * dest_trimesh,
222 	char copy_by_reference, char transformed_reply);
223 
224 
225 //! Locks the trimesh for working with it
226 /*!
227 \post locks m_tri_index_buffer and m_transformed_vertex_buffer.
228 \param trimesh
229 */
230 void gim_trimesh_locks_work_data(GIM_TRIMESH * trimesh);
231 
232 
233 //! unlocks the trimesh
234 /*!
235 \post unlocks m_tri_index_buffer and m_transformed_vertex_buffer.
236 \param trimesh
237 */
238 void gim_trimesh_unlocks_work_data(GIM_TRIMESH * trimesh);
239 
240 //! Updates m_transformed_vertex_buffer
241 /*!
242 \pre m_transformed_vertex_buffer must be unlocked
243 */
244 void gim_trimesh_update_vertices(GIM_TRIMESH * trimesh);
245 
246 //! Updates m_aabbset and m_planes_cache_bitset
247 /*!
248 \pre gim_trimesh_locks_work_data must be called before
249 */
250 void gim_trimesh_update_aabbset(GIM_TRIMESH * trimesh);
251 
252 //! Calls before perfom collisions. Updates the trimesh if needed
253 /*!
254 \post If gim_trimesh_needs_update returns 1, then it calls  gim_trimesh_update_vertices and gim_trimesh_update_aabbset
255 */
256 void gim_trimesh_update(GIM_TRIMESH * trimesh);
257 
258 //! Set the transform of a trimesh
259 /*!
260 \post This function calls to gim_trimesh_post_update
261 */
262 void gim_trimesh_set_tranform(GIM_TRIMESH * trimesh, mat4f transform);
263 
264 //! Fetch triangle data
265 /*!
266 \pre gim_trimesh_locks_work_data must be called before
267 */
268 void gim_trimesh_get_triangle_data(GIM_TRIMESH * trimesh, GUINT32 triangle_index, GIM_TRIANGLE_DATA * tri_data);
269 
270 //! Fetch triangle vertices
271 /*!
272 \pre gim_trimesh_locks_work_data must be called before
273 */
274 void gim_trimesh_get_triangle_vertices(GIM_TRIMESH * trimesh, GUINT32 triangle_index, vec3f v1,vec3f v2,vec3f v3);
275 
276 //! Trimesh Trimesh Collisions
277 /*!
278 Before use this function you must update each trimesh:
279 \code
280 gim_trimesh_update(TriMesh1);
281 gim_trimesh_update(TriMesh2);
282 \endcode
283 Then you must use the trimesh collision in this way:
284 \code
285 int collide_trimeshes(GIM_TRIMESH * TriMesh1, GIM_TRIMESH * TriMesh2)
286 {
287     //Create contact list
288     GDYNAMIC_ARRAY trimeshcontacts;
289     GIM_CREATE_CONTACT_LIST(trimeshcontacts);
290 
291     //Collide trimeshes
292     gim_trimesh_trimesh_collision(TriMesh1,TriMesh2,&trimeshcontacts);
293 
294     if(trimeshcontacts.m_size == 0) //do  nothing
295     {
296         GIM_DYNARRAY_DESTROY(trimeshcontacts);//clean contact array
297         return 0;
298     }
299 
300     //Getting a pointer to the contact array
301     GIM_CONTACT * ptrimeshcontacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,trimeshcontacts);
302 
303     int contactcount = trimeshcontacts.m_size;
304     int i;
305     //Process contacts
306     for (i=0;i<contactcount ;i++)
307     {
308         //Do something with the contact (ptrimeshcontacts)
309         ......
310         ......
311         // Like creating joints or anything else
312         ......
313         ......
314         ptrimeshcontacts++;
315     }
316     GIM_DYNARRAY_DESTROY(trimeshcontacts);
317     return contactcount;
318 }
319 \endcode
320 In each contact
321 <ul>
322 <li> m_handle1 points to trimesh1.
323 <li> m_handle2 points to trimesh2.
324 <li> m_feature1 Is a triangle index of trimesh1.
325 <li> m_feature2 Is a triangle index of trimesh2.
326 </ul>
327 
328 \param trimesh1 Collider
329 \param trimesh2 Collidee
330 \param contacts A GIM_CONTACT array. Must be initialized
331 */
332 void gim_trimesh_trimesh_collision(GIM_TRIMESH * trimesh1, GIM_TRIMESH * trimesh2, GDYNAMIC_ARRAY * contacts);
333 
334 
335 //! Trimesh Sphere Collisions
336 /*!
337 Before use this function you must update the trimesh:
338 \code
339 gim_trimesh_update(trimesh);
340 \endcode
341 Then you must use this function in this way:
342 \code
343 int collide_trimesh_sphere(GIM_TRIMESH * trimesh, vec3f center,GREAL radius)
344 {
345     //Create contact list
346     GDYNAMIC_ARRAY trimeshcontacts;
347     GIM_CREATE_CONTACT_LIST(trimeshcontacts);
348 
349     //Collide trimeshes
350     gim_trimesh_sphere_collision(trimesh,center,radius,&trimeshcontacts);
351 
352     if(trimeshcontacts.m_size == 0) //do  nothing
353     {
354         GIM_DYNARRAY_DESTROY(trimeshcontacts);//clean contact array
355         return 0;
356     }
357 
358     //Getting a pointer to the contact array
359     GIM_CONTACT * ptrimeshcontacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,trimeshcontacts);
360 
361     int contactcount = trimeshcontacts.m_size;
362     int i;
363     //Process contacts
364     for (i=0;i<contactcount ;i++)
365     {
366         //Do something with the contact (ptrimeshcontacts)
367         ......
368         ......
369         // Like creating joints or anything else
370         ......
371         ......
372         ptrimeshcontacts++;
373     }
374     GIM_DYNARRAY_DESTROY(trimeshcontacts);
375     return contactcount;
376 }
377 \endcode
378 
379 In each contact
380 <ul>
381 <li> m_handle1 points to trimesh.
382 <li> m_handle2 points to NULL.
383 <li> m_feature1 Is a triangle index of trimesh.
384 </ul>
385 
386 \param trimesh
387 \param center
388 \param radius
389 \param contacts A GIM_CONTACT array. Must be initialized
390 */
391 void gim_trimesh_sphere_collision(GIM_TRIMESH * trimesh,vec3f center,GREAL radius, GDYNAMIC_ARRAY * contacts);
392 
393 
394 //! Trimesh Capsule collision
395 /*!
396 Find the closest primitive collided by the ray.
397 
398 Before use this function you must update the trimesh:
399 \code
400 gim_trimesh_update(trimesh);
401 \endcode
402 Then you must use this function in this way:
403 \code
404 int collide_trimesh_capsule(GIM_TRIMESH * trimesh, GIM_CAPSULE_DATA * capsule)
405 {
406     //Create contact list
407     GDYNAMIC_ARRAY trimeshcontacts;
408     GIM_CREATE_CONTACT_LIST(trimeshcontacts);
409 
410     //Collide trimeshes
411     gim_trimesh_capsule_collision(trimesh,capsule,&trimeshcontacts);
412 
413     if(trimeshcontacts.m_size == 0) //do  nothing
414     {
415         GIM_DYNARRAY_DESTROY(trimeshcontacts);//clean contact array
416         return 0;
417     }
418 
419     //Getting a pointer to the contact array
420     GIM_CONTACT * ptrimeshcontacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,trimeshcontacts);
421 
422     int contactcount = trimeshcontacts.m_size;
423     int i;
424     //Process contacts
425     for (i=0;i<contactcount ;i++)
426     {
427         //Do something with the contact (ptrimeshcontacts)
428         ......
429         ......
430         // Like creating joints or anything else
431         ......
432         ......
433         ptrimeshcontacts++;
434     }
435     GIM_DYNARRAY_DESTROY(trimeshcontacts);
436     return contactcount;
437 }
438 \endcode
439 
440 In each contact
441 <ul>
442 <li> m_handle1 points to trimesh.
443 <li> m_handle2 points to NULL.
444 <li> m_feature1 Is a triangle index of trimesh.
445 </ul>
446 
447 \param trimesh
448 \param capsule
449 \param contacts A GIM_CONTACT array. Must be initialized
450 */
451 void gim_trimesh_capsule_collision(GIM_TRIMESH * trimesh, GIM_CAPSULE_DATA * capsule, GDYNAMIC_ARRAY * contacts);
452 
453 
454 ///Function for create Trimesh Plane  collision result
455 #define GIM_CREATE_TRIMESHPLANE_CONTACTS(dynarray) GIM_DYNARRAY_CREATE(vec4f,dynarray,G_ARRAY_GROW_SIZE)
456 
457 //! Trimesh Plane Collisions
458 /*!
459 
460 Before use this function you must update the trimesh:
461 \code
462 gim_trimesh_update(trimesh);
463 \endcode
464 Then you must use this function in this way:
465 \code
466 int collide_trimesh_plane(GIM_TRIMESH * trimesh, vec4f plane)
467 {
468     //Create contact list
469     GDYNAMIC_ARRAY tri_plane_contacts;
470     GIM_CREATE_TRIMESHPLANE_CONTACTS(tri_plane_contacts);
471 
472     //Collide trimeshes
473     gim_trimesh_plane_collision(trimesh,plane,&tri_plane_contacts);
474 
475     if(tri_plane_contacts.m_size == 0) //do  nothing
476     {
477         GIM_DYNARRAY_DESTROY(tri_plane_contacts);//clean contact array
478         return 0;
479     }
480 
481     //Getting a pointer to the contact array
482     vec4f * planecontacts = GIM_DYNARRAY_POINTER(vec4f,tri_plane_contacts);
483 
484     int contactcount = tri_plane_contacts.m_size;
485     int i;
486     //Process contacts
487     for (i=0;i<contactcount ;i++)
488     {
489         vec3f contactpoint;
490         GREAL contactdis;
491 
492         VEC_COPY(contactpoint,planecontacts[i]); //Get contact point
493         contactdis = planecontacts[i][3]; // Get distance depth
494 
495         //Do something with the contact
496         ......
497         ......
498         // Like creating joints or anything else
499         ......
500         ......
501     }
502     GIM_DYNARRAY_DESTROY(tri_plane_contacts);
503     return contactcount;
504 }
505 \endcode
506 
507 In each contact the 3 first coordinates refers to the contact point, the fourth refers to the distance depth and the normal is the normal of the plane.
508 
509 \param trimesh
510 \param plane vec4f plane
511 \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.
512 */
513 void gim_trimesh_plane_collision(GIM_TRIMESH * trimesh,vec4f plane, GDYNAMIC_ARRAY * contacts);
514 
515 
516 //! Trimesh Ray Collisions
517 /*!
518 \param trimesh
519 \param origin
520 \param dir
521 \param tmax
522 \param contact
523 \return 1 if the ray collides, else 0
524 */
525 int gim_trimesh_ray_collision(GIM_TRIMESH * trimesh,vec3f origin,vec3f dir, GREAL tmax, GIM_TRIANGLE_RAY_CONTACT_DATA * contact);
526 
527 
528 //! Trimesh Ray Collisions closest
529 /*!
530 Find the closest primitive collided by the ray
531 \param trimesh
532 \param origin
533 \param dir
534 \param tmax
535 \param contact
536 \return 1 if the ray collides, else 0
537 */
538 int gim_trimesh_ray_closest_collision(GIM_TRIMESH * trimesh,vec3f origin,vec3f dir, GREAL tmax, GIM_TRIANGLE_RAY_CONTACT_DATA * contact);
539 
540 //! @}
541 
542 
543 
544 #endif // GIM_TRIMESH_H_INCLUDED
545