From c5fc66ee58f2c60f2d226868bb1cf5b91badaf53 Mon Sep 17 00:00:00 2001 From: sanine Date: Sat, 1 Oct 2022 20:59:36 -0500 Subject: add ode --- libs/ode-0.16.1/GIMPACT/src/gim_trimesh.cpp | 391 ++++++++++++++++++++++++++++ 1 file changed, 391 insertions(+) create mode 100644 libs/ode-0.16.1/GIMPACT/src/gim_trimesh.cpp (limited to 'libs/ode-0.16.1/GIMPACT/src/gim_trimesh.cpp') diff --git a/libs/ode-0.16.1/GIMPACT/src/gim_trimesh.cpp b/libs/ode-0.16.1/GIMPACT/src/gim_trimesh.cpp new file mode 100644 index 0000000..7be639b --- /dev/null +++ b/libs/ode-0.16.1/GIMPACT/src/gim_trimesh.cpp @@ -0,0 +1,391 @@ + +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +#include +#include "GIMPACT/gim_trimesh.h" + +GUINT32 gim_trimesh_get_triangle_count(GIM_TRIMESH * trimesh) +{ + return trimesh->m_tri_index_buffer.m_element_count/3; +} + +//! Creates the aabb set and the triangles cache +/*! + +\param trimesh +\param vertex_array +\param triindex_array +\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. +\post it copies the arrays by reference, and creates the auxiliary data (m_aabbset,m_planes_cache_buffer) +*/ +void gim_trimesh_create_from_arrays(GBUFFER_MANAGER_DATA buffer_managers[], + GIM_TRIMESH * trimesh, GBUFFER_ARRAY * vertex_array, GBUFFER_ARRAY * triindex_array,char transformed_reply) +{ + assert(trimesh); + assert(vertex_array); + assert(triindex_array); + gim_buffer_array_copy_ref(vertex_array,&trimesh->m_source_vertex_buffer); + gim_buffer_array_copy_ref(triindex_array,&trimesh->m_tri_index_buffer); + + trimesh->m_mask = GIM_TRIMESH_NEED_UPDATE;//needs update + //Create the transformed vertices + if(transformed_reply==1) + { + trimesh->m_mask |= GIM_TRIMESH_TRANSFORMED_REPLY; + gim_buffer_array_copy_value(vertex_array, + buffer_managers,&trimesh->m_transformed_vertex_buffer,G_BUFFER_MANAGER_SYSTEM,G_MU_DYNAMIC_READ_WRITE); + } + else + { + gim_buffer_array_copy_ref(vertex_array,&trimesh->m_transformed_vertex_buffer); + } + //create the box set + GUINT32 facecount = gim_trimesh_get_triangle_count(trimesh); + + gim_aabbset_alloc(&trimesh->m_aabbset,facecount); + //create the planes cache + GIM_DYNARRAY_CREATE_SIZED(GIM_TRIPLANES_CACHE,trimesh->m_planes_cache_buffer,facecount); + //Create the bitset + GIM_BITSET_CREATE_SIZED(trimesh->m_planes_cache_bitset,facecount); + //Callback is 0 + trimesh->m_update_callback = 0; + //set to identity + IDENTIFY_MATRIX_4X4(trimesh->m_transform); +} + + + +//! Create a trimesh from vertex array and an index array +/*! + +\param trimesh An uninitialized GIM_TRIMESH structure +\param vertex_array A buffer to a vec3f array +\param vertex_count +\param triindex_array +\param index_count +\param copy_vertices If 1, it copies the source vertices in another buffer. Else (0) it constructs a reference to the data. +\param copy_indices If 1, it copies the source vertices in another buffer. Else (0) it constructs a reference to the data. +\param transformed_reply If , then the m_transformed_vertices is a reply of the source vertices. Else it just be a reference to the original array. +*/ +void gim_trimesh_create_from_data(GBUFFER_MANAGER_DATA buffer_managers[], + GIM_TRIMESH * trimesh, vec3f * vertex_array, GUINT32 vertex_count,char copy_vertices, + GUINT32 * triindex_array, GUINT32 index_count,char copy_indices,char transformed_reply) +{ + GBUFFER_ARRAY buffer_vertex_array; + GBUFFER_ARRAY buffer_triindex_array; + + //Create vertices + if(copy_vertices == 1) + { + gim_create_common_buffer_from_data(buffer_managers, + vertex_array, vertex_count*sizeof(vec3f), &buffer_vertex_array.m_buffer_id); + } + else//Create a shared buffer + { + gim_create_shared_buffer_from_data(buffer_managers, + vertex_array, vertex_count*sizeof(vec3f), &buffer_vertex_array.m_buffer_id); + } + GIM_BUFFER_ARRAY_INIT_TYPE(vec3f,buffer_vertex_array,buffer_vertex_array.m_buffer_id,vertex_count); + + + //Create vertices + if(copy_indices == 1) + { + gim_create_common_buffer_from_data(buffer_managers, + triindex_array, index_count*sizeof(GUINT32), &buffer_triindex_array.m_buffer_id); + } + else//Create a shared buffer + { + gim_create_shared_buffer_from_data(buffer_managers, + triindex_array, index_count*sizeof(GUINT32), &buffer_triindex_array.m_buffer_id); + } + GIM_BUFFER_ARRAY_INIT_TYPE(GUINT32,buffer_triindex_array,buffer_triindex_array.m_buffer_id,index_count); + + gim_trimesh_create_from_arrays(buffer_managers, trimesh, + &buffer_vertex_array, &buffer_triindex_array,transformed_reply); + + ///always call this after create a buffer_array + GIM_BUFFER_ARRAY_DESTROY(buffer_vertex_array); + GIM_BUFFER_ARRAY_DESTROY(buffer_triindex_array); +} + +//! Clears auxiliary data and releases buffer arrays +void gim_trimesh_destroy(GIM_TRIMESH * trimesh) +{ + gim_aabbset_destroy(&trimesh->m_aabbset); + + GIM_DYNARRAY_DESTROY(trimesh->m_planes_cache_buffer); + GIM_DYNARRAY_DESTROY(trimesh->m_planes_cache_bitset); + + GIM_BUFFER_ARRAY_DESTROY(trimesh->m_transformed_vertex_buffer); + GIM_BUFFER_ARRAY_DESTROY(trimesh->m_source_vertex_buffer); + GIM_BUFFER_ARRAY_DESTROY(trimesh->m_tri_index_buffer); +} + +//! Copies two meshes +/*! +\pre dest_trimesh shouldn't be created +\post dest_trimesh will be created +\param source_trimesh +\param dest_trimesh +\param copy_by_reference If 1, it attach a reference to the source vertices, else it copies the vertices +\param transformed_reply IF 1, then it forces the m_trasnformed_vertices to be a reply of the source vertices +*/ +void gim_trimesh_copy(GIM_TRIMESH * source_trimesh, + GBUFFER_MANAGER_DATA dest_buffer_managers[], GIM_TRIMESH * dest_trimesh, + char copy_by_reference, char transformed_reply) +{ +/* -- trimesh can not be copied by reference until GBUFFER_MANAGER_DATA is rewritten + to be thread safe and until it is moved back to global variables. + if(copy_by_reference==1) + { + gim_trimesh_create_from_arrays(dest_trimesh, &source_trimesh->m_source_vertex_buffer, &source_trimesh->m_tri_index_buffer,transformed_reply); + } + else +*/ + { + GBUFFER_ARRAY buffer_vertex_array; + GBUFFER_ARRAY buffer_triindex_array; + + gim_buffer_array_copy_value(&source_trimesh->m_source_vertex_buffer, + dest_buffer_managers,&buffer_vertex_array,G_BUFFER_MANAGER_SYSTEM,G_MU_DYNAMIC_READ_WRITE); + + gim_buffer_array_copy_value(&source_trimesh->m_tri_index_buffer, + dest_buffer_managers,&buffer_triindex_array,G_BUFFER_MANAGER_SYSTEM,G_MU_DYNAMIC_READ_WRITE); + + gim_trimesh_create_from_arrays(dest_buffer_managers, dest_trimesh, + &buffer_vertex_array, &buffer_triindex_array,transformed_reply); + + ///always call this after create a buffer_array + GIM_BUFFER_ARRAY_DESTROY(buffer_vertex_array); + GIM_BUFFER_ARRAY_DESTROY(buffer_triindex_array); + } +} +//! Locks the trimesh for working with it +/*! +\post locks m_tri_index_buffer and m_transformed_vertex_buffer. +\param trimesh +*/ +void gim_trimesh_locks_work_data(GIM_TRIMESH * trimesh) +{ + GINT32 res; + res=gim_buffer_array_lock(&trimesh->m_tri_index_buffer,G_MA_READ_ONLY); + assert(res==G_BUFFER_OP_SUCCESS); + res=gim_buffer_array_lock(&trimesh->m_transformed_vertex_buffer,G_MA_READ_ONLY); + assert(res==G_BUFFER_OP_SUCCESS); +} + +//! unlocks the trimesh +/*! +\post unlocks m_tri_index_buffer and m_transformed_vertex_buffer. +\param trimesh +*/ +void gim_trimesh_unlocks_work_data(GIM_TRIMESH * trimesh) +{ + gim_buffer_array_unlock(&trimesh->m_tri_index_buffer); + gim_buffer_array_unlock(&trimesh->m_transformed_vertex_buffer); +} + + +//! Returns 1 if the m_transformed_vertex_buffer is a reply of m_source_vertex_buffer +char gim_trimesh_has_tranformed_reply(GIM_TRIMESH * trimesh) +{ + if(trimesh->m_mask&GIM_TRIMESH_TRANSFORMED_REPLY) return 1; + return 0; +} + +//! Returns 1 if the trimesh needs to update their aabbset and the planes cache. +char gim_trimesh_needs_update(GIM_TRIMESH * trimesh) +{ + if(trimesh->m_mask&GIM_TRIMESH_NEED_UPDATE) return 1; + return 0; +} + +//! Change the state of the trimesh for force it to update +/*! +Call it after made changes to the trimesh. +\post gim_trimesh_need_update(trimesh) will return 1 +*/ +void gim_trimesh_post_update(GIM_TRIMESH * trimesh) +{ + trimesh->m_mask |= GIM_TRIMESH_NEED_UPDATE; +} + +//kernel +#define MULT_MAT_VEC4_KERNEL(_mat,_src,_dst) MAT_DOT_VEC_3X4((_dst),(_mat),(_src)) + +//! Updates m_transformed_vertex_buffer +/*! +\pre m_transformed_vertex_buffer must be unlocked +*/ +void gim_trimesh_update_vertices(GIM_TRIMESH * trimesh) +{ + if(gim_trimesh_has_tranformed_reply(trimesh) == 0) return; //Don't perform transformation + + //Vertices + GBUFFER_ARRAY * psource_vertex_buffer = &trimesh->m_source_vertex_buffer; + GBUFFER_ARRAY * ptransformed_vertex_buffer = &trimesh->m_transformed_vertex_buffer; + //Temp transform + mat4f transform; + COPY_MATRIX_4X4(transform,trimesh->m_transform); + + GIM_PROCESS_BUFFER_ARRAY(transform,(*psource_vertex_buffer),(*ptransformed_vertex_buffer),MULT_MAT_VEC4_KERNEL,vec3f,vec3f); +} + +//! Updates m_aabbset and m_planes_cache_bitset +/*! +\pre gim_trimesh_locks_work_data must be called before +*/ +void gim_trimesh_update_aabbset(GIM_TRIMESH * trimesh) +{ + vec3f * transformed_vertices = GIM_BUFFER_ARRAY_POINTER(vec3f,trimesh->m_transformed_vertex_buffer,0); + assert(transformed_vertices); + + GUINT32 * triangle_indices = GIM_BUFFER_ARRAY_POINTER(GUINT32,trimesh->m_tri_index_buffer,0); + assert(triangle_indices); + // box set + aabb3f * paabb = trimesh->m_aabbset.m_boxes; + GUINT32 triangle_count = gim_trimesh_get_triangle_count(trimesh); + float * v1,*v2,*v3; + GUINT32 i; + for (i=0; im_planes_cache_bitset); + //Sorts set + gim_aabbset_update(&trimesh->m_aabbset); +} + +//! Updates the trimesh if needed +/*! +\post If gim_trimesh_needs_update returns 1, then it calls gim_trimesh_update_vertices and gim_trimesh_update_aabbset +*/ +void gim_trimesh_update(GIM_TRIMESH * trimesh) +{ + if(gim_trimesh_needs_update(trimesh)==0) return; + gim_trimesh_update_vertices(trimesh); + gim_trimesh_locks_work_data(trimesh); + gim_trimesh_update_aabbset(trimesh); + gim_trimesh_unlocks_work_data(trimesh); + + //Clear update flag + trimesh->m_mask &= ~GIM_TRIMESH_NEED_UPDATE; +} + +void gim_trimesh_set_tranform(GIM_TRIMESH * trimesh, mat4f transform) +{ + GREAL diff = 0.0f; + float * originaltrans = &trimesh->m_transform[0][0]; + float * newtrans = &transform[0][0]; + GUINT32 i; + for (i=0;i<16;i++) + { + diff += fabs(originaltrans[i]-newtrans[i]); + } + +// if(IS_ZERO(diff)) return ;///don't need to update + if(diff< 0.00001f) return ;///don't need to update + + COPY_MATRIX_4X4(trimesh->m_transform,transform); + + gim_trimesh_post_update(trimesh); +} + +void gim_trimesh_get_triangle_data(GIM_TRIMESH * trimesh, GUINT32 triangle_index, GIM_TRIANGLE_DATA * tri_data) +{ + vec3f * transformed_vertices = GIM_BUFFER_ARRAY_POINTER(vec3f,trimesh->m_transformed_vertex_buffer,0); + + GUINT32 * triangle_indices = GIM_BUFFER_ARRAY_POINTER(GUINT32,trimesh->m_tri_index_buffer,triangle_index*3); + + + //Copy the vertices + VEC_COPY(tri_data->m_vertices[0],transformed_vertices[triangle_indices[0]]); + VEC_COPY(tri_data->m_vertices[1],transformed_vertices[triangle_indices[1]]); + VEC_COPY(tri_data->m_vertices[2],transformed_vertices[triangle_indices[2]]); + + //Get the planes + GIM_TRIPLANES_CACHE * planes = GIM_DYNARRAY_POINTER(GIM_TRIPLANES_CACHE,trimesh->m_planes_cache_buffer); + planes += triangle_index; + + //verify planes cache + GUINT32 bit_eval; + GIM_BITSET_GET(trimesh->m_planes_cache_bitset,triangle_index,bit_eval); + if(bit_eval == 0)// Needs to calc the planes + { + //Calc the face plane + TRIANGLE_PLANE(tri_data->m_vertices[0],tri_data->m_vertices[1],tri_data->m_vertices[2],planes->m_planes[0]); + //Calc the edge 1 + EDGE_PLANE(tri_data->m_vertices[0],tri_data->m_vertices[1],(planes->m_planes[0]),(planes->m_planes[1])); + + //Calc the edge 2 + EDGE_PLANE(tri_data->m_vertices[1],tri_data->m_vertices[2],(planes->m_planes[0]),(planes->m_planes[2])); + + //Calc the edge 3 + EDGE_PLANE(tri_data->m_vertices[2],tri_data->m_vertices[0],(planes->m_planes[0]), (planes->m_planes[3])); + + //mark + GIM_BITSET_SET(trimesh->m_planes_cache_bitset,triangle_index); + } + + + VEC_COPY_4((tri_data->m_planes.m_planes[0]),(planes->m_planes[0]));//face plane + VEC_COPY_4((tri_data->m_planes.m_planes[1]),(planes->m_planes[1]));//edge1 + VEC_COPY_4((tri_data->m_planes.m_planes[2]),(planes->m_planes[2]));//edge2 + VEC_COPY_4((tri_data->m_planes.m_planes[3]),(planes->m_planes[3]));//edge3 +} + +void gim_trimesh_get_triangle_vertices(GIM_TRIMESH * trimesh, GUINT32 triangle_index, vec3f v1, vec3f v2, vec3f v3) +{ + vec3f * transformed_vertices = GIM_BUFFER_ARRAY_POINTER(vec3f,trimesh->m_transformed_vertex_buffer,0); + + GUINT32 * triangle_indices = GIM_BUFFER_ARRAY_POINTER(GUINT32,trimesh->m_tri_index_buffer,triangle_index*3); + + //Copy the vertices + if (v1 != NULL) + { + VEC_COPY(v1,transformed_vertices[triangle_indices[0]]); + } + + if (v2 != NULL) + { + VEC_COPY(v2,transformed_vertices[triangle_indices[1]]); + } + + if (v3 != NULL) + { + VEC_COPY(v3,transformed_vertices[triangle_indices[2]]); + } +} -- cgit v1.2.1