3 -----------------------------------------------------------------------------
4 This source file is part of GIMPACT Library.
6 For the latest info, see http://gimpact.sourceforge.net/
8 Copyright (c) 2006 Francisco Leon. C.C. 80087371.
9 email: projectileman@yahoo.com
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.
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.
26 -----------------------------------------------------------------------------
31 #include "GIMPACT/gim_trimesh.h"
33 GUINT32
gim_trimesh_get_triangle_count(GIM_TRIMESH
* trimesh
)
35 return trimesh
->m_tri_index_buffer
.m_element_count
/3;
38 //! Creates the aabb set and the triangles cache
44 \param transformed_reply If 1, then the m_transformed_vertices is a reply of the source vertices. Else it just is a reference to the original array.
45 \post it copies the arrays by reference, and creates the auxiliary data (m_aabbset,m_planes_cache_buffer)
47 void gim_trimesh_create_from_arrays(GBUFFER_MANAGER_DATA buffer_managers
[],
48 GIM_TRIMESH
* trimesh
, GBUFFER_ARRAY
* vertex_array
, GBUFFER_ARRAY
* triindex_array
,char transformed_reply
)
52 assert(triindex_array
);
53 gim_buffer_array_copy_ref(vertex_array
,&trimesh
->m_source_vertex_buffer
);
54 gim_buffer_array_copy_ref(triindex_array
,&trimesh
->m_tri_index_buffer
);
56 trimesh
->m_mask
= GIM_TRIMESH_NEED_UPDATE
;//needs update
57 //Create the transformed vertices
58 if(transformed_reply
==1)
60 trimesh
->m_mask
|= GIM_TRIMESH_TRANSFORMED_REPLY
;
61 gim_buffer_array_copy_value(vertex_array
,
62 buffer_managers
,&trimesh
->m_transformed_vertex_buffer
,G_BUFFER_MANAGER_SYSTEM
,G_MU_DYNAMIC_READ_WRITE
);
66 gim_buffer_array_copy_ref(vertex_array
,&trimesh
->m_transformed_vertex_buffer
);
69 GUINT32 facecount
= gim_trimesh_get_triangle_count(trimesh
);
71 gim_aabbset_alloc(&trimesh
->m_aabbset
,facecount
);
72 //create the planes cache
73 GIM_DYNARRAY_CREATE_SIZED(GIM_TRIPLANES_CACHE
,trimesh
->m_planes_cache_buffer
,facecount
);
75 GIM_BITSET_CREATE_SIZED(trimesh
->m_planes_cache_bitset
,facecount
);
77 trimesh
->m_update_callback
= 0;
79 IDENTIFY_MATRIX_4X4(trimesh
->m_transform
);
84 //! Create a trimesh from vertex array and an index array
87 \param trimesh An uninitialized GIM_TRIMESH structure
88 \param vertex_array A buffer to a vec3f array
92 \param copy_vertices If 1, it copies the source vertices to another buffer. Else (0) it constructs a reference to the data.
93 \param copy_indices If 1, it copies the source vertices to another buffer. Else (0) it constructs a reference to the data.
94 \param transformed_reply If 1, then the m_transformed_vertices is a reply of the source vertices. Else (0) it just is a reference to the original array.
96 void gim_trimesh_create_from_data(GBUFFER_MANAGER_DATA buffer_managers
[],
97 GIM_TRIMESH
* trimesh
, vec3f
* vertex_array
, GUINT32 vertex_count
,char copy_vertices
,
98 GUINT32
* triindex_array
, GUINT32 index_count
,char copy_indices
,char transformed_reply
)
100 GBUFFER_ARRAY buffer_vertex_array
;
101 GBUFFER_ARRAY buffer_triindex_array
;
104 if(copy_vertices
== 1)
106 gim_create_common_buffer_from_data(buffer_managers
,
107 vertex_array
, vertex_count
*sizeof(vec3f
), &buffer_vertex_array
.m_buffer_id
);
109 else//Create a shared buffer
111 gim_create_shared_buffer_from_data(buffer_managers
,
112 vertex_array
, vertex_count
*sizeof(vec3f
), &buffer_vertex_array
.m_buffer_id
);
114 GIM_BUFFER_ARRAY_INIT_TYPE(vec3f
,buffer_vertex_array
,buffer_vertex_array
.m_buffer_id
,vertex_count
);
118 if(copy_indices
== 1)
120 gim_create_common_buffer_from_data(buffer_managers
,
121 triindex_array
, index_count
*sizeof(GUINT32
), &buffer_triindex_array
.m_buffer_id
);
123 else//Create a shared buffer
125 gim_create_shared_buffer_from_data(buffer_managers
,
126 triindex_array
, index_count
*sizeof(GUINT32
), &buffer_triindex_array
.m_buffer_id
);
128 GIM_BUFFER_ARRAY_INIT_TYPE(GUINT32
,buffer_triindex_array
,buffer_triindex_array
.m_buffer_id
,index_count
);
130 gim_trimesh_create_from_arrays(buffer_managers
, trimesh
,
131 &buffer_vertex_array
, &buffer_triindex_array
,transformed_reply
);
133 ///always call this after create a buffer_array
134 GIM_BUFFER_ARRAY_DESTROY(buffer_vertex_array
);
135 GIM_BUFFER_ARRAY_DESTROY(buffer_triindex_array
);
138 //! Clears auxiliary data and releases buffer arrays
139 void gim_trimesh_destroy(GIM_TRIMESH
* trimesh
)
141 gim_aabbset_destroy(&trimesh
->m_aabbset
);
143 GIM_DYNARRAY_DESTROY(trimesh
->m_planes_cache_buffer
);
144 GIM_DYNARRAY_DESTROY(trimesh
->m_planes_cache_bitset
);
146 GIM_BUFFER_ARRAY_DESTROY(trimesh
->m_transformed_vertex_buffer
);
147 GIM_BUFFER_ARRAY_DESTROY(trimesh
->m_source_vertex_buffer
);
148 GIM_BUFFER_ARRAY_DESTROY(trimesh
->m_tri_index_buffer
);
151 //! Copies two meshes
153 \pre dest_trimesh shouldn't be created
154 \post dest_trimesh will be created
155 \param source_trimesh
157 \param copy_by_reference If 1, it attaches a reference to the source vertices, else it copies the vertices
158 \param transformed_reply IF 1, then it forces the m_trasnformed_vertices to be a reply of the source vertices
160 void gim_trimesh_copy(GIM_TRIMESH
* source_trimesh
,
161 GBUFFER_MANAGER_DATA dest_buffer_managers
[], GIM_TRIMESH
* dest_trimesh
,
162 char copy_by_reference
, char transformed_reply
)
164 /* -- trimesh can not be copied by reference until GBUFFER_MANAGER_DATA is rewritten
165 to be thread safe and until it is moved back to global variables.
166 if(copy_by_reference==1)
168 gim_trimesh_create_from_arrays(dest_trimesh, &source_trimesh->m_source_vertex_buffer, &source_trimesh->m_tri_index_buffer,transformed_reply);
173 GBUFFER_ARRAY buffer_vertex_array
;
174 GBUFFER_ARRAY buffer_triindex_array
;
176 gim_buffer_array_copy_value(&source_trimesh
->m_source_vertex_buffer
,
177 dest_buffer_managers
,&buffer_vertex_array
,G_BUFFER_MANAGER_SYSTEM
,G_MU_DYNAMIC_READ_WRITE
);
179 gim_buffer_array_copy_value(&source_trimesh
->m_tri_index_buffer
,
180 dest_buffer_managers
,&buffer_triindex_array
,G_BUFFER_MANAGER_SYSTEM
,G_MU_DYNAMIC_READ_WRITE
);
182 gim_trimesh_create_from_arrays(dest_buffer_managers
, dest_trimesh
,
183 &buffer_vertex_array
, &buffer_triindex_array
,transformed_reply
);
185 ///always call this after create a buffer_array
186 GIM_BUFFER_ARRAY_DESTROY(buffer_vertex_array
);
187 GIM_BUFFER_ARRAY_DESTROY(buffer_triindex_array
);
190 //! Locks the trimesh for working with it
192 \post locks m_tri_index_buffer and m_transformed_vertex_buffer.
195 void gim_trimesh_locks_work_data(GIM_TRIMESH
* trimesh
)
198 res
=gim_buffer_array_lock(&trimesh
->m_tri_index_buffer
,G_MA_READ_ONLY
);
199 assert(res
==G_BUFFER_OP_SUCCESS
);
200 res
=gim_buffer_array_lock(&trimesh
->m_transformed_vertex_buffer
,G_MA_READ_ONLY
);
201 assert(res
==G_BUFFER_OP_SUCCESS
);
204 //! unlocks the trimesh
206 \post unlocks m_tri_index_buffer and m_transformed_vertex_buffer.
209 void gim_trimesh_unlocks_work_data(GIM_TRIMESH
* trimesh
)
211 gim_buffer_array_unlock(&trimesh
->m_tri_index_buffer
);
212 gim_buffer_array_unlock(&trimesh
->m_transformed_vertex_buffer
);
216 //! Returns 1 if the m_transformed_vertex_buffer is a reply of m_source_vertex_buffer
217 char gim_trimesh_has_tranformed_reply(GIM_TRIMESH
* trimesh
)
219 if(trimesh
->m_mask
&GIM_TRIMESH_TRANSFORMED_REPLY
) return 1;
223 //! Returns 1 if the trimesh needs to update their aabbset and the planes cache.
224 char gim_trimesh_needs_update(GIM_TRIMESH
* trimesh
)
226 if(trimesh
->m_mask
&GIM_TRIMESH_NEED_UPDATE
) return 1;
230 //! Change the state of the trimesh for force it to update
232 Call it after having made changes to the trimesh.
233 \post gim_trimesh_need_update(trimesh) will return 1
235 void gim_trimesh_post_update(GIM_TRIMESH
* trimesh
)
237 trimesh
->m_mask
|= GIM_TRIMESH_NEED_UPDATE
;
241 #define MULT_MAT_VEC4_KERNEL(_mat,_src,_dst) MAT_DOT_VEC_3X4((_dst),(_mat),(_src))
243 //! Updates m_transformed_vertex_buffer
245 \pre m_transformed_vertex_buffer must be unlocked
247 void gim_trimesh_update_vertices(GIM_TRIMESH
* trimesh
)
249 if(gim_trimesh_has_tranformed_reply(trimesh
) == 0) return; //Don't perform transformation
252 GBUFFER_ARRAY
* psource_vertex_buffer
= &trimesh
->m_source_vertex_buffer
;
253 GBUFFER_ARRAY
* ptransformed_vertex_buffer
= &trimesh
->m_transformed_vertex_buffer
;
256 COPY_MATRIX_4X4(transform
,trimesh
->m_transform
);
258 GIM_PROCESS_BUFFER_ARRAY(transform
,(*psource_vertex_buffer
),(*ptransformed_vertex_buffer
),MULT_MAT_VEC4_KERNEL
,vec3f
,vec3f
);
261 //! Updates m_aabbset and m_planes_cache_bitset
263 \pre gim_trimesh_locks_work_data must be called before
265 void gim_trimesh_update_aabbset(GIM_TRIMESH
* trimesh
)
267 vec3f
* transformed_vertices
= GIM_BUFFER_ARRAY_POINTER(vec3f
,trimesh
->m_transformed_vertex_buffer
,0);
268 assert(transformed_vertices
);
270 GUINT32
* triangle_indices
= GIM_BUFFER_ARRAY_POINTER(GUINT32
,trimesh
->m_tri_index_buffer
,0);
271 assert(triangle_indices
);
273 aabb3f
* paabb
= trimesh
->m_aabbset
.m_boxes
;
274 GUINT32 triangle_count
= gim_trimesh_get_triangle_count(trimesh
);
277 for (i
=0; i
<triangle_count
;i
++)
279 v1
= &transformed_vertices
[triangle_indices
[0]][0];
280 v2
= &transformed_vertices
[triangle_indices
[1]][0];
281 v3
= &transformed_vertices
[triangle_indices
[2]][0];
282 COMPUTEAABB_FOR_TRIANGLE((*paabb
),v1
,v2
,v3
);
287 GIM_BITSET_CLEAR_ALL(trimesh
->m_planes_cache_bitset
);
289 gim_aabbset_update(&trimesh
->m_aabbset
);
292 //! Updates the trimesh if needed
294 \post If gim_trimesh_needs_update returns 1, then it calls gim_trimesh_update_vertices and gim_trimesh_update_aabbset
296 void gim_trimesh_update(GIM_TRIMESH
* trimesh
)
298 if(gim_trimesh_needs_update(trimesh
)==0) return;
299 gim_trimesh_update_vertices(trimesh
);
300 gim_trimesh_locks_work_data(trimesh
);
301 gim_trimesh_update_aabbset(trimesh
);
302 gim_trimesh_unlocks_work_data(trimesh
);
305 trimesh
->m_mask
&= ~GIM_TRIMESH_NEED_UPDATE
;
308 void gim_trimesh_set_tranform(GIM_TRIMESH
* trimesh
, mat4f transform
)
311 float * originaltrans
= &trimesh
->m_transform
[0][0];
312 float * newtrans
= &transform
[0][0];
316 diff
+= GIM_FABS_FN(originaltrans
[i
]-newtrans
[i
]);
319 // if(IS_ZERO(diff)) return ;///don't need to update
320 if(diff
< 0.00001f
) return ;///don't need to update
322 COPY_MATRIX_4X4(trimesh
->m_transform
,transform
);
324 gim_trimesh_post_update(trimesh
);
327 void gim_trimesh_get_triangle_data(GIM_TRIMESH
* trimesh
, GUINT32 triangle_index
, GIM_TRIANGLE_DATA
* tri_data
)
329 vec3f
* transformed_vertices
= GIM_BUFFER_ARRAY_POINTER(vec3f
,trimesh
->m_transformed_vertex_buffer
,0);
331 GUINT32
* triangle_indices
= GIM_BUFFER_ARRAY_POINTER(GUINT32
,trimesh
->m_tri_index_buffer
,triangle_index
*3);
335 VEC_COPY(tri_data
->m_vertices
[0],transformed_vertices
[triangle_indices
[0]]);
336 VEC_COPY(tri_data
->m_vertices
[1],transformed_vertices
[triangle_indices
[1]]);
337 VEC_COPY(tri_data
->m_vertices
[2],transformed_vertices
[triangle_indices
[2]]);
340 GIM_TRIPLANES_CACHE
* planes
= GIM_DYNARRAY_POINTER(GIM_TRIPLANES_CACHE
,trimesh
->m_planes_cache_buffer
);
341 planes
+= triangle_index
;
343 //verify planes cache
345 GIM_BITSET_GET(trimesh
->m_planes_cache_bitset
,triangle_index
,bit_eval
);
346 if(bit_eval
== 0)// Needs to calc the planes
348 //Calc the face plane
349 TRIANGLE_PLANE(tri_data
->m_vertices
[0],tri_data
->m_vertices
[1],tri_data
->m_vertices
[2],planes
->m_planes
[0]);
351 EDGE_PLANE(tri_data
->m_vertices
[0],tri_data
->m_vertices
[1],(planes
->m_planes
[0]),(planes
->m_planes
[1]));
354 EDGE_PLANE(tri_data
->m_vertices
[1],tri_data
->m_vertices
[2],(planes
->m_planes
[0]),(planes
->m_planes
[2]));
357 EDGE_PLANE(tri_data
->m_vertices
[2],tri_data
->m_vertices
[0],(planes
->m_planes
[0]), (planes
->m_planes
[3]));
360 GIM_BITSET_SET(trimesh
->m_planes_cache_bitset
,triangle_index
);
364 VEC_COPY_4((tri_data
->m_planes
.m_planes
[0]),(planes
->m_planes
[0]));//face plane
365 VEC_COPY_4((tri_data
->m_planes
.m_planes
[1]),(planes
->m_planes
[1]));//edge1
366 VEC_COPY_4((tri_data
->m_planes
.m_planes
[2]),(planes
->m_planes
[2]));//edge2
367 VEC_COPY_4((tri_data
->m_planes
.m_planes
[3]),(planes
->m_planes
[3]));//edge3
370 void gim_trimesh_get_triangle_vertices(GIM_TRIMESH
* trimesh
, GUINT32 triangle_index
, vec3f v1
, vec3f v2
, vec3f v3
)
372 vec3f
* transformed_vertices
= GIM_BUFFER_ARRAY_POINTER(vec3f
,trimesh
->m_transformed_vertex_buffer
,0);
374 GUINT32
* triangle_indices
= GIM_BUFFER_ARRAY_POINTER(GUINT32
,trimesh
->m_tri_index_buffer
,triangle_index
*3);
379 VEC_COPY(v1
,transformed_vertices
[triangle_indices
[0]]);
384 VEC_COPY(v2
,transformed_vertices
[triangle_indices
[1]]);
389 VEC_COPY(v3
,transformed_vertices
[triangle_indices
[2]]);