gimpact 0.2 prep

This commit is contained in:
ejcoumans
2007-06-22 16:59:13 +00:00
parent a399784077
commit 55258a8a72
36 changed files with 0 additions and 12082 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,185 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. 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.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.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, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "GIMPACT/gim_contact.h"
#define MAX_COINCIDENT 8
void gim_interpolate_contact_normals(GIM_CONTACT * destcontact,vec3f * normals,GUINT normal_count)
{
GREAL vec_sum[]={0.0f,0.0f,0.0f};
vec3f test_vec;
for(GUINT i=0;i<normal_count;i++)
{
VEC_SCALE(test_vec,destcontact->m_depth,normals[i]);
VEC_SUM(vec_sum,vec_sum,test_vec);
}
if(VEC_DOT(vec_sum,vec_sum)<CONTACT_DIFF_EPSILON) return;
test_vec[0] = 1.0f/((GREAL)normal_count);
VEC_SCALE(vec_sum,test_vec[0],vec_sum);
VEC_LENGTH(vec_sum,destcontact->m_depth);
test_vec[0] = 1.0f/destcontact->m_depth;
VEC_SCALE(destcontact->m_normal,test_vec[0],vec_sum);
}
void gim_merge_contacts(GDYNAMIC_ARRAY * source_contacts,
GDYNAMIC_ARRAY * dest_contacts)
{
dest_contacts->m_size = 0;
GUINT source_count = source_contacts->m_size;
GIM_CONTACT * psource_contacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,(*source_contacts));
//create keys
GIM_RSORT_TOKEN * keycontacts = (GIM_RSORT_TOKEN * )gim_alloc(sizeof(GIM_RSORT_TOKEN)*source_count);
GUINT i;
for(i=0;i<source_count;i++)
{
keycontacts[i].m_value = i;
GIM_CALC_KEY_CONTACT(psource_contacts[i].m_point,keycontacts[i].m_key);
}
//sort keys
GIM_QUICK_SORT_ARRAY(GIM_RSORT_TOKEN , keycontacts, source_count, RSORT_TOKEN_COMPARATOR,GIM_DEF_EXCHANGE_MACRO);
// Merge contacts
GIM_CONTACT * pcontact = 0;
GIM_CONTACT * scontact = 0;
GUINT key,last_key=0;
GUINT coincident_count=0;
vec3f coincident_normals[MAX_COINCIDENT];
for(i=0;i<source_contacts->m_size;i++)
{
key = keycontacts[i].m_key;
scontact = &psource_contacts[keycontacts[i].m_value];
if(i>0 && last_key == key)
{
//merge contact
if(pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//)
{
GIM_COPY_CONTACTS(pcontact, scontact);
coincident_count = 0;
}
else
{
#if (NORMAL_CONTACT_AVERAGE == 1)
if(fabsf(pcontact->m_depth - scontact->m_depth)<CONTACT_DIFF_EPSILON)
{
if(coincident_count<MAX_COINCIDENT)
{
VEC_COPY(coincident_normals[coincident_count],scontact->m_normal);
coincident_count++;
}
}
#endif
}
}
else
{//add new contact
#if (NORMAL_CONTACT_AVERAGE == 1)
if(pcontact&&coincident_count>0)
{
gim_interpolate_contact_normals(pcontact,coincident_normals,coincident_count);
coincident_count = 0;
}
#endif
GIM_DYNARRAY_PUSH_EMPTY(GIM_CONTACT,(*dest_contacts));
pcontact = GIM_DYNARRAY_POINTER_LAST(GIM_CONTACT,(*dest_contacts));
GIM_COPY_CONTACTS(pcontact, scontact);
coincident_count=0;
}
last_key = key;
}
gim_free(keycontacts,0);
}
void gim_merge_contacts_unique(GDYNAMIC_ARRAY * source_contacts,
GDYNAMIC_ARRAY * dest_contacts)
{
dest_contacts->m_size = 0;
//Traverse the source contacts
GUINT source_count = source_contacts->m_size;
if(source_count==0) return;
GIM_CONTACT * psource_contacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,(*source_contacts));
//add the unique contact
GIM_CONTACT * pcontact = 0;
GIM_DYNARRAY_PUSH_EMPTY(GIM_CONTACT,(*dest_contacts));
pcontact = GIM_DYNARRAY_POINTER_LAST(GIM_CONTACT,(*dest_contacts));
//set the first contact
GIM_COPY_CONTACTS(pcontact, psource_contacts);
if(source_count==1) return;
//scale the first contact
VEC_SCALE(pcontact->m_normal,pcontact->m_depth,pcontact->m_normal);
psource_contacts++;
//Average the contacts
GUINT i;
for(i=1;i<source_count;i++)
{
VEC_SUM(pcontact->m_point,pcontact->m_point,psource_contacts->m_point);
VEC_ACCUM(pcontact->m_normal,psource_contacts->m_depth,psource_contacts->m_normal);
psource_contacts++;
}
GREAL divide_average = 1.0f/((GREAL)source_count);
VEC_SCALE(pcontact->m_point,divide_average,pcontact->m_point);
pcontact->m_depth = VEC_DOT(pcontact->m_normal,pcontact->m_normal)*divide_average;
GIM_SQRT(pcontact->m_depth,pcontact->m_depth);
VEC_NORMALIZE(pcontact->m_normal);
/*GREAL normal_len;
VEC_INV_LENGTH(pcontact->m_normal,normal_len);
VEC_SCALE(pcontact->m_normal,normal_len,pcontact->m_normal);
//Deep = LEN(normal)/SQRT(source_count)
GIM_SQRT(divide_average,divide_average);
pcontact->m_depth = divide_average/normal_len;
*/
}

View File

@@ -1,62 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. 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.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.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, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "GIMPACT/gim_math.h"
#include "stdlib.h"
#include "time.h"
GREAL gim_inv_sqrt(GREAL f)
{
GREAL r;
GIM_INV_SQRT(f,r);
return r;
}
GREAL gim_sqrt(GREAL f)
{
GREAL r;
GIM_SQRT(f,r);
return r;
}
//!Initializes mathematical functions
void gim_init_math()
{
srand(time(0));
}
//! Generates an unit random
GREAL gim_unit_random()
{
GREAL rn = rand();
rn/=(GREAL)RAND_MAX;
return rn;
}

View File

@@ -1,857 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. 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.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.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, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "GIMPACT/gim_memory.h"
#include "stdlib.h"
//#include "malloc.h"
//#include "mm_malloc.h"
static gim_alloc_function *g_allocfn = 0;
static gim_alloca_function *g_allocafn = 0;
static gim_realloc_function *g_reallocfn = 0;
static gim_free_function *g_freefn = 0;
// buffer managers
#define MAX_BUFFER_MANAGERS 16
static GBUFFER_MANAGER_DATA g_buffer_managers[MAX_BUFFER_MANAGERS];
static GUINT g_buffer_managers_count = 0;
#define VALIDATE_BUFFER_MANAGER(buffer_manager_id)\
if(buffer_manager_id>=MAX_BUFFER_MANAGERS) return G_BUFFER_OP_INVALID;\
GBUFFER_MANAGER_DATA * bm_data;\
gim_get_buffer_manager_data(buffer_manager_id,&bm_data);\
if(bm_data == 0) return G_BUFFER_OP_INVALID;\
#define VALIDATE_BUFFER_ID_PT(buffer_id)\
VALIDATE_BUFFER_MANAGER(buffer_id->m_buffer_manager_id)\
if(buffer_id->m_buffer_id>=bm_data->m_buffer_array.m_size) return G_BUFFER_OP_INVALID;\
GBUFFER_DATA * pbuffer = GIM_DYNARRAY_POINTER(GBUFFER_DATA,bm_data->m_buffer_array);\
pbuffer += buffer_id->m_buffer_id;\
if(pbuffer->m_buffer_handle==0) return G_BUFFER_OP_INVALID;\
void GIM_BUFFER_ARRAY_DESTROY(GBUFFER_ARRAY & array_data)
{
gim_buffer_array_unlock(&array_data);
gim_buffer_free(&(array_data).m_buffer_id);
array_data.m_buffer_id.m_buffer_id = G_UINT_INFINITY;
array_data.m_element_count = 0;
}
void GIM_DYNARRAY_DESTROY(GDYNAMIC_ARRAY & array_data)
{
if(array_data.m_pdata != 0)
{
gim_free(array_data.m_pdata,0);
array_data.m_reserve_size = 0;
array_data.m_size = 0;
array_data.m_pdata = 0;
}
}
void gim_set_alloc_handler (gim_alloc_function *fn)
{
g_allocfn = fn;
}
void gim_set_alloca_handler (gim_alloca_function *fn)
{
g_allocafn = fn;
}
void gim_set_realloc_handler (gim_realloc_function *fn)
{
g_reallocfn = fn;
}
void gim_set_free_handler (gim_free_function *fn)
{
g_freefn = fn;
}
gim_alloc_function *gim_get_alloc_handler()
{
return g_allocfn;
}
gim_alloca_function *gim_get_alloca_handler()
{
return g_allocafn;
}
gim_realloc_function *gim_get_realloc_handler ()
{
return g_reallocfn;
}
gim_free_function *gim_get_free_handler ()
{
return g_freefn;
}
void * gim_alloc(size_t size)
{
char * ptr = 0;
ptr = new char[size]; //malloc(size);
/*if (g_allocfn) ptr = g_allocfn(size); else ptr = malloc(size);//_mm_malloc(size,0);*/
if(ptr==0)
{
float * fp = 0;
*fp = 0.0f;
}
return ptr;
}
#ifdef ALLOCA_GIMPACT
void * gim_alloca(size_t size)
{
if (g_allocafn) return g_allocafn(size); else
return alloca(size);
}
#endif
void * gim_realloc(void *ptr, size_t oldsize, size_t newsize)
{
/*if (g_reallocfn) return g_reallocfn(ptr,oldsize,newsize);
else return realloc(ptr,newsize);*/
//return realloc(ptr,newsize);
void * newptr = gim_alloc(newsize);
size_t copysize = newsize> oldsize? oldsize: newsize;
memcpy(newptr,ptr,copysize);
gim_free(ptr,oldsize);
return newptr;
}
void gim_free(void *ptr, size_t size)
{
if (!ptr) return;
if (g_freefn)
{
g_freefn(ptr,size);
}
else
{
char * cptr = (char *)ptr;
delete [] cptr;
//free(ptr);//_mm_free(ptr);
}
}
///******************************* BUFFER MANAGERS ******************************///
//!** Basic buffer prototyoe functions
GUINT _system_buffer_alloc_function(GUINT size,int usage)
{
void * newdata = gim_alloc(size);
memset(newdata,0,size);
return (GUINT)(newdata);
}
GUINT _system_buffer_alloc_data_function(const void * pdata,GUINT size,int usage)
{
void * newdata = gim_alloc(size);
memcpy(newdata,pdata,size);
return (GUINT)(newdata);
}
GUINT _system_buffer_realloc_function(GUINT buffer_handle,GUINT oldsize,int old_usage,GUINT newsize,int new_usage)
{
void * newdata = gim_realloc((void *)buffer_handle,oldsize,newsize);
return (GUINT)(newdata);
}
void _system_buffer_free_function(GUINT buffer_handle,GUINT size)
{
gim_free((void*)buffer_handle,size);
}
char * _system_lock_buffer_function(GUINT buffer_handle,int access)
{
return (char * )(buffer_handle);
}
void _system_unlock_buffer_function(GUINT buffer_handle)
{
}
void _system_download_from_buffer_function(
GUINT source_buffer_handle,
GUINT source_pos,
void * destdata,
GUINT copysize)
{
char * pdata;
pdata = (char *)source_buffer_handle;
memcpy(destdata,pdata+source_pos,copysize);
}
void _system_upload_to_buffer_function(
GUINT dest_buffer_handle,
GUINT dest_pos,
void * sourcedata,
GUINT copysize)
{
char * pdata;
pdata = (char * )dest_buffer_handle;
memcpy(pdata+dest_pos,sourcedata,copysize);
}
void _system_copy_buffers_function(
GUINT source_buffer_handle,
GUINT source_pos,
GUINT dest_buffer_handle,
GUINT dest_pos,
GUINT copysize)
{
char * pdata1,*pdata2;
pdata1 = (char *)source_buffer_handle;
pdata2 = (char *)dest_buffer_handle;
memcpy(pdata2+dest_pos,pdata1+source_pos,copysize);
}
GUINT _shared_buffer_alloc_function(GUINT size,int usage)
{
return 0;
}
GUINT _shared_buffer_alloc_data_function(const void * pdata,GUINT size,int usage)
{
return (GUINT)pdata;
}
GUINT _shared_buffer_realloc_function(GUINT buffer_handle,GUINT oldsize,int old_usage,GUINT newsize,int new_usage)
{
return 0;
}
void _shared_buffer_free_function(GUINT buffer_handle,GUINT size)
{
}
//!** Buffer manager operations
void gim_create_buffer_manager(GBUFFER_MANAGER_PROTOTYPE * prototype,GUINT buffer_manager_id)
{
GBUFFER_MANAGER_DATA * bm_data;
bm_data = &g_buffer_managers[buffer_manager_id];
if(bm_data->m_active==0)
{
if(g_buffer_managers_count<=buffer_manager_id)
{
g_buffer_managers_count = buffer_manager_id+1;
}
}
else
{
gim_destroy_buffer_manager(buffer_manager_id);
}
bm_data->m_active = 1;
//CREATE ARRAYS
GIM_DYNARRAY_CREATE(GBUFFER_DATA,bm_data->m_buffer_array,G_ARRAY_GROW_SIZE);
GIM_DYNARRAY_CREATE(GUINT,bm_data->m_free_positions,G_ARRAY_GROW_SIZE);
//INIT PROTOTYPE
bm_data->m_prototype.alloc_data_fn = prototype->alloc_data_fn;
bm_data->m_prototype.alloc_fn = prototype->alloc_fn;
bm_data->m_prototype.copy_buffers_fn = prototype->copy_buffers_fn;
bm_data->m_prototype.download_from_buffer_fn = prototype->download_from_buffer_fn;
bm_data->m_prototype.free_fn = prototype->free_fn;
bm_data->m_prototype.lock_buffer_fn = prototype->lock_buffer_fn;
bm_data->m_prototype.realloc_fn = prototype->realloc_fn;
bm_data->m_prototype.unlock_buffer_fn = prototype->unlock_buffer_fn;
bm_data->m_prototype.upload_to_buffer_fn = prototype->upload_to_buffer_fn;
}
GUINT gim_get_buffer_manager_count()
{
return g_buffer_managers_count;
}
void gim_destroy_buffer_manager(GUINT buffer_manager_id)
{
GBUFFER_MANAGER_DATA * bm_data;
gim_get_buffer_manager_data(buffer_manager_id,&bm_data);
if(bm_data == 0) return;
//Destroy all buffers
GBUFFER_DATA * buffers = GIM_DYNARRAY_POINTER(GBUFFER_DATA,bm_data->m_buffer_array);
GUINT i, buffer_count = bm_data->m_buffer_array.m_size;
for (i=0;i<buffer_count ;i++ )
{
if(buffers[i].m_buffer_handle!=0) //Is active
{
// free handle
bm_data->m_prototype.free_fn(buffers[i].m_buffer_handle,buffers[i].m_size);
}
}
//destroy buffer array
GIM_DYNARRAY_DESTROY(bm_data->m_buffer_array);
//destroy free positions
GIM_DYNARRAY_DESTROY(bm_data->m_free_positions);
//Mark as innactive
bm_data->m_active = 0;
}
void gim_get_buffer_manager_data(GUINT buffer_manager_id,GBUFFER_MANAGER_DATA ** pbm_data)
{
GBUFFER_MANAGER_DATA * bm_data;
bm_data = &g_buffer_managers[buffer_manager_id];
if(bm_data->m_active==0)
{
*pbm_data = 0;
}
else
{
*pbm_data = bm_data;
}
}
void gim_init_buffer_managers()
{
GUINT i;
for (i=0;i<MAX_BUFFER_MANAGERS;i++)
{
g_buffer_managers[i].m_active = 0;
g_buffer_managers[i].m_buffer_array.m_pdata = 0;
g_buffer_managers[i].m_buffer_array.m_reserve_size = 0;
g_buffer_managers[i].m_buffer_array.m_size = 0;
g_buffer_managers[i].m_free_positions.m_pdata = 0;
g_buffer_managers[i].m_free_positions.m_reserve_size = 0;
g_buffer_managers[i].m_free_positions.m_size = 0;
}
g_buffer_managers_count = 0;
// Add the two most important buffer managers
GBUFFER_MANAGER_PROTOTYPE prototype;
//add system buffer manager
prototype.alloc_data_fn = _system_buffer_alloc_data_function;
prototype.alloc_fn = _system_buffer_alloc_function;
prototype.copy_buffers_fn = _system_copy_buffers_function;
prototype.download_from_buffer_fn = _system_download_from_buffer_function;
prototype.free_fn = _system_buffer_free_function;
prototype.lock_buffer_fn = _system_lock_buffer_function;
prototype.realloc_fn = _system_buffer_realloc_function;
prototype.unlock_buffer_fn = _system_unlock_buffer_function;
prototype.upload_to_buffer_fn = _system_upload_to_buffer_function;
gim_create_buffer_manager(&prototype,G_BUFFER_MANAGER_SYSTEM );
//add zhared buffer manager
prototype.alloc_data_fn = _shared_buffer_alloc_data_function;
prototype.alloc_fn = _shared_buffer_alloc_function;
prototype.free_fn = _shared_buffer_free_function;
gim_create_buffer_manager(&prototype,G_BUFFER_MANAGER_SHARED);
}
void gim_terminate_buffer_managers()
{
GUINT i;
for (i=0;i<g_buffer_managers_count;i++)
{
gim_destroy_buffer_manager(i);
}
g_buffer_managers_count = 0;
}
//!** Nuffer operations
void GET_AVALIABLE_BUFFER_ID(GBUFFER_MANAGER_DATA * buffer_manager, GUINT & buffer_id)
{
if(buffer_manager->m_free_positions.m_size>0)\
{
GUINT * _pointer = GIM_DYNARRAY_POINTER(GUINT,buffer_manager->m_free_positions);
buffer_id = _pointer[buffer_manager->m_free_positions.m_size-1];
GIM_DYNARRAY_POP_ITEM(buffer_manager->m_free_positions);
}
else
{
buffer_id = buffer_manager->m_buffer_array.m_size;
GIM_DYNARRAY_PUSH_EMPTY(GBUFFER_DATA,buffer_manager->m_buffer_array);
}
}
GINT _validate_buffer_id(GBUFFER_ID * buffer_id,GBUFFER_DATA ** ppbuffer,GBUFFER_MANAGER_DATA ** pbm_data)
{
VALIDATE_BUFFER_ID_PT(buffer_id)
*ppbuffer = pbuffer;
*pbm_data = bm_data;
return G_BUFFER_OP_SUCCESS;
}
GUINT gim_create_buffer(
GUINT buffer_manager_id,
GUINT buffer_size,
int usage,
GBUFFER_ID * buffer_id)
{
VALIDATE_BUFFER_MANAGER(buffer_manager_id)
GUINT newbufferhandle = bm_data->m_prototype.alloc_fn(buffer_size,usage);
if(newbufferhandle==0) return G_BUFFER_OP_INVALID;
GET_AVALIABLE_BUFFER_ID(bm_data,buffer_id->m_buffer_id);
buffer_id->m_buffer_manager_id = buffer_manager_id;
GBUFFER_DATA * pbuffer = GIM_DYNARRAY_POINTER(GBUFFER_DATA,bm_data->m_buffer_array);
pbuffer += buffer_id->m_buffer_id ;
pbuffer->m_buffer_handle = newbufferhandle;
pbuffer->m_size = buffer_size;
pbuffer->m_usage = usage;
pbuffer->m_lock_count = 0;
pbuffer->m_refcount = 0;
pbuffer->m_mapped_pointer = 0;
//set shadow buffer if needed
if(usage == G_MU_STATIC_READ ||
usage == G_MU_STATIC_READ_DYNAMIC_WRITE||
usage == G_MU_STATIC_READ_DYNAMIC_WRITE_COPY)
{
gim_create_common_buffer(buffer_size,&pbuffer->m_shadow_buffer);
}
else
{
pbuffer->m_shadow_buffer.m_buffer_id = G_UINT_INFINITY;
pbuffer->m_shadow_buffer.m_buffer_manager_id = G_UINT_INFINITY;
}
return G_BUFFER_OP_SUCCESS;
}
GUINT gim_create_buffer_from_data(
GUINT buffer_manager_id,
const void * pdata,
GUINT buffer_size,
int usage,
GBUFFER_ID * buffer_id)
{
VALIDATE_BUFFER_MANAGER(buffer_manager_id)
GUINT newbufferhandle = bm_data->m_prototype.alloc_data_fn(pdata,buffer_size,usage);
if(newbufferhandle==0) return G_BUFFER_OP_INVALID;
GET_AVALIABLE_BUFFER_ID(bm_data,buffer_id->m_buffer_id);
buffer_id->m_buffer_manager_id = buffer_manager_id;
GBUFFER_DATA * pbuffer = GIM_DYNARRAY_POINTER(GBUFFER_DATA,bm_data->m_buffer_array);
pbuffer += buffer_id->m_buffer_id ;
pbuffer->m_buffer_handle = newbufferhandle;
pbuffer->m_size = buffer_size;
pbuffer->m_usage = usage;
pbuffer->m_lock_count = 0;
pbuffer->m_mapped_pointer = 0;
pbuffer->m_refcount = 0;
//set shadow buffer if needed
if(usage == G_MU_STATIC_READ ||
usage == G_MU_STATIC_READ_DYNAMIC_WRITE||
usage == G_MU_STATIC_READ_DYNAMIC_WRITE_COPY)
{
gim_create_common_buffer_from_data(pdata,buffer_size,&pbuffer->m_shadow_buffer);
}
else
{
pbuffer->m_shadow_buffer.m_buffer_id = G_UINT_INFINITY;
pbuffer->m_shadow_buffer.m_buffer_manager_id = G_UINT_INFINITY;
}
return G_BUFFER_OP_SUCCESS;
}
GUINT gim_create_common_buffer(GUINT buffer_size, GBUFFER_ID * buffer_id)
{
return gim_create_buffer(G_BUFFER_MANAGER_SYSTEM,buffer_size,G_MU_DYNAMIC_READ_WRITE,buffer_id);
}
GUINT gim_create_common_buffer_from_data(
const void * pdata, GUINT buffer_size, GBUFFER_ID * buffer_id)
{
return gim_create_buffer_from_data(G_BUFFER_MANAGER_SYSTEM,pdata,buffer_size,G_MU_DYNAMIC_READ_WRITE,buffer_id);
}
GUINT gim_create_shared_buffer_from_data(
const void * pdata, GUINT buffer_size, GBUFFER_ID * buffer_id)
{
return gim_create_buffer_from_data(G_BUFFER_MANAGER_SHARED,pdata,buffer_size,G_MU_DYNAMIC_READ_WRITE,buffer_id);
}
GINT gim_buffer_realloc(GBUFFER_ID * buffer_id,GUINT newsize)
{
VALIDATE_BUFFER_ID_PT(buffer_id)
if(pbuffer->m_lock_count>0) return G_BUFFER_OP_INVALID;
GUINT newhandle = bm_data->m_prototype.realloc_fn(pbuffer->m_buffer_handle,pbuffer->m_size,pbuffer->m_usage,newsize,pbuffer->m_usage);
if(newhandle==0) return G_BUFFER_OP_INVALID;
pbuffer->m_buffer_handle = newhandle;
//realloc shadow buffer if any
gim_buffer_realloc(&pbuffer->m_shadow_buffer,newsize);
return G_BUFFER_OP_SUCCESS;
}
GINT gim_buffer_add_ref(GBUFFER_ID * buffer_id)
{
VALIDATE_BUFFER_ID_PT(buffer_id)
pbuffer->m_refcount++;
return G_BUFFER_OP_SUCCESS;
}
GINT gim_buffer_free(GBUFFER_ID * buffer_id)
{
VALIDATE_BUFFER_ID_PT(buffer_id)
if(pbuffer->m_lock_count>0) return G_BUFFER_OP_INVALID;
if(pbuffer->m_refcount>0) pbuffer->m_refcount--;
if(pbuffer->m_refcount>0) return G_BUFFER_OP_STILLREFCOUNTED;
bm_data->m_prototype.free_fn(pbuffer->m_buffer_handle,pbuffer->m_size);
//destroy shadow buffer if needed
gim_buffer_free(&pbuffer->m_shadow_buffer);
// Obtain a free slot index for a new buffer
GIM_DYNARRAY_PUSH_ITEM(GUINT,bm_data->m_free_positions,buffer_id->m_buffer_id);
pbuffer->m_buffer_handle = 0;
pbuffer->m_size = 0;
pbuffer->m_shadow_buffer.m_buffer_id = G_UINT_INFINITY;
pbuffer->m_shadow_buffer.m_buffer_manager_id = G_UINT_INFINITY;
return G_BUFFER_OP_SUCCESS;
}
GINT gim_lock_buffer(GBUFFER_ID * buffer_id,int access,char ** map_pointer)
{
VALIDATE_BUFFER_ID_PT(buffer_id)
if(pbuffer->m_lock_count>0)
{
if(pbuffer->m_access!=access) return G_BUFFER_OP_INVALID;
pbuffer->m_lock_count++;
*map_pointer = pbuffer->m_mapped_pointer;
return G_BUFFER_OP_SUCCESS;
}
pbuffer->m_access = access;
GUINT result;
if(pbuffer->m_usage==G_MU_STATIC_WRITE)
{
*map_pointer = 0;///no access
return G_BUFFER_OP_INVALID;
}
else if(pbuffer->m_usage==G_MU_STATIC_READ)
{
if(pbuffer->m_access == G_MA_READ_ONLY)
{
result = gim_lock_buffer(&pbuffer->m_shadow_buffer,access,map_pointer);
if(result!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
pbuffer->m_mapped_pointer = *map_pointer;
pbuffer->m_lock_count++;
}
else
{
*map_pointer = 0;
return G_BUFFER_OP_INVALID;
}
}
else if(pbuffer->m_usage==G_MU_STATIC_READ_DYNAMIC_WRITE)
{
if(pbuffer->m_access == G_MA_READ_ONLY)
{
result = gim_lock_buffer(&pbuffer->m_shadow_buffer,access,map_pointer);
if(result!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
pbuffer->m_mapped_pointer = *map_pointer;
pbuffer->m_lock_count++;
}
else if(pbuffer->m_access == G_MA_WRITE_ONLY)
{
pbuffer->m_mapped_pointer = bm_data->m_prototype.lock_buffer_fn(pbuffer->m_buffer_handle,access);
*map_pointer = pbuffer->m_mapped_pointer;
pbuffer->m_lock_count++;
}
else if(pbuffer->m_access == G_MA_READ_WRITE)
{
*map_pointer = 0;
return G_BUFFER_OP_INVALID;
}
}
else if(pbuffer->m_usage==G_MU_STATIC_READ_DYNAMIC_WRITE_COPY)
{
result = gim_lock_buffer(&pbuffer->m_shadow_buffer,access,map_pointer);
if(result!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
pbuffer->m_mapped_pointer = *map_pointer;
pbuffer->m_lock_count++;
}
else if(pbuffer->m_usage==G_MU_STATIC_WRITE_DYNAMIC_READ)
{
if(pbuffer->m_access == G_MA_READ_ONLY)
{
pbuffer->m_mapped_pointer = bm_data->m_prototype.lock_buffer_fn(pbuffer->m_buffer_handle,access);
*map_pointer = pbuffer->m_mapped_pointer;
pbuffer->m_lock_count++;
}
else
{
*map_pointer = 0;
return G_BUFFER_OP_INVALID;
}
}
else if(pbuffer->m_usage==G_MU_DYNAMIC_READ_WRITE)
{
pbuffer->m_mapped_pointer = bm_data->m_prototype.lock_buffer_fn(pbuffer->m_buffer_handle,access);
*map_pointer = pbuffer->m_mapped_pointer;
pbuffer->m_lock_count++;
}
return G_BUFFER_OP_SUCCESS;
}
GINT gim_unlock_buffer(GBUFFER_ID * buffer_id)
{
VALIDATE_BUFFER_ID_PT(buffer_id)
if(pbuffer->m_lock_count==0) return G_BUFFER_OP_INVALID;
if(pbuffer->m_lock_count>1)
{
pbuffer->m_lock_count--;
return G_BUFFER_OP_SUCCESS;
}
GUINT result;
if(pbuffer->m_usage==G_MU_STATIC_WRITE)
{
pbuffer->m_mapped_pointer = 0;
pbuffer->m_lock_count=0;
return G_BUFFER_OP_INVALID;
}
else if(pbuffer->m_usage==G_MU_STATIC_READ)
{
if(pbuffer->m_access == G_MA_READ_ONLY)
{
result = gim_unlock_buffer(&pbuffer->m_shadow_buffer);
if(result!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
pbuffer->m_mapped_pointer = 0;
pbuffer->m_lock_count=0;
}
else
{
pbuffer->m_mapped_pointer = 0;
pbuffer->m_lock_count=0;
return G_BUFFER_OP_INVALID;
}
}
else if(pbuffer->m_usage==G_MU_STATIC_READ_DYNAMIC_WRITE)
{
if(pbuffer->m_access == G_MA_READ_ONLY)
{
result = gim_unlock_buffer(&pbuffer->m_shadow_buffer);
if(result!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
pbuffer->m_mapped_pointer = 0;
pbuffer->m_lock_count=0;
}
else if(pbuffer->m_access == G_MA_WRITE_ONLY)
{
bm_data->m_prototype.unlock_buffer_fn(pbuffer->m_buffer_handle);
pbuffer->m_mapped_pointer = 0;
pbuffer->m_lock_count=0;
}
else if(pbuffer->m_access == G_MA_READ_WRITE)
{
pbuffer->m_mapped_pointer = 0;
pbuffer->m_lock_count=0;
return G_BUFFER_OP_INVALID;
}
}
else if(pbuffer->m_usage==G_MU_STATIC_READ_DYNAMIC_WRITE_COPY)
{
result = gim_unlock_buffer(&pbuffer->m_shadow_buffer);
if(result!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
pbuffer->m_mapped_pointer = 0;
pbuffer->m_lock_count=0;
if(pbuffer->m_access == G_MA_WRITE_ONLY||pbuffer->m_access == G_MA_READ_WRITE)
{
gim_copy_buffers(&pbuffer->m_shadow_buffer,0,buffer_id,0,pbuffer->m_size);
}
}
else if(pbuffer->m_usage==G_MU_STATIC_WRITE_DYNAMIC_READ)
{
if(pbuffer->m_access == G_MA_READ_ONLY)
{
bm_data->m_prototype.unlock_buffer_fn(pbuffer->m_buffer_handle);
pbuffer->m_mapped_pointer = 0;
pbuffer->m_lock_count=0;
}
else
{
pbuffer->m_mapped_pointer = 0;
pbuffer->m_lock_count=0;
return G_BUFFER_OP_INVALID;
}
}
else if(pbuffer->m_usage==G_MU_DYNAMIC_READ_WRITE)
{
bm_data->m_prototype.unlock_buffer_fn(pbuffer->m_buffer_handle);
pbuffer->m_mapped_pointer = 0;
pbuffer->m_lock_count=0;
}
return G_BUFFER_OP_SUCCESS;
}
GINT gim_get_buffer_size(GBUFFER_ID * buffer_id,GUINT * buffer_size)
{
VALIDATE_BUFFER_ID_PT(buffer_id)
*buffer_size = pbuffer->m_size;
return G_BUFFER_OP_SUCCESS;
}
GINT gim_get_buffer_is_locked(GBUFFER_ID * buffer_id,GUINT * lock_count)
{
VALIDATE_BUFFER_ID_PT(buffer_id)
*lock_count = pbuffer->m_lock_count;
return G_BUFFER_OP_SUCCESS;
}
GINT gim_download_from_buffer(
GBUFFER_ID * buffer_id,
GUINT source_pos,
void * destdata,
GUINT copysize)
{
VALIDATE_BUFFER_ID_PT(buffer_id)
bm_data->m_prototype.download_from_buffer_fn(
pbuffer->m_buffer_handle,source_pos,destdata,copysize);
return G_BUFFER_OP_SUCCESS;
}
GINT gim_upload_to_buffer(
GBUFFER_ID * buffer_id,
GUINT dest_pos,
void * sourcedata,
GUINT copysize)
{
VALIDATE_BUFFER_ID_PT(buffer_id)
bm_data->m_prototype.upload_to_buffer_fn(
pbuffer->m_buffer_handle,dest_pos,sourcedata,copysize);
return G_BUFFER_OP_SUCCESS;
}
GINT gim_copy_buffers(
GBUFFER_ID * source_buffer_id,
GUINT source_pos,
GBUFFER_ID * dest_buffer_id,
GUINT dest_pos,
GUINT copysize)
{
GBUFFER_MANAGER_DATA * bm_data1,* bm_data2;
GBUFFER_DATA * pbuffer1, * pbuffer2;
void * tempdata;
if(_validate_buffer_id(source_buffer_id,&pbuffer1,&bm_data1)!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
if(_validate_buffer_id(dest_buffer_id,&pbuffer2,&bm_data2)!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
if((source_buffer_id->m_buffer_manager_id == dest_buffer_id->m_buffer_manager_id)||
(source_buffer_id->m_buffer_manager_id == G_BUFFER_MANAGER_SYSTEM && dest_buffer_id->m_buffer_manager_id == G_BUFFER_MANAGER_SHARED)||
(source_buffer_id->m_buffer_manager_id == G_BUFFER_MANAGER_SHARED && dest_buffer_id->m_buffer_manager_id == G_BUFFER_MANAGER_SYSTEM)
)
{//smooth copy
bm_data1->m_prototype.copy_buffers_fn(pbuffer1->m_buffer_handle,source_pos,pbuffer2->m_buffer_handle,dest_pos,copysize);
}
else if(source_buffer_id->m_buffer_manager_id == G_BUFFER_MANAGER_SYSTEM || source_buffer_id->m_buffer_manager_id == G_BUFFER_MANAGER_SHARED)
{
//hard copy
tempdata = (void *)pbuffer1->m_buffer_handle;
//upload data
bm_data2->m_prototype.upload_to_buffer_fn(pbuffer2->m_buffer_handle,dest_pos,
tempdata,
copysize);
}
else
{
//very hard copy
void * tempdata = gim_alloc(copysize);
//download data
bm_data1->m_prototype.download_from_buffer_fn(pbuffer1->m_buffer_handle,source_pos,
tempdata,
copysize);
//upload data
bm_data2->m_prototype.upload_to_buffer_fn(pbuffer2->m_buffer_handle,dest_pos,
tempdata,
copysize);
//delete temp buffer
gim_free(tempdata,copysize);
}
return G_BUFFER_OP_SUCCESS;
}
GINT gim_buffer_array_lock(GBUFFER_ARRAY * array_data, int access)
{
if(array_data->m_buffer_data != 0) return G_BUFFER_OP_SUCCESS;
GINT result = gim_lock_buffer(&array_data->m_buffer_id,access,&array_data->m_buffer_data);
if(result!= G_BUFFER_OP_SUCCESS) return result;
array_data->m_buffer_data += array_data->m_byte_offset;
return result;
}
GINT gim_buffer_array_unlock(GBUFFER_ARRAY * array_data)
{
if(array_data->m_buffer_data == 0) return G_BUFFER_OP_SUCCESS;
GINT result = gim_unlock_buffer(&array_data->m_buffer_id);
if(result!= G_BUFFER_OP_SUCCESS) return result;
array_data->m_buffer_data = 0;
return result;
}
void gim_buffer_array_copy_ref(GBUFFER_ARRAY * source_data,GBUFFER_ARRAY * dest_data)
{
dest_data->m_buffer_id.m_buffer_id = source_data->m_buffer_id.m_buffer_id;
dest_data->m_buffer_id.m_buffer_manager_id = source_data->m_buffer_id.m_buffer_manager_id;
dest_data->m_buffer_data = 0;
dest_data->m_byte_stride = source_data->m_byte_stride;
dest_data->m_byte_offset = source_data->m_byte_offset;
dest_data->m_element_count = source_data->m_element_count;
gim_buffer_add_ref(&dest_data->m_buffer_id);
}
void gim_buffer_array_copy_value(GBUFFER_ARRAY * source_data,GBUFFER_ARRAY * dest_data, GUINT buffer_manager_id,int usage)
{
//Create new buffer
GUINT buffsize = source_data->m_element_count*source_data->m_byte_stride;
gim_create_buffer(buffer_manager_id,buffsize,usage,&dest_data->m_buffer_id);
//copy ref data
dest_data->m_buffer_data = 0;
dest_data->m_byte_stride = source_data->m_byte_stride;
dest_data->m_byte_offset = 0;
dest_data->m_element_count = source_data->m_element_count;
gim_buffer_add_ref(&dest_data->m_buffer_id);
//copy buffers
gim_copy_buffers(&source_data->m_buffer_id,source_data->m_byte_offset,&dest_data->m_buffer_id,0,buffsize);
}

View File

@@ -1,329 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. 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.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.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, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "GIMPACT/gim_trimesh.h"
#define FABS(x) (float(fabs(x))) /* implement as is fastest on your machine */
/* some macros */
#define CLASSIFY_TRIPOINTS_BY_FACE(v1,v2,v3,faceplane,out_of_face)\
{ \
_distances[0] = DISTANCE_PLANE_POINT(faceplane,v1);\
_distances[1] = _distances[0] * DISTANCE_PLANE_POINT(faceplane,v2);\
_distances[2] = _distances[0] * DISTANCE_PLANE_POINT(faceplane,v3); \
if(_distances[1]>0.0f && _distances[2]>0.0f)\
{\
out_of_face = 1;\
}\
else\
{\
out_of_face = 0;\
}\
}\
#define CLASSIFY_TRIPOINTS_BY_PLANE(v1,v2,v3,faceplane,out_of_face)\
{ \
_distances[0] = DISTANCE_PLANE_POINT(faceplane,v1);\
_distances[1] = DISTANCE_PLANE_POINT(faceplane,v2);\
_distances[2] = DISTANCE_PLANE_POINT(faceplane,v3); \
if(_distances[0]<=0.0f || _distances[1]<=0.0f || _distances[2]<=0.0f)\
{\
out_of_face = 0;\
}\
else\
{\
out_of_face = 1;\
}\
}\
/* sort so that a<=b */
#define SORT(a,b) \
if(a>b) \
{ \
float c; \
c=a; \
a=b; \
b=c; \
}
/* this edge to edge test is based on Franlin Antonio's gem:
"Faster Line Segment Intersection", in Graphics Gems III,
pp. 199-202 */
#define EDGE_EDGE_TEST(V0,U0,U1) \
Bx=U0[i0]-U1[i0]; \
By=U0[i1]-U1[i1]; \
Cx=V0[i0]-U0[i0]; \
Cy=V0[i1]-U0[i1]; \
f=Ay*Bx-Ax*By; \
d=By*Cx-Bx*Cy; \
if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f)) \
{ \
e=Ax*Cy-Ay*Cx; \
if(f>0) \
{ \
if(e>=0 && e<=f) return 1; \
} \
else \
{ \
if(e<=0 && e>=f) return 1; \
} \
}
#define EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2) \
{ \
float Ax,Ay,Bx,By,Cx,Cy,e,d,f; \
Ax=V1[i0]-V0[i0]; \
Ay=V1[i1]-V0[i1]; \
/* test edge U0,U1 against V0,V1 */ \
EDGE_EDGE_TEST(V0,U0,U1); \
/* test edge U1,U2 against V0,V1 */ \
EDGE_EDGE_TEST(V0,U1,U2); \
/* test edge U2,U1 against V0,V1 */ \
EDGE_EDGE_TEST(V0,U2,U0); \
}
#define POINT_IN_TRI(V0,U0,U1,U2) \
{ \
float a,b,c,d0,d1,d2; \
/* is T1 completly inside T2? */ \
/* check if V0 is inside tri(U0,U1,U2) */ \
a=U1[i1]-U0[i1]; \
b=-(U1[i0]-U0[i0]); \
c=-a*U0[i0]-b*U0[i1]; \
d0=a*V0[i0]+b*V0[i1]+c; \
\
a=U2[i1]-U1[i1]; \
b=-(U2[i0]-U1[i0]); \
c=-a*U1[i0]-b*U1[i1]; \
d1=a*V0[i0]+b*V0[i1]+c; \
\
a=U0[i1]-U2[i1]; \
b=-(U0[i0]-U2[i0]); \
c=-a*U2[i0]-b*U2[i1]; \
d2=a*V0[i0]+b*V0[i1]+c; \
if(d0*d1>0.0) \
{ \
if(d0*d2>0.0) return 1; \
} \
}
int coplanar_tri_tri(GIM_TRIANGLE_DATA *tri1,
GIM_TRIANGLE_DATA *tri2)
{
short i0,i1;
/* first project onto an axis-aligned plane, that maximizes the area */
/* of the triangles, compute indices: i0,i1. */
PLANE_MINOR_AXES(tri1->m_planes.m_planes[0], i0, i1);
/* test all edges of triangle 1 against the edges of triangle 2 */
EDGE_AGAINST_TRI_EDGES(tri1->m_vertices[0],tri1->m_vertices[1],tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2]);
EDGE_AGAINST_TRI_EDGES(tri1->m_vertices[1],tri1->m_vertices[2],tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2]);
EDGE_AGAINST_TRI_EDGES(tri1->m_vertices[2],tri1->m_vertices[0],tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2]);
/* finally, test if tri1 is totally contained in tri2 or vice versa */
/*POINT_IN_HULL(tri1->m_vertices[0],(&tri2->m_planes.m_planes[1]),3,i0);
if(i0==0) return 1;
POINT_IN_HULL(tri2->m_vertices[0],(&tri1->m_planes.m_planes[1]),3,i0);
if(i0==0) return 1;*/
POINT_IN_TRI(tri1->m_vertices[0],tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2])
POINT_IN_TRI(tri2->m_vertices[0],tri1->m_vertices[0],tri1->m_vertices[1],tri1->m_vertices[2])
return 0;
}
#define NEWCOMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,A,B,C,X0,X1) \
{ \
if(D0D1>0.0f) \
{ \
/* here we know that D0D2<=0.0 */ \
/* that is D0, D1 are on the same side, D2 on the other or on the plane */ \
A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
} \
else if(D0D2>0.0f)\
{ \
/* here we know that d0d1<=0.0 */ \
A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
} \
else if(D1*D2>0.0f || D0!=0.0f) \
{ \
/* here we know that d0d1<=0.0 or that D0!=0.0 */ \
A=VV0; B=(VV1-VV0)*D0; C=(VV2-VV0)*D0; X0=D0-D1; X1=D0-D2; \
} \
else if(D1!=0.0f) \
{ \
A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
} \
else if(D2!=0.0f) \
{ \
A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
} \
else \
{ \
/* triangles are coplanar */ \
return coplanar_tri_tri(tri1,tri2); \
} \
}\
int gim_triangle_triangle_overlap_fast(
GIM_TRIANGLE_DATA *tri1,
GIM_TRIANGLE_DATA *tri2)
{
vec3f _distances;
char out_of_face;
CLASSIFY_TRIPOINTS_BY_FACE(tri1->m_vertices[0],tri1->m_vertices[1],tri1->m_vertices[2],tri2->m_planes.m_planes[0],out_of_face);
if(out_of_face==1) return 0;
CLASSIFY_TRIPOINTS_BY_PLANE(tri2->m_vertices[0],tri2->m_vertices[1],
tri2->m_vertices[2],tri1->m_planes.m_planes[0],out_of_face);
if(out_of_face==1) return 0;
/*vec3f _points[3];
VEC_COPY(_points[0],tri2->m_vertices[0]);
VEC_COPY(_points[1],tri2->m_vertices[1]);
VEC_COPY(_points[2],tri2->m_vertices[2]);
CLASSIFY_TRIPOINTS_BY_FACE(_points[0],_points[1],_points[2],tri1->m_planes.m_planes[0],out_of_face);
if(out_of_face==1) return 0;
CLASSIFY_TRIPOINTS_BY_PLANE(_points[0],_points[1],_points[2],tri1->m_planes.m_planes[1],out_of_face);
if(out_of_face==1) return 0;
CLASSIFY_TRIPOINTS_BY_PLANE(_points[0],_points[1],_points[2],tri1->m_planes.m_planes[2],out_of_face);
if(out_of_face==1) return 0;
CLASSIFY_TRIPOINTS_BY_PLANE(_points[0],_points[1],_points[2],tri1->m_planes.m_planes[3],out_of_face);
if(out_of_face==1) return 0;
return 1;*/
short i0,i1;
/* first project onto an axis-aligned plane, that maximizes the area */
/* of the triangles, compute indices: i0,i1. */
PLANE_MINOR_AXES(tri2->m_planes.m_planes[0], i0, i1);
/* test all edges of triangle 1 against the edges of triangle 2 */
EDGE_AGAINST_TRI_EDGES(tri1->m_vertices[0],tri1->m_vertices[1],tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2]);
EDGE_AGAINST_TRI_EDGES(tri1->m_vertices[1],tri1->m_vertices[2],tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2]);
EDGE_AGAINST_TRI_EDGES(tri1->m_vertices[2],tri1->m_vertices[0],tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2]);
/* finally, test if tri1 is totally contained in tri2 or vice versa */
/*POINT_IN_HULL(tri1->m_vertices[0],(&tri2->m_planes.m_planes[1]),3,i0);
if(i0==0) return 1;
POINT_IN_HULL(tri2->m_vertices[0],(&tri1->m_planes.m_planes[1]),3,i0);
if(i0==0) return 1;*/
POINT_IN_TRI(tri1->m_vertices[0],tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2])
POINT_IN_TRI(tri2->m_vertices[0],tri1->m_vertices[0],tri1->m_vertices[1],tri1->m_vertices[2])
return 0;
}
int gim_triangle_triangle_overlap(
GIM_TRIANGLE_DATA *tri1,
GIM_TRIANGLE_DATA *tri2)
{
vec3f _distances;
char out_of_face;
CLASSIFY_TRIPOINTS_BY_FACE(tri1->m_vertices[0],tri1->m_vertices[1],tri1->m_vertices[2],tri2->m_planes.m_planes[0],out_of_face);
if(out_of_face==1) return 0;
CLASSIFY_TRIPOINTS_BY_FACE(tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2],tri1->m_planes.m_planes[0],out_of_face);
if(out_of_face==1) return 0;
float du0=0,du1=0,du2=0,dv0=0,dv1=0,dv2=0;
float D[3];
float isect1[2], isect2[2];
float du0du1=0,du0du2=0,dv0dv1=0,dv0dv2=0;
short index;
float vp0,vp1,vp2;
float up0,up1,up2;
float bb,cc,max;
/* compute direction of intersection line */
VEC_CROSS(D,tri1->m_planes.m_planes[0],tri2->m_planes.m_planes[0]);
/* compute and index to the largest component of D */
max=(float)FABS(D[0]);
index=0;
bb=(float)FABS(D[1]);
cc=(float)FABS(D[2]);
if(bb>max) max=bb,index=1;
if(cc>max) max=cc,index=2;
/* this is the simplified projection onto L*/
vp0= tri1->m_vertices[0][index];
vp1= tri1->m_vertices[1][index];
vp2= tri1->m_vertices[2][index];
up0= tri2->m_vertices[0][index];
up1= tri2->m_vertices[1][index];
up2= tri2->m_vertices[2][index];
/* compute interval for triangle 1 */
float a,b,c,x0,x1;
NEWCOMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1);
/* compute interval for triangle 2 */
float d,e,f,y0,y1;
NEWCOMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1);
float xx,yy,xxyy,tmp;
xx=x0*x1;
yy=y0*y1;
xxyy=xx*yy;
tmp=a*xxyy;
isect1[0]=tmp+b*x1*yy;
isect1[1]=tmp+c*x0*yy;
tmp=d*xxyy;
isect2[0]=tmp+e*xx*y1;
isect2[1]=tmp+f*xx*y0;
SORT(isect1[0],isect1[1]);
SORT(isect2[0],isect2[1]);
if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) return 0;
return 1;
}

View File

@@ -1,707 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. 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.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.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, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "GIMPACT/gim_trimesh.h"
#include "assert.h"
GUINT gim_trimesh_get_triangle_count(GIM_TRIMESH * trimesh)
{
return gim_trimesh_data_get_triangle_count(trimesh->m_trimesh_data_handle);
}
GUINT gim_trimesh_get_vertex_count(GIM_TRIMESH * trimesh)
{
return gim_trimesh_data_get_vertex_count(trimesh->m_trimesh_data_handle);
}
GUINT gim_trimesh_get_bound_method(GIM_TRIMESH * trimesh)
{
if(gim_trimesh_data_has_bv_tree(trimesh->m_trimesh_data_handle) != 0) return G_TRIMESH_BOUND_AABB_TREE;
else if(trimesh->m_aabbset != 0) return G_TRIMESH_BOUND_AABB_SET;
return G_TRIMESH_BOUND_NONE;
}
#define LAZY_TRANSFORM_VERTEX(bitset,vec_index,transform,source_trimesh_data,dest_vert,temp_vert)\
{\
GUINT bit_eval;\
if(GIM_DYNARRAY_IS_VALID(bitset))\
{\
GIM_BITSET_GET(bitset,vec_index,bit_eval);\
if(bit_eval == 0)\
{\
gim_trimesh_data_get_vertex(source_trimesh_data,vec_index,vec);\
MAT_DOT_VEC_3X4(dest_vert,transform,temp_vert);\
}\
}\
}\
//! Fetch a single transformed vertex
/*!
\pre gim_trimesh_locks_work_data must be called before
*/
void gim_trimesh_get_vertex(GIM_TRIMESH * trimesh, GUINT vertex_index, vec3f vec)
{
if(trimesh->m_cache)
{
if(GIM_BUFFER_ARRAY_IS_VALID(trimesh->m_cache->m_transformed_vertex_buffer))
{
GREAL * transvecf = GIM_BUFFER_ARRAY_POINTER(GREAL,trimesh->m_cache->m_transformed_vertex_buffer,vertex_index);
LAZY_TRANSFORM_VERTEX(trimesh->m_cache->m_transformed_vertices_cache_bitset,vertex_index,trimesh->m_transform,trimesh->m_unlocked_trimesh_data,transvecf,vec);
VEC_COPY(vec,transvecf);
return;
}
}
if(gim_trimesh_has_tranform(trimesh))
{
vec3f vectemp;
gim_trimesh_data_get_vertex(trimesh->m_unlocked_trimesh_data,vertex_index,vectemp);
MAT_DOT_VEC_3X4(vec,trimesh->m_transform,vectemp);
return;
}
gim_trimesh_data_get_vertex(trimesh->m_unlocked_trimesh_data,vertex_index,vec);
}
void gim_trimesh_get_triangle_vertices_local(GIM_TRIMESH * trimesh, GUINT triangle_index,
vec3f v1,vec3f v2,vec3f v3)
{
vec3ui triangle_indices;
gim_trimesh_data_get_triangle_indices(
trimesh->m_unlocked_trimesh_data,triangle_index,triangle_indices);
gim_trimesh_data_get_vertex(trimesh->m_unlocked_trimesh_data,triangle_indices[0],v1);
gim_trimesh_data_get_vertex(trimesh->m_unlocked_trimesh_data,triangle_indices[1],v2);
gim_trimesh_data_get_vertex(trimesh->m_unlocked_trimesh_data,triangle_indices[2],v3);
}
void gim_trimesh_get_vertex_local(GIM_TRIMESH * trimesh, GUINT vertex_index, vec3f vec)
{
gim_trimesh_data_get_vertex(trimesh->m_unlocked_trimesh_data,vertex_index,vec);
}
void gim_trimesh_get_triangle_vertices(GIM_TRIMESH * trimesh, GUINT triangle_index, vec3f v1,vec3f v2,vec3f v3)
{
if(gim_trimesh_has_tranform(trimesh)==0)
{
gim_trimesh_get_triangle_vertices_local(trimesh,triangle_index,v1,v2,v3);
return;
}
vec3ui triangle_indices;
gim_trimesh_data_get_triangle_indices(
trimesh->m_unlocked_trimesh_data,triangle_index,triangle_indices);
if(trimesh->m_aabbset)
{
vec3f * vertices = GIM_BUFFER_ARRAY_POINTER(vec3f,trimesh->m_cache->m_transformed_vertex_buffer,0);
VEC_COPY(v1,vertices[triangle_indices[0]]);
VEC_COPY(v2,vertices[triangle_indices[1]]);
VEC_COPY(v3,vertices[triangle_indices[2]]);
return;
}
gim_trimesh_get_vertex(trimesh, triangle_indices[0], v1);
gim_trimesh_get_vertex(trimesh, triangle_indices[1], v2);
gim_trimesh_get_vertex(trimesh, triangle_indices[2], v3);
}
void gim_trimesh_initialize_cache(GIM_TRIMESH * trimesh)
{
trimesh->m_cache = (GIM_TRIMESH_CACHE *)gim_alloc(sizeof(GIM_TRIMESH_CACHE));
//Initializes the transformed vertices
if(gim_trimesh_has_tranform(trimesh))
{
gim_trimesh_data_get(trimesh->m_trimesh_data_handle,&trimesh->m_unlocked_trimesh_data );
//Create vertex buffer
gim_create_common_vertex_buffer(&trimesh->m_cache->m_transformed_vertex_buffer,
trimesh->m_unlocked_trimesh_data->m_source_vertex_buffer.m_element_count);
//Copy the vertex buffer
gim_copy_vertex_buffers(&trimesh->m_unlocked_trimesh_data->m_source_vertex_buffer,
trimesh->m_unlocked_trimesh_data->m_vertex_scalar_type,
&trimesh->m_cache->m_transformed_vertex_buffer,G_STYPE_REAL);
trimesh->m_cache->m_tranformed_scalar_type = G_STYPE_REAL;
trimesh->m_unlocked_trimesh_data = 0;
//Create vertices bitset
if(gim_trimesh_get_bound_method(trimesh)==G_TRIMESH_BOUND_AABB_TREE)
{
//Create the bitset
GIM_BITSET_CREATE_SIZED(trimesh->m_cache->m_transformed_vertices_cache_bitset,
trimesh->m_cache->m_transformed_vertex_buffer.m_element_count);
}
else
{
GIM_DYNARRAY_INVALIDATE(trimesh->m_cache->m_transformed_vertices_cache_bitset);
}
}
else
{
GIM_BUFFER_ARRAY_INVALIDATE(trimesh->m_cache->m_transformed_vertex_buffer);
GIM_DYNARRAY_INVALIDATE(trimesh->m_cache->m_transformed_vertices_cache_bitset);
}
GUINT facecount = gim_trimesh_get_triangle_count(trimesh);
//create the planes cache
GIM_DYNARRAY_CREATE_SIZED(GIM_TRIPLANES_CACHE,trimesh->m_cache->m_planes_cache_buffer,facecount);
//Create the bitset
GIM_BITSET_CREATE_SIZED(trimesh->m_cache->m_planes_cache_bitset,facecount);
}
void gim_trimesh_destroy_cache(GIM_TRIMESH * trimesh)
{
if(trimesh->m_cache==0) return;
if(trimesh->m_unlocked_trimesh_data != 0)
{
gim_trimesh_unlocks_work_data(trimesh);
}
GIM_DYNARRAY_DESTROY(trimesh->m_cache->m_planes_cache_buffer);
GIM_DYNARRAY_DESTROY(trimesh->m_cache->m_planes_cache_bitset);
if(GIM_BUFFER_ARRAY_IS_VALID(trimesh->m_cache->m_transformed_vertex_buffer))
{
GIM_BUFFER_ARRAY_DESTROY(trimesh->m_cache->m_transformed_vertex_buffer);
if(GIM_DYNARRAY_IS_VALID(trimesh->m_cache->m_transformed_vertices_cache_bitset))
{
GIM_DYNARRAY_DESTROY(trimesh->m_cache->m_transformed_vertices_cache_bitset);
}
}
gim_free(trimesh->m_cache,0);
trimesh->m_cache = 0;
}
void gim_trimesh_initialize_bound(GIM_TRIMESH * trimesh)
{
if(gim_trimesh_get_bound_method(trimesh)==G_TRIMESH_BOUND_NONE)
{
GUINT facecount = gim_trimesh_get_triangle_count(trimesh);
trimesh->m_aabbset = (GIM_AABB_SET *)gim_alloc(sizeof(GIM_AABB_SET));
gim_aabbset_alloc(trimesh->m_aabbset,facecount);
}
}
void gim_trimesh_destroy_bound(GIM_TRIMESH * trimesh)
{
if(trimesh->m_aabbset != 0)
{
gim_aabbset_destroy(trimesh->m_aabbset);
gim_free(trimesh->m_aabbset,0);
}
trimesh->m_aabbset = 0;
}
void gim_trimesh_create(GIM_TRIMESH * trimesh, GUINT trimesh_data_handle,
char apply_transform,char create_cache)
{
trimesh->m_mask = GIM_TRIMESH_NEED_UPDATE;//needs update
trimesh->m_trimesh_data_handle = trimesh_data_handle;
trimesh->m_unlocked_trimesh_data = 0;
gim_trimesh_data_inc_ref(trimesh->m_trimesh_data_handle);
trimesh->m_aabbset = 0;
trimesh->m_cache = 0;
if(apply_transform==1) trimesh->m_mask |= GIM_TRIMESH_APPLY_TRANSFORMATION;
gim_trimesh_initialize_bound(trimesh);
if(create_cache == 1 || gim_trimesh_get_bound_method(trimesh)==G_TRIMESH_BOUND_AABB_SET )
{
gim_trimesh_initialize_cache(trimesh);
}
//Callback is 0
trimesh->m_update_callback = 0;
//set to identity
IDENTIFY_MATRIX_4X4(trimesh->m_transform);
IDENTIFY_MATRIX_4X4(trimesh->m_inv_transform);
}
void gim_trimesh_create_from_arrays(GIM_TRIMESH * trimesh, GBUFFER_ARRAY * vertex_array,GUINT vertex_scalar_type, GBUFFER_ARRAY * triindex_array,GUINT index_scalar_type,
char apply_transform,char create_cache)
{
//Create mesh data
gim_trimesh_data_create_from_arrays(
&trimesh->m_trimesh_data_handle,vertex_array,vertex_scalar_type,triindex_array,index_scalar_type);
//Create
gim_trimesh_create(trimesh,trimesh->m_trimesh_data_handle,apply_transform,create_cache);
}
//! 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(GIM_TRIMESH * trimesh, vec3f * vertex_array, GUINT vertex_count,char copy_vertices, GUINT * triindex_array, GUINT triangle_count,char copy_indices,
char apply_transform,char create_cache)
{
//Create mesh data
gim_trimesh_data_create_from_array_data(
&trimesh->m_trimesh_data_handle,vertex_array,vertex_count,copy_vertices,
triindex_array, triangle_count,copy_indices);
//Create
gim_trimesh_create(trimesh,trimesh->m_trimesh_data_handle,
apply_transform,create_cache);
}
//! Clears auxiliary data and releases buffer arrays
void gim_trimesh_destroy(GIM_TRIMESH * trimesh)
{
gim_trimesh_destroy_cache(trimesh);
gim_trimesh_destroy_bound(trimesh);
//Release trimesh data
gim_trimesh_data_dec_ref(trimesh->m_trimesh_data_handle);
trimesh->m_trimesh_data_handle = 0;
}
//! 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,GIM_TRIMESH * dest_trimesh, char copy_by_reference,
char apply_transform,char create_cache)
{
if(copy_by_reference==1)
{
gim_trimesh_create(dest_trimesh,source_trimesh->m_trimesh_data_handle,
apply_transform,create_cache);
}
else
{
gim_trimesh_data_create_copy(source_trimesh->m_trimesh_data_handle,&dest_trimesh->m_trimesh_data_handle,0);
gim_trimesh_create(dest_trimesh,dest_trimesh->m_trimesh_data_handle,
apply_transform,create_cache);
}
}
void gim_trimesh_locks_work_data(GIM_TRIMESH * trimesh)
{
gim_trimesh_data_lock(trimesh->m_trimesh_data_handle,G_MA_READ_ONLY,&trimesh->m_unlocked_trimesh_data);
if(trimesh->m_cache)
{
if(GIM_BUFFER_ARRAY_IS_VALID(trimesh->m_cache->m_transformed_vertex_buffer))
{
gim_buffer_array_lock(&trimesh->m_cache->m_transformed_vertex_buffer,G_MA_READ_ONLY);
}
}
}
//! 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)
{
trimesh->m_unlocked_trimesh_data = 0;
gim_trimesh_data_unlock(trimesh->m_trimesh_data_handle);
if(trimesh->m_cache)
{
if(GIM_BUFFER_ARRAY_IS_VALID(trimesh->m_cache->m_transformed_vertex_buffer))
{
gim_buffer_array_unlock(&trimesh->m_cache->m_transformed_vertex_buffer);
}
}
}
//! Returns 1 if the m_transformed_vertex_buffer is a reply of m_source_vertex_buffer
char gim_trimesh_has_tranform(GIM_TRIMESH * trimesh)
{
if(trimesh->m_mask&GIM_TRIMESH_APPLY_TRANSFORMATION) 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;
}
//! Updates m_transformed_vertex_buffer
/*!
\pre m_transformed_vertex_buffer must be unlocked
*/
void gim_trimesh_update_vertices(GIM_TRIMESH * trimesh)
{
if(trimesh->m_cache == 0) return;
if(gim_trimesh_has_tranform(trimesh) == 0) return; //Don't perform transformation
if(GIM_DYNARRAY_IS_VALID( trimesh->m_cache->m_transformed_vertices_cache_bitset))
{
GIM_BITSET_CLEAR_ALL(trimesh->m_cache->m_transformed_vertices_cache_bitset);
return;
}
//transform vertices
mat4f transform;
COPY_MATRIX_4X4(transform,trimesh->m_transform);
gim_trimesh_data_get(trimesh->m_trimesh_data_handle,&trimesh->m_unlocked_trimesh_data );
gim_transform_vertex_buffers(
&trimesh->m_unlocked_trimesh_data->m_source_vertex_buffer,
trimesh->m_unlocked_trimesh_data->m_vertex_scalar_type,
&trimesh->m_cache->m_transformed_vertex_buffer,trimesh->m_cache->m_tranformed_scalar_type,transform);
trimesh->m_unlocked_trimesh_data = 0;
}
void gim_trimesh_update_cache(GIM_TRIMESH * trimesh)
{
if(trimesh->m_cache == 0) return;
//Clear planes cache
GIM_BITSET_CLEAR_ALL(trimesh->m_cache->m_planes_cache_bitset);
gim_trimesh_update_vertices(trimesh);
}
//! 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)
{
if(trimesh->m_aabbset == 0) return;
assert(trimesh->m_cache);
assert(GIM_BUFFER_ARRAY_IS_VALID(trimesh->m_cache->m_transformed_vertex_buffer));
vec3f * vertices = GIM_BUFFER_ARRAY_POINTER(vec3f,trimesh->m_cache->m_transformed_vertex_buffer,0);
// box set
aabb3f * paabb = trimesh->m_aabbset->m_boxes;
GUINT triangle_count = gim_trimesh_get_triangle_count(trimesh);
vec3ui triangle_indices;
GUINT i;
for (i=0; i<triangle_count;i++)
{
gim_trimesh_data_get_triangle_indices(
trimesh->m_unlocked_trimesh_data,i,triangle_indices);
COMPUTEAABB_FOR_TRIANGLE((*paabb),
vertices[triangle_indices[0]],
vertices[triangle_indices[1]],vertices[triangle_indices[2]]);
paabb++;
}
//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_cache(trimesh);
if(trimesh->m_aabbset!=0)
{
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];
GUINT i;
for (i=0;i<16;i++)
{
diff += fabs(originaltrans[i]-newtrans[i]);
}
if(GIM_IS_ZERO(diff)) return ;///don't need to update
//if(diff< 0.0006f) return ;///don't need to update
COPY_MATRIX_4X4(trimesh->m_transform,transform);
GREAL det;
INVERT_4X4(trimesh->m_inv_transform,det,transform);
gim_trimesh_post_update(trimesh);
}
void gim_trimesh_get_triangle_data(GIM_TRIMESH * trimesh, GUINT triangle_index, GIM_TRIANGLE_DATA * tri_data)
{
gim_trimesh_get_triangle_vertices(trimesh,triangle_index,
tri_data->m_vertices[0],
tri_data->m_vertices[1],
tri_data->m_vertices[2]);
if(trimesh->m_cache)
{
//Get the planes
GIM_TRIPLANES_CACHE * planes = GIM_DYNARRAY_POINTER(GIM_TRIPLANES_CACHE,trimesh->m_cache->m_planes_cache_buffer);
planes += triangle_index;
//verify planes cache
char bit_eval;
GIM_BITSET_GET(trimesh->m_cache->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_cache->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
tri_data->m_has_planes = 1;
return;
}
GIM_CALC_TRIANGLE_DATA_PLANES((*tri_data));
tri_data->m_has_planes = 1;
}
void gim_trimesh_get_triangle_data_lazy(GIM_TRIMESH * trimesh, GUINT triangle_index, GIM_TRIANGLE_DATA * tri_data)
{
gim_trimesh_get_triangle_vertices(trimesh,triangle_index,
tri_data->m_vertices[0],
tri_data->m_vertices[1],
tri_data->m_vertices[2]);
if(trimesh->m_cache)
{
//Get the planes
GIM_TRIPLANES_CACHE * planes = GIM_DYNARRAY_POINTER(GIM_TRIPLANES_CACHE,trimesh->m_cache->m_planes_cache_buffer);
planes += triangle_index;
//verify planes cache
char bit_eval;
GIM_BITSET_GET(trimesh->m_cache->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_cache->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
tri_data->m_has_planes = 1;
return;
}
tri_data->m_has_planes = 0;
}
void gim_trimesh_get_aabb(GIM_TRIMESH * trimesh,aabb3f * bound)
{
if(trimesh->m_aabbset)
{
AABB_COPY((*bound),trimesh->m_aabbset->m_global_bound);
return;
}
if(gim_trimesh_data_has_bv_tree(trimesh->m_trimesh_data_handle))
{
gim_trimesh_data_get(trimesh->m_trimesh_data_handle,&trimesh->m_unlocked_trimesh_data);
if(gim_trimesh_has_tranform(trimesh))
{
AABB_TRANSFORM((*bound),
trimesh->m_unlocked_trimesh_data->m_bv_tree.m_root_node->m_data.m_aabb,
trimesh->m_transform);
}
else
{
AABB_COPY((*bound),trimesh->m_unlocked_trimesh_data->m_bv_tree.m_root_node->m_data.m_aabb);
}
trimesh->m_unlocked_trimesh_data = 0;
return;
}
}
void gim_trimesh_midphase_box_collision(GIM_TRIMESH * trimesh,aabb3f *test_aabb, GDYNAMIC_ARRAY * collided)
{
collided->m_size = 0;
if(gim_trimesh_get_bound_method(trimesh)==G_TRIMESH_BOUND_AABB_TREE)
{
GIM_TRIMESH_DATA * tridata;
gim_trimesh_data_get(trimesh->m_trimesh_data_handle,&tridata);
aabb3f transbound;
AABB_TRANSFORM(transbound,(*test_aabb),trimesh->m_inv_transform);
gim_aabbtree_box_collision(&transbound,&tridata->m_bv_tree,collided);
}
else if(gim_trimesh_get_bound_method(trimesh)==G_TRIMESH_BOUND_AABB_SET)
{
gim_aabbset_box_collision(test_aabb,trimesh->m_aabbset,collided);
}
}
void gim_trimesh_midphase_box_collision_local(GIM_TRIMESH * trimesh,aabb3f *test_aabb, GDYNAMIC_ARRAY * collided)
{
collided->m_size = 0;
if(gim_trimesh_get_bound_method(trimesh)==G_TRIMESH_BOUND_AABB_TREE)
{
GIM_TRIMESH_DATA * tridata;
gim_trimesh_data_get(trimesh->m_trimesh_data_handle,&tridata);
gim_aabbtree_box_collision(test_aabb,&tridata->m_bv_tree,collided);
}
else if(gim_trimesh_get_bound_method(trimesh)==G_TRIMESH_BOUND_AABB_SET)
{
gim_aabbset_box_collision(test_aabb,trimesh->m_aabbset,collided);
}
}
void gim_trimesh_midphase_trimesh_collision(GIM_TRIMESH * trimesh1,
GIM_TRIMESH * trimesh2, GDYNAMIC_ARRAY * collision_pairs, char * swaped)
{
collision_pairs->m_size = 0;
GIM_TRIMESH_DATA * tridata1;
GIM_TRIMESH_DATA * tridata2;
if(gim_trimesh_get_bound_method(trimesh1)==G_TRIMESH_BOUND_AABB_TREE)
{
gim_trimesh_data_get(trimesh1->m_trimesh_data_handle,&tridata1);
if(gim_trimesh_get_bound_method(trimesh2)==G_TRIMESH_BOUND_AABB_TREE)
{
*swaped = 0;
gim_trimesh_data_get(trimesh2->m_trimesh_data_handle,&tridata2);
gim_aabbtree_bipartite_intersections_trans(
&tridata1->m_bv_tree,
&tridata2->m_bv_tree,
trimesh1->m_transform,
trimesh1->m_inv_transform,
trimesh2->m_transform,
trimesh2->m_inv_transform,
collision_pairs);
}
else if(gim_trimesh_get_bound_method(trimesh2)==G_TRIMESH_BOUND_AABB_SET)
{
*swaped = 1;
gim_aabbset_aabbtree_intersections_trans(
trimesh2->m_aabbset,
&tridata1->m_bv_tree,
trimesh1->m_transform,
trimesh1->m_inv_transform,
collision_pairs);
}
}
else if(gim_trimesh_get_bound_method(trimesh1)==G_TRIMESH_BOUND_AABB_SET)
{
*swaped = 0;
if(gim_trimesh_get_bound_method(trimesh2)==G_TRIMESH_BOUND_AABB_TREE)
{
gim_trimesh_data_get(trimesh2->m_trimesh_data_handle,&tridata2);
gim_aabbset_aabbtree_intersections_trans(
trimesh1->m_aabbset,
&tridata2->m_bv_tree,
trimesh2->m_transform,
trimesh2->m_inv_transform,
collision_pairs);
}
else if(gim_trimesh_get_bound_method(trimesh2)==G_TRIMESH_BOUND_AABB_SET)
{
gim_aabbset_bipartite_intersections(
trimesh1->m_aabbset,
trimesh2->m_aabbset,
collision_pairs);
}
}
}

View File

@@ -1,281 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. 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.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.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, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "GIMPACT/gim_trimesh.h"
//! Utility function for find the closest point between a segment and a triangle
/*!
\param triangle
\param s1
\param s2
\param contacts Contains the closest points on the segment (1,2), and the normal points to segment, and m_depth contains the distance
\post The contacts array is not set to 0. It adds aditional contacts
*/
void gim_closest_point_triangle_segment(GIM_TRIANGLE_DATA * triangle, vec3f s1,vec3f s2, GDYNAMIC_ARRAY * contacts)
{
vec3f segment_points[4];
vec3f closest_points[2];
GUINT intersection_type, out_edge= 10;
GREAL dis, dis_temp,perpend;
vec4f sdiff;
dis = DISTANCE_PLANE_POINT(triangle->m_planes.m_planes[0],s1);
dis_temp = DISTANCE_PLANE_POINT(triangle->m_planes.m_planes[0],s2);
if(dis<=0.0f && dis_temp<=0.0f) return;
VEC_DIFF(sdiff,s2,s1);
perpend = VEC_DOT(sdiff,triangle->m_planes.m_planes[0]);
if(!GIM_IS_ZERO(perpend)) // Not perpendicular
{
if(dis<dis_temp)
{
VEC_COPY(closest_points[0],s1);
}
else
{
dis = dis_temp;
VEC_COPY(closest_points[0],s2);
}
//Testing segment vertices over triangle
if(dis>=0.0f && dis_temp>=0.0f)
{
POINT_IN_HULL(closest_points[0],(&triangle->m_planes.m_planes[1]),3,out_edge);
if(out_edge==0)//Point over face
{
GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
return;
}
}
else
{
PLANE_CLIP_SEGMENT(s1,s2,triangle->m_planes.m_planes[0],closest_points[1]);
POINT_IN_HULL(closest_points[1],(&triangle->m_planes.m_planes[1]),3,out_edge);
if(out_edge==0)//Point over face
{
GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
return;
}
}
}
else // Perpendicular Face
{
//out_edge=10
//Clip segment by triangle
// Edge1
PLANE_CLIP_SEGMENT_CLOSEST(s1,s2,triangle->m_planes.m_planes[1],segment_points[0],segment_points[1],intersection_type);
if(intersection_type==0||intersection_type==1)
{
out_edge = 0;
VEC_COPY(closest_points[0],segment_points[0]);
}
else
{
//Edge2
PLANE_CLIP_SEGMENT_CLOSEST(segment_points[0],segment_points[1],triangle->m_planes.m_planes[2],segment_points[2],segment_points[3],intersection_type);
if(intersection_type==0||intersection_type==1)
{
out_edge = 1;
VEC_COPY(closest_points[0],segment_points[3]);
}
else
{
//Edge3
PLANE_CLIP_SEGMENT_CLOSEST(segment_points[2],segment_points[3],triangle->m_planes.m_planes[3],closest_points[0],closest_points[1],intersection_type);
if(intersection_type==0||intersection_type==1)
{
out_edge = 2;
}
}
}
//POST closest_points[0] and closest_points[1] are inside the triangle, if out_edge>2
if(out_edge>2) // Over triangle
{
dis = VEC_DOT(closest_points[0],triangle->m_planes.m_planes[0]);
GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
GIM_PUSH_CONTACT((*contacts),closest_points[1] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
return;
}
}
//Find closest edges
out_edge = 10;
dis = G_REAL_INFINITY;
GUINT i;
for(i=0;i<3;i++)
{
SEGMENT_COLLISION(s1,s2,triangle->m_vertices[i],triangle->m_vertices[(i+1)%3],segment_points[0],segment_points[1]);
VEC_DIFF(sdiff,segment_points[0],segment_points[1]);
dis_temp = VEC_DOT(sdiff,sdiff);
if(dis_temp< dis)
{
dis = dis_temp;
out_edge = i;
VEC_COPY(closest_points[0],segment_points[0]);
VEC_COPY(closest_points[1],sdiff);//normal
}
}
if(out_edge>2) return ;// ???? btAssert this please
if(GIM_IS_ZERO(dis))
{
//Set face plane
GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,0.0f,0, 0, 0,0);
}
else
{
GIM_SQRT(dis,dis);
VEC_SCALE(closest_points[1],(1.0f/dis),closest_points[1]);//normal
GIM_PUSH_CONTACT((*contacts),closest_points[0] ,closest_points[1],dis,0, 0, 0,0);
}
}
//! Utility function for find the closest point between a capsule and a triangle
/*!
\param triangle
\param capsule
\param contacts Contains the closest points on the capsule, and the normal points to triangle
\post The contacts array is not set to 0. It adds aditional contacts
*/
int gim_triangle_capsule_collision(GIM_TRIANGLE_DATA * triangle, GIM_CAPSULE_DATA * capsule, GDYNAMIC_ARRAY * contacts)
{
GUINT old_contact_size = contacts->m_size;
gim_closest_point_triangle_segment(triangle,capsule->m_point1,capsule->m_point2,contacts);
GIM_CONTACT * pcontact = GIM_DYNARRAY_POINTER(GIM_CONTACT ,(*contacts));
pcontact+= old_contact_size;
if(pcontact->m_depth > capsule->m_radius)
{
contacts->m_size = old_contact_size;
return 0;
}
vec3f vec;
while(old_contact_size<contacts->m_size)
{
//Scale the normal for pointing to triangle
VEC_SCALE(pcontact->m_normal,-1.0f,pcontact->m_normal);
//Fix the contact point
VEC_SCALE(vec,capsule->m_radius,pcontact->m_normal);
VEC_SUM(pcontact->m_point,vec,pcontact->m_point);
//Fix the depth
pcontact->m_depth = capsule->m_radius - pcontact->m_depth;
pcontact++;
old_contact_size++;
}
return 1;
}
//! Trimesh Capsule collision
/*!
Find the closest primitive collided by the ray
\param trimesh
\param capsule
\param contact
\param contacts A GIM_CONTACT array. Must be initialized
*/
void gim_trimesh_capsule_collision(GIM_TRIMESH * trimesh, GIM_CAPSULE_DATA * capsule, GDYNAMIC_ARRAY * contacts)
{
contacts->m_size = 0;
aabb3f test_aabb;
CALC_CAPSULE_AABB((*capsule),test_aabb);
GDYNAMIC_ARRAY collision_result;
GIM_CREATE_BOXQUERY_LIST(collision_result);
gim_trimesh_midphase_box_collision(trimesh,&test_aabb,&collision_result);
if(collision_result.m_size==0)
{
GIM_DYNARRAY_DESTROY(collision_result);
}
//collide triangles
//Locks trimesh
gim_trimesh_locks_work_data(trimesh);
//dummy contacts
GDYNAMIC_ARRAY dummycontacts;
GIM_CREATE_CONTACT_LIST(dummycontacts);
int cresult;
unsigned int i;
GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
GIM_TRIANGLE_DATA tri_data;
GUINT old_contact_size;
GIM_CONTACT * pcontact;
for(i=0;i<collision_result.m_size;i++)
{
old_contact_size = dummycontacts.m_size;
gim_trimesh_get_triangle_data(trimesh,boxesresult[i],&tri_data);
cresult = gim_triangle_capsule_collision(&tri_data, capsule, &dummycontacts);
if(cresult!=0)
{
pcontact = GIM_DYNARRAY_POINTER(GIM_CONTACT ,dummycontacts);
pcontact+= old_contact_size;
while(old_contact_size<dummycontacts.m_size)
{
pcontact->m_handle1 = trimesh;
pcontact->m_handle2 = capsule;
pcontact->m_feature1 = boxesresult[i];
pcontact->m_feature2 = 0;
pcontact++;
old_contact_size++;
}
}
}
///unlocks
gim_trimesh_unlocks_work_data(trimesh);
///Destroy box result
GIM_DYNARRAY_DESTROY(collision_result);
//merge contacts
gim_merge_contacts(&dummycontacts,contacts);
//Destroy dummy
GIM_DYNARRAY_DESTROY(dummycontacts);
}

View File

@@ -1,454 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. 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.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.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, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "GIMPACT/gim_trimesh_data.h"
GDYNAMIC_ARRAY g_trimesh_data_array;
GDYNAMIC_ARRAY g_trimesh_data_free_positions;
void gim_trimesh_data_manager_init()
{
GIM_DYNARRAY_CREATE(GIM_TRIMESH_DATA,g_trimesh_data_array,G_ARRAY_GROW_SIZE);
GIM_DYNARRAY_CREATE(GUINT,g_trimesh_data_free_positions,G_ARRAY_GROW_SIZE);
}
void gim_trimesh_data_manager_end()
{
//Destroy all trimeshes
GUINT i,tricount;
GIM_TRIMESH_DATA * trimeshes = GIM_DYNARRAY_POINTER(GIM_TRIMESH_DATA,g_trimesh_data_array);
tricount = g_trimesh_data_array.m_size;
for (i=0;i<tricount;i++)
{
if(GIM_IS_VALID_BUFFER_ID(trimeshes[i].m_source_vertex_buffer.m_buffer_id))
{
trimeshes[i].m_ref_count = 0;
gim_trimesh_data_destroy(i);
}
}
GIM_DYNARRAY_DESTROY(g_trimesh_data_array);
GIM_DYNARRAY_DESTROY(g_trimesh_data_free_positions);
}
int gim_trimesh_data_is_valid_manager()
{
if(g_trimesh_data_array.m_pdata == 0 ) return 0;
return 1;
}
//! Returns the free position (1 based) on the g_trimesh_data_array
GUINT _gim_trimesh_data_get_avaliable_pos()
{
if(gim_trimesh_data_is_valid_manager()==0) return 0;
if(g_trimesh_data_free_positions.m_size>0)
{
GUINT freeposition = *GIM_DYNARRAY_POINTER_LAST(GUINT,g_trimesh_data_free_positions);
GIM_DYNARRAY_POP_ITEM(g_trimesh_data_free_positions);
return freeposition+1;
}
GIM_DYNARRAY_PUSH_EMPTY(GIM_TRIMESH_DATA,g_trimesh_data_array);
return g_trimesh_data_array.m_size;
}
void _gim_trimesh_data_free_handle(GUINT handle)
{
if(gim_trimesh_data_is_valid_manager()==0) return;
GUINT freeposition = handle-1;
GIM_DYNARRAY_PUSH_ITEM(GUINT,g_trimesh_data_free_positions,freeposition);
}
void gim_trimesh_data_get(GUINT trimesh_data_handle,GIM_TRIMESH_DATA ** trimesh_data)
{
if(gim_trimesh_data_is_valid_manager()==0)
{
*trimesh_data = 0;
return;
}
GIM_TRIMESH_DATA * trimeshes = GIM_DYNARRAY_POINTER(GIM_TRIMESH_DATA,g_trimesh_data_array);
*trimesh_data = trimeshes+(trimesh_data_handle-1);
}
void _gim_gim_trimesh_data_create_empty(GIM_TRIMESH_DATA * tridata)
{
tridata->m_vertex_scalar_type = G_STYPE_REAL;
tridata->m_index_scalar_type = G_STYPE_UINT;
tridata->m_ref_count = 0;
//Init bvh
tridata->m_bv_tree.m_node_array = 0;
tridata->m_bv_tree.m_num_nodes = 0;
tridata->m_bv_tree.m_root_node = 0;
tridata->m_bv_tree.m_nodes_array_size = 0;
//Reference buffer arrays
tridata->m_source_vertex_buffer.m_buffer_data = 0;
tridata->m_source_vertex_buffer.m_buffer_id.m_buffer_id = G_UINT_INFINITY;
tridata->m_source_vertex_buffer.m_element_count = 0;
tridata->m_tri_index_buffer.m_buffer_data = 0;
tridata->m_tri_index_buffer.m_buffer_id.m_buffer_id = G_UINT_INFINITY;
tridata->m_tri_index_buffer.m_element_count = 0;
}
void _gim_gim_trimesh_data_build_from_arrays(GIM_TRIMESH_DATA * tridata,GBUFFER_ARRAY * vertex_array,GUINT vertex_scalar_type, GBUFFER_ARRAY * triindex_array,GUINT index_scalar_type)
{
tridata->m_vertex_scalar_type = vertex_scalar_type;
tridata->m_index_scalar_type = index_scalar_type;
tridata->m_ref_count = 0;
//Init bvh
tridata->m_bv_tree.m_node_array = 0;
tridata->m_bv_tree.m_num_nodes = 0;
tridata->m_bv_tree.m_root_node = 0;
tridata->m_bv_tree.m_nodes_array_size = 0;
//Reference buffer arrays
gim_buffer_array_copy_ref(vertex_array,&tridata->m_source_vertex_buffer);
gim_buffer_array_copy_ref(triindex_array,&tridata->m_tri_index_buffer);
}
void _gim_gim_trimesh_data_destroy_data(GIM_TRIMESH_DATA * tridata)
{
GIM_BUFFER_ARRAY_DESTROY(tridata->m_source_vertex_buffer);
GIM_BUFFER_ARRAY_DESTROY(tridata->m_tri_index_buffer);
gim_aabbtree_destroy(&tridata->m_bv_tree);
}
void gim_trimesh_data_create_empty(GUINT * trimesh_data_handle)
{
*trimesh_data_handle = _gim_trimesh_data_get_avaliable_pos();
if(*trimesh_data_handle == 0) return ; //an error ocurred
GIM_TRIMESH_DATA * tridata;
gim_trimesh_data_get(*trimesh_data_handle,&tridata);
//init trimesh
tridata->m_handle = *trimesh_data_handle;
_gim_gim_trimesh_data_create_empty(tridata);
}
void gim_trimesh_data_create_from_arrays(GUINT * trimesh_data_handle, GBUFFER_ARRAY * vertex_array,GUINT vertex_scalar_type, GBUFFER_ARRAY * triindex_array,GUINT index_scalar_type)
{
*trimesh_data_handle = _gim_trimesh_data_get_avaliable_pos();
if(*trimesh_data_handle == 0) return ; //an error ocurred
GIM_TRIMESH_DATA * tridata;
gim_trimesh_data_get(*trimesh_data_handle,&tridata);
//init trimesh
tridata->m_handle = *trimesh_data_handle;
//construct
_gim_gim_trimesh_data_build_from_arrays(tridata,vertex_array,vertex_scalar_type,triindex_array,index_scalar_type);
}
void gim_trimesh_data_create_from_array_data(GUINT * trimesh_data_handle, vec3f * vertex_array, GUINT vertex_count,char copy_vertices, GUINT * triindex_array, GUINT triangle_count,char copy_indices)
{
if(gim_trimesh_data_is_valid_manager()==0)
{
*trimesh_data_handle = 0;
return;
}
GBUFFER_ARRAY buffer_vertex_array;
GBUFFER_ARRAY buffer_triindex_array;
//Create vertices
if(copy_vertices == 1)
{
gim_create_common_buffer_from_data(vertex_array, vertex_count*sizeof(vec3f), &buffer_vertex_array.m_buffer_id);
}
else//Create a shared buffer
{
gim_create_shared_buffer_from_data(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(triindex_array, triangle_count*sizeof(vec3ui), &buffer_triindex_array.m_buffer_id);
}
else//Create a shared buffer
{
gim_create_shared_buffer_from_data(triindex_array, triangle_count*sizeof(vec3ui), &buffer_triindex_array.m_buffer_id);
}
GIM_BUFFER_ARRAY_INIT_TYPE(vec3ui,buffer_triindex_array,buffer_triindex_array.m_buffer_id,triangle_count);
gim_trimesh_data_create_from_arrays(trimesh_data_handle, &buffer_vertex_array,G_STYPE_REAL, &buffer_triindex_array,G_STYPE_UINT);
///always call this after create a buffer_array
GIM_BUFFER_ARRAY_DESTROY(buffer_vertex_array);
GIM_BUFFER_ARRAY_DESTROY(buffer_triindex_array);
}
void gim_trimesh_data_inc_ref(GUINT trimesh_data_handle)
{
if(gim_trimesh_data_is_valid_manager()==0) return;
GIM_TRIMESH_DATA * tridata;
gim_trimesh_data_get(trimesh_data_handle,&tridata);
tridata->m_ref_count++;
}
void gim_trimesh_data_dec_ref(GUINT trimesh_data_handle)
{
if(gim_trimesh_data_is_valid_manager()==0) return;
GIM_TRIMESH_DATA * tridata;
gim_trimesh_data_get(trimesh_data_handle,&tridata);
if(tridata->m_ref_count==0)
{
//Attemps to destroy the trimesh
gim_trimesh_data_destroy(trimesh_data_handle);
return;
}
tridata->m_ref_count--;
if(tridata->m_ref_count==0)
{
//Attemps to destroy the trimesh
gim_trimesh_data_destroy(trimesh_data_handle);
}
}
void gim_trimesh_data_destroy(GUINT trimesh_data_handle)
{
if(gim_trimesh_data_is_valid_manager()==0) return;
GIM_TRIMESH_DATA * tridata;
gim_trimesh_data_get(trimesh_data_handle,&tridata);
if(tridata->m_ref_count>0) return; //Can't destroy it now
_gim_gim_trimesh_data_destroy_data(tridata);
//Get a free position
_gim_trimesh_data_free_handle(trimesh_data_handle);
}
void gim_trimesh_data_lock(GUINT trimesh_data_handle, int access,GIM_TRIMESH_DATA ** trimesh_data)
{
if(gim_trimesh_data_is_valid_manager()==0) return;
gim_trimesh_data_get(trimesh_data_handle,trimesh_data);
gim_buffer_array_lock(&(*trimesh_data)->m_source_vertex_buffer,access);
gim_buffer_array_lock(&(*trimesh_data)->m_tri_index_buffer,access);
}
void gim_trimesh_data_unlock(GUINT trimesh_data_handle)
{
if(gim_trimesh_data_is_valid_manager()==0) return;
GIM_TRIMESH_DATA * tridata;
gim_trimesh_data_get(trimesh_data_handle,&tridata);
gim_buffer_array_unlock(&tridata->m_source_vertex_buffer);
gim_buffer_array_unlock(&tridata->m_tri_index_buffer);
}
GUINT gim_trimesh_data_get_vertex_count(GUINT trimesh_data_handle)
{
GIM_TRIMESH_DATA * tridata;
gim_trimesh_data_get(trimesh_data_handle,&tridata);
return tridata->m_source_vertex_buffer.m_element_count;
}
GUINT gim_trimesh_data_get_triangle_count(GUINT trimesh_data_handle)
{
GIM_TRIMESH_DATA * tridata;
gim_trimesh_data_get(trimesh_data_handle,&tridata);
return tridata->m_tri_index_buffer.m_element_count;
}
void gim_trimesh_data_get_triangle_indices(GIM_TRIMESH_DATA * trimesh_data, GUINT tri_index, GUINT * indices)
{
if(trimesh_data->m_index_scalar_type == G_STYPE_UINT)
{
GUINT * uipindices = GIM_BUFFER_ARRAY_POINTER(GUINT,trimesh_data->m_tri_index_buffer,tri_index);
indices[0] = uipindices[0];
indices[1] = uipindices[1];
indices[2] = uipindices[2];
}
else if(trimesh_data->m_index_scalar_type == G_STYPE_INT)
{
GINT * ipindices = GIM_BUFFER_ARRAY_POINTER(GINT,trimesh_data->m_tri_index_buffer,tri_index);
indices[0] = ipindices[0];
indices[1] = ipindices[1];
indices[2] = ipindices[2];
}
else if(trimesh_data->m_index_scalar_type == G_STYPE_USHORT)
{
GUSHORT * uspindices = GIM_BUFFER_ARRAY_POINTER(GUSHORT,trimesh_data->m_tri_index_buffer,tri_index);
indices[0] = uspindices[0];
indices[1] = uspindices[1];
indices[2] = uspindices[2];
}
else if(trimesh_data->m_index_scalar_type == G_STYPE_SHORT)
{
GSHORT * spindices = GIM_BUFFER_ARRAY_POINTER(GSHORT,trimesh_data->m_tri_index_buffer,tri_index);
indices[0] = spindices[0];
indices[1] = spindices[1];
indices[2] = spindices[2];
}
}
void gim_trimesh_data_get_vertex(GIM_TRIMESH_DATA * trimesh_data, GUINT vertex_index, vec3f vec)
{
if(trimesh_data->m_vertex_scalar_type == G_STYPE_REAL)
{
GREAL * rvalues = GIM_BUFFER_ARRAY_POINTER(GREAL,trimesh_data->m_source_vertex_buffer,vertex_index);
vec[0] = rvalues[0];
vec[1] = rvalues[1];
vec[2] = rvalues[2];
}
else if(trimesh_data->m_vertex_scalar_type == G_STYPE_REAL2)
{
GREAL2 * r2values = GIM_BUFFER_ARRAY_POINTER(GREAL2,trimesh_data->m_source_vertex_buffer,vertex_index);
vec[0] = r2values[0];
vec[1] = r2values[1];
vec[2] = r2values[2];
}
}
void gim_trimesh_data_get_triangle_vertices(GIM_TRIMESH_DATA * trimesh_data, GUINT tri_index, vec3f v1, vec3f v2, vec3f v3)
{
GUINT tri_indices[3];
gim_trimesh_data_get_triangle_indices(trimesh_data,tri_index,tri_indices);
if(trimesh_data->m_vertex_scalar_type == G_STYPE_REAL)
{
GREAL * rvalues = GIM_BUFFER_ARRAY_POINTER(GREAL,trimesh_data->m_source_vertex_buffer,tri_indices[0]);
VEC_COPY(v1,rvalues);
rvalues = GIM_BUFFER_ARRAY_POINTER(GREAL,trimesh_data->m_source_vertex_buffer,tri_indices[1]);
VEC_COPY(v2,rvalues);
rvalues = GIM_BUFFER_ARRAY_POINTER(GREAL,trimesh_data->m_source_vertex_buffer,tri_indices[2]);
VEC_COPY(v3,rvalues);
}
else if(trimesh_data->m_vertex_scalar_type == G_STYPE_REAL2)
{
GREAL2 * r2values = GIM_BUFFER_ARRAY_POINTER(GREAL2,trimesh_data->m_source_vertex_buffer,tri_indices[0]);
VEC_COPY(v1,r2values);
r2values = GIM_BUFFER_ARRAY_POINTER(GREAL2,trimesh_data->m_source_vertex_buffer,tri_indices[1]);
VEC_COPY(v2,r2values);
r2values = GIM_BUFFER_ARRAY_POINTER(GREAL2,trimesh_data->m_source_vertex_buffer,tri_indices[2]);
VEC_COPY(v3,r2values);
}
}
void gim_trimesh_data_build_aabbtree(GUINT trimesh_data_handle)
{
if(gim_trimesh_data_is_valid_manager()==0) return;
GIM_TRIMESH_DATA * tridata;
gim_trimesh_data_lock(trimesh_data_handle, G_MA_READ_ONLY,&tridata);
GUINT i,tricount;
tricount = gim_trimesh_data_get_triangle_count(trimesh_data_handle);
GIM_AABB_DATA * boxarray = (GIM_AABB_DATA *)gim_alloc(tricount*sizeof(GIM_AABB_DATA));
vec3f trivertices[3];
for (i=0;i<tricount ;i++ )
{
gim_trimesh_data_get_triangle_vertices(tridata,i,trivertices[0],trivertices[1],trivertices[2]);
COMPUTEAABB_FOR_TRIANGLE(boxarray[i].m_aabb,trivertices[0],trivertices[1],trivertices[2]);
boxarray[i].m_data = i;
}
gim_trimesh_data_unlock(trimesh_data_handle);
gim_aabbtree_create(&tridata->m_bv_tree,boxarray,tricount);
gim_free(boxarray,0);
}
int gim_trimesh_data_has_bv_tree(GUINT trimesh_data_handle)
{
GIM_TRIMESH_DATA * tridata;
gim_trimesh_data_get(trimesh_data_handle,&tridata);
if(tridata->m_bv_tree.m_node_array == 0) return 0;
return 1;
}
void gim_trimesh_data_copy(GUINT source_trimesh_data,GUINT dest_trimesh_data, char copy_by_reference)
{
if(gim_trimesh_data_is_valid_manager()==0) return;
GIM_TRIMESH_DATA * sourcetridata;
gim_trimesh_data_get(source_trimesh_data,&sourcetridata);
GIM_TRIMESH_DATA * desttridata;
gim_trimesh_data_get(dest_trimesh_data,&desttridata);
_gim_gim_trimesh_data_destroy_data(desttridata);//Clear previus data
if(copy_by_reference==1)
{
_gim_gim_trimesh_data_build_from_arrays(desttridata, &sourcetridata->m_source_vertex_buffer,
sourcetridata->m_vertex_scalar_type, &sourcetridata->m_tri_index_buffer,
sourcetridata->m_index_scalar_type);
}
else
{
GBUFFER_ARRAY buffer_vertex_array;
GBUFFER_ARRAY buffer_triindex_array;
gim_buffer_array_copy_value(&sourcetridata->m_source_vertex_buffer,&buffer_vertex_array,G_BUFFER_MANAGER_SYSTEM,G_MU_DYNAMIC_READ_WRITE);
gim_buffer_array_copy_value(&sourcetridata->m_tri_index_buffer,&buffer_triindex_array,G_BUFFER_MANAGER_SYSTEM,G_MU_DYNAMIC_READ_WRITE);
_gim_gim_trimesh_data_build_from_arrays(desttridata, &buffer_vertex_array,
sourcetridata->m_vertex_scalar_type, &buffer_triindex_array,
sourcetridata->m_index_scalar_type);
///always call this after create a buffer_array
GIM_BUFFER_ARRAY_DESTROY(buffer_vertex_array);
GIM_BUFFER_ARRAY_DESTROY(buffer_triindex_array);
}
//If it has a Bounding volume tree, construct it
if(gim_trimesh_data_has_bv_tree(source_trimesh_data))
{
gim_trimesh_data_build_aabbtree(dest_trimesh_data);
}
}
void gim_trimesh_data_create_copy(GUINT source_trimesh_data,GUINT * dest_trimesh_data, char copy_by_reference)
{
if(gim_trimesh_data_is_valid_manager()==0) return;
gim_trimesh_data_create_empty(dest_trimesh_data);
gim_trimesh_data_copy(source_trimesh_data,*dest_trimesh_data, copy_by_reference);
}

View File

@@ -1,180 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. 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.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.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, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "GIMPACT/gim_trimesh.h"
//! Trimesh Ray Collisions
/*!
\param trimesh
\param contact
\return 1 if the ray collides, else 0
*/
int gim_trimesh_ray_collision(GIM_TRIMESH * trimesh,vec3f origin,vec3f dir, GREAL tmax, GIM_TRIANGLE_RAY_CONTACT_DATA * contact)
{
GDYNAMIC_ARRAY collision_result;
GIM_CREATE_BOXQUERY_LIST(collision_result);
if(trimesh->m_aabbset)
{
gim_aabbset_ray_collision(origin,dir,tmax,trimesh->m_aabbset,
&collision_result);
}
else if(gim_trimesh_get_bound_method(trimesh)==G_TRIMESH_BOUND_AABB_TREE)
{
vec3f torigin, tdir;
gim_trimesh_data_get(trimesh->m_trimesh_data_handle,
&trimesh->m_unlocked_trimesh_data);
MAT_DOT_VEC_3X4(torigin,trimesh->m_inv_transform,dir);
MAT_DOT_VEC_3X3(tdir,trimesh->m_inv_transform,dir);
gim_aabbtree_ray_collision(
torigin,tdir, tmax,
&trimesh->m_unlocked_trimesh_data->m_bv_tree, &collision_result);
trimesh->m_unlocked_trimesh_data = 0;
}
if(collision_result.m_size==0)
{
GIM_DYNARRAY_DESTROY(collision_result);
return 0;
}
//collide triangles
GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
GIM_TRIANGLE_DATA tridata;
vec3f pout;
GREAL tparam,u,v;
char does_intersect;
gim_trimesh_locks_work_data(trimesh);
for(unsigned int i=0;i<collision_result.m_size;i++)
{
gim_trimesh_get_triangle_data(trimesh,boxesresult[i],&tridata);
RAY_TRIANGLE_INTERSECTION(origin,dir,tridata.m_vertices[0],tridata.m_vertices[1],tridata.m_vertices[2],tridata.m_planes.m_planes[0],pout,u,v,tparam,tmax,does_intersect);
if(does_intersect)
{
contact->tparam = tparam;
contact->u = u;
contact->v = v;
contact->m_face_id = boxesresult[i];
VEC_COPY(contact->m_point,pout);
VEC_COPY(contact->m_normal,tridata.m_planes.m_planes[0]);
gim_trimesh_unlocks_work_data(trimesh);
GIM_DYNARRAY_DESTROY(collision_result);
return 1;
}
}
gim_trimesh_unlocks_work_data(trimesh);
GIM_DYNARRAY_DESTROY(collision_result);
return 0;//no collisiion
}
//! Trimesh Ray Collisions closest
/*!
Find the closest primitive collided by the ray
\param trimesh
\param contact
\return 1 if the ray collides, else 0
*/
int gim_trimesh_ray_closest_collision(GIM_TRIMESH * trimesh,vec3f origin,vec3f dir, GREAL tmax, GIM_TRIANGLE_RAY_CONTACT_DATA * contact)
{
GDYNAMIC_ARRAY collision_result;
GIM_CREATE_BOXQUERY_LIST(collision_result);
if(trimesh->m_aabbset)
{
gim_aabbset_ray_collision(origin,dir,tmax,trimesh->m_aabbset,
&collision_result);
}
else if(gim_trimesh_get_bound_method(trimesh)==G_TRIMESH_BOUND_AABB_TREE)
{
vec3f torigin, tdir;
gim_trimesh_data_get(trimesh->m_trimesh_data_handle,
&trimesh->m_unlocked_trimesh_data);
MAT_DOT_VEC_3X4(torigin,trimesh->m_inv_transform,dir);
MAT_DOT_VEC_3X3(tdir,trimesh->m_inv_transform,dir);
gim_aabbtree_ray_collision(
torigin,tdir, tmax,
&trimesh->m_unlocked_trimesh_data->m_bv_tree, &collision_result);
trimesh->m_unlocked_trimesh_data = 0;
}
if(collision_result.m_size==0)
{
GIM_DYNARRAY_DESTROY(collision_result);
return 0;
}
//collide triangles
GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
GIM_TRIANGLE_DATA tridata;
vec3f pout;
GREAL tparam,u,v;
char does_intersect;
contact->tparam = tmax + 0.1f;
gim_trimesh_locks_work_data(trimesh);
for(unsigned int i=0;i<collision_result.m_size;i++)
{
gim_trimesh_get_triangle_data(trimesh,boxesresult[i],&tridata);
RAY_TRIANGLE_INTERSECTION(origin,dir,tridata.m_vertices[0],tridata.m_vertices[1],tridata.m_vertices[2],tridata.m_planes.m_planes[0],pout,u,v,tparam,tmax,does_intersect);
if(does_intersect && (tparam < contact->tparam))
{
contact->tparam = tparam;
contact->u = u;
contact->v = v;
contact->m_face_id = boxesresult[i];
VEC_COPY(contact->m_point,pout);
VEC_COPY(contact->m_normal,tridata.m_planes.m_planes[0]);
}
}
gim_trimesh_unlocks_work_data(trimesh);
GIM_DYNARRAY_DESTROY(collision_result);
if(contact->tparam > tmax) return 0;
return 1;
}

View File

@@ -1,198 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. 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.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.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, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "GIMPACT/gim_trimesh.h"
int gim_triangle_sphere_collision(
GIM_TRIANGLE_DATA *tri,
vec3f center, GREAL radius,
GIM_TRIANGLE_CONTACT_DATA * contact_data)
{
contact_data->m_point_count = 0;
//Find Face plane distance
GREAL dis = DISTANCE_PLANE_POINT(tri->m_planes.m_planes[0],center);
if(dis>radius) return 0; //out
if(dis<-radius) return 0;//Out of triangle
contact_data->m_penetration_depth = dis;
//Find the most edge
GUINT most_edge = 4;//no edge
GREAL max_dis = 0.0f;
dis = DISTANCE_PLANE_POINT(tri->m_planes.m_planes[1],center);
if(dis>radius) return 0;//Out of triangle
if(dis>0.0f)
{
max_dis = dis;
most_edge = 0;
}
dis = DISTANCE_PLANE_POINT(tri->m_planes.m_planes[2],center);
if(dis>radius) return 0;//Out of triangle
if(dis>max_dis)// && dis>0.0f)
{
max_dis = dis;
most_edge = 1;
}
dis = DISTANCE_PLANE_POINT(tri->m_planes.m_planes[3],center);
if(dis>radius) return 0;//Out of triangle
if(dis>max_dis)// && dis>0.0f)
{
max_dis = dis;
most_edge = 2;
}
if(most_edge == 4) //Box is into triangle
{
//contact_data->m_penetration_depth = dis is set above
//Find Face plane point
VEC_COPY(contact_data->m_separating_normal,tri->m_planes.m_planes[0]);
//Find point projection on plane
if(contact_data->m_penetration_depth>=0.0f)
{
VEC_SCALE(contact_data->m_points[0],-radius,contact_data->m_separating_normal);
}
else
{
VEC_SCALE(contact_data->m_points[0],radius,contact_data->m_separating_normal);
}
contact_data->m_penetration_depth = radius - contact_data->m_penetration_depth;
VEC_SUM(contact_data->m_points[0],contact_data->m_points[0],center);
//Scale normal for pointing to triangle
VEC_SCALE(contact_data->m_separating_normal,-1.0f,contact_data->m_separating_normal);
contact_data->m_point_count = 1;
return 1;
}
//find the edge
vec3f e1,e2;
VEC_COPY(e1,tri->m_vertices[most_edge]);
VEC_COPY(e2,tri->m_vertices[(most_edge+1)%3]);
CLOSEST_POINT_ON_SEGMENT(contact_data->m_points[0],center,e1,e2);
//find distance
VEC_DIFF(e1,center,contact_data->m_points[0]);
VEC_LENGTH(e1,dis);
if(dis>radius) return 0;
contact_data->m_penetration_depth = radius - dis;
if(GIM_IS_ZERO(dis))
{
VEC_COPY(contact_data->m_separating_normal,tri->m_planes.m_planes[most_edge+1]);
VEC_SCALE(contact_data->m_points[0],-radius,contact_data->m_separating_normal);
VEC_SUM(contact_data->m_points[0],contact_data->m_points[0],center);
}
else
{
VEC_SCALE(contact_data->m_separating_normal,1.0f/dis,e1);
VEC_SCALE(contact_data->m_points[0],-radius,contact_data->m_separating_normal);
VEC_SUM(contact_data->m_points[0],contact_data->m_points[0],center);
}
//Scale normal for pointing to triangle
VEC_SCALE(contact_data->m_separating_normal,-1.0f,contact_data->m_separating_normal);
contact_data->m_point_count = 1;
return 1;
}
//! Trimesh Sphere Collisions
/*!
In each contact
<ul>
<li> m_handle1 points to trimesh.
<li> m_handle2 points to NULL.
<li> m_feature1 Is a triangle index of trimesh.
</ul>
\param trimesh
\param center
\param radius
\param contacts A GIM_CONTACT array. Must be initialized
*/
void gim_trimesh_sphere_collision(GIM_TRIMESH * trimesh,vec3f center,GREAL radius, GDYNAMIC_ARRAY * contacts)
{
contacts->m_size = 0;
aabb3f test_aabb;
test_aabb.minX = center[0]-radius;
test_aabb.maxX = center[0]+radius;
test_aabb.minY = center[1]-radius;
test_aabb.maxY = center[1]+radius;
test_aabb.minZ = center[2]-radius;
test_aabb.maxZ = center[2]+radius;
GDYNAMIC_ARRAY collision_result;
GIM_CREATE_BOXQUERY_LIST(collision_result);
gim_trimesh_midphase_box_collision(trimesh,&test_aabb,&collision_result);
if(collision_result.m_size==0)
{
GIM_DYNARRAY_DESTROY(collision_result);
}
//collide triangles
//Locks trimesh
gim_trimesh_locks_work_data(trimesh);
//dummy contacts
GDYNAMIC_ARRAY dummycontacts;
GIM_CREATE_CONTACT_LIST(dummycontacts);
int cresult;
unsigned int i;
GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
GIM_TRIANGLE_CONTACT_DATA tri_contact_data;
GIM_TRIANGLE_DATA tri_data;
for(i=0;i<collision_result.m_size;i++)
{
gim_trimesh_get_triangle_data(trimesh,boxesresult[i],&tri_data);
cresult = gim_triangle_sphere_collision(&tri_data,center,radius,&tri_contact_data);
if(cresult!=0)
{
GIM_PUSH_CONTACT(dummycontacts, tri_contact_data.m_points[0],tri_contact_data.m_separating_normal ,tri_contact_data.m_penetration_depth,trimesh, 0, boxesresult[i],0);
}
}
///unlocks
gim_trimesh_unlocks_work_data(trimesh);
///Destroy box result
GIM_DYNARRAY_DESTROY(collision_result);
//merge contacts
gim_merge_contacts(&dummycontacts,contacts);
//Destroy dummy
GIM_DYNARRAY_DESTROY(dummycontacts);
}

View File

@@ -1,457 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. 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.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.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, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "GIMPACT/gim_trimesh.h"
#define CLASSIFY_TRI_BY_FACE(v1,v2,v3,faceplane,out_of_face)\
{ \
_distances[0] = DISTANCE_PLANE_POINT(faceplane,v1);\
_distances[1] = _distances[0] * DISTANCE_PLANE_POINT(faceplane,v2);\
_distances[2] = _distances[0] * DISTANCE_PLANE_POINT(faceplane,v3); \
if(_distances[1]<=0.0f || _distances[2]<=0.0f)\
{\
out_of_face = 0;\
}\
else\
{\
out_of_face = 1;\
}\
}\
#define CLASSIFY_TRI_BY_PLANE(v1,v2,v3,faceplane,out_of_face)\
{ \
if(DISTANCE_PLANE_POINT(faceplane,v1)<=0.0f)\
{\
out_of_face = 0;\
}\
else if(DISTANCE_PLANE_POINT(faceplane,v2)<=0.0f)\
{\
out_of_face = 0;\
}\
else if(DISTANCE_PLANE_POINT(faceplane,v3)<=0.0f)\
{\
out_of_face = 0;\
}\
else\
{\
out_of_face = 1;\
}\
}\
//! Receives the 3 edge planes
#define MOST_DEEP_POINTS(plane,points,point_count,deep_points,deep_points_count,maxdeep)\
{\
maxdeep=-1000.0f;\
GUINT _k;\
GREAL _dist;\
deep_points_count = 0;\
for(_k=0;_k<point_count;_k++)\
{\
_dist = -DISTANCE_PLANE_POINT(plane,points[_k]);\
if(_dist>maxdeep)\
{\
maxdeep = _dist;\
_max_candidates[0] = _k;\
deep_points_count=1;\
}\
else if((_dist+G_EPSILON)>=maxdeep)\
{\
_max_candidates[deep_points_count] = _k;\
deep_points_count++;\
}\
}\
if(maxdeep<0.0f)\
{\
deep_points_count = 0;\
}\
else\
{\
for(_k=0;_k<deep_points_count;_k++)\
{\
VEC_COPY(deep_points[_k],points[_max_candidates[_k]]);\
}\
}\
}\
//! Receives the 3 edge planes
#define CLIP_TRI_POINTS_BY_TRI_EDGE_PLANES(tri_points,tri_edge_planes, clipped_points, clipped_point_count)\
{\
clipped_point_count = 0; \
_temp_clip_count = 0;\
PLANE_CLIP_POLYGON(tri_edge_planes[0],tri_points,3,_temp_clip,_temp_clip_count,MAX_TRI_CLIPPING);\
if(_temp_clip_count>0)\
{\
_temp_clip_count2 = 0;\
PLANE_CLIP_POLYGON(tri_edge_planes[1],_temp_clip,_temp_clip_count,_temp_clip2,_temp_clip_count2,MAX_TRI_CLIPPING);\
if(_temp_clip_count2>0)\
{\
PLANE_CLIP_POLYGON(tri_edge_planes[2],_temp_clip2,_temp_clip_count2,clipped_points,clipped_point_count,MAX_TRI_CLIPPING);\
}\
}\
}\
static int _gim_triangle_triangle_collision(
GIM_TRIANGLE_DATA *tri1,
GIM_TRIANGLE_DATA *tri2,
GIM_TRIANGLE_CONTACT_DATA * contact_data)
{
//Cache variables for triangle intersection
GUINT _max_candidates[MAX_TRI_CLIPPING];
vec3f _temp_clip[MAX_TRI_CLIPPING];
GUINT _temp_clip_count = 0;
vec3f _temp_clip2[MAX_TRI_CLIPPING];
GUINT _temp_clip_count2 = 0;
vec3f clipped_points2[MAX_TRI_CLIPPING];
vec3f deep_points2[MAX_TRI_CLIPPING];
vec3f clipped_points1[MAX_TRI_CLIPPING];
vec3f deep_points1[MAX_TRI_CLIPPING];
//State variabnles
GUINT mostdir=0;
GUINT clipped2_count=0;
//Clip tri2 by tri1 edges
CLIP_TRI_POINTS_BY_TRI_EDGE_PLANES(tri2->m_vertices,(&tri1->m_planes.m_planes[1]), clipped_points2, clipped2_count);
if(clipped2_count == 0 )
{
return 0;//Reject
}
//find most deep interval face1
GUINT deep2_count=0;
GREAL maxdeep;
MOST_DEEP_POINTS((tri1->m_planes.m_planes[0]), clipped_points2, clipped2_count, deep_points2, deep2_count, maxdeep);
if(deep2_count==0)
{
// *perror = 0.0f;
return 0;//Reject
}
//Normal pointing to triangle1
VEC_SCALE(contact_data->m_separating_normal,-1.0f,(tri1->m_planes.m_planes[0]));
//Clip tri1 by tri2 edges
GUINT clipped1_count=0;
CLIP_TRI_POINTS_BY_TRI_EDGE_PLANES(tri1->m_vertices,(&tri2->m_planes.m_planes[1]), clipped_points1, clipped1_count);
if(clipped2_count == 0 )
{
// *perror = 0.0f;
return 0;//Reject
}
//find interval face2
GUINT deep1_count=0;
GREAL dist;
MOST_DEEP_POINTS((tri2->m_planes.m_planes[0]), clipped_points1, clipped1_count, deep_points1, deep1_count, dist);
if(deep1_count==0)
{
// *perror = 0.0f;
return 0;
}
if(dist<maxdeep)
{
maxdeep = dist;
mostdir = 1;
VEC_COPY(contact_data->m_separating_normal,(tri2->m_planes.m_planes[0]));
}
//set deep
contact_data->m_penetration_depth = maxdeep;
////check most dir for contacts
if(mostdir==0)
{
contact_data->m_point_count = deep2_count;
for(mostdir=0;mostdir<deep2_count;mostdir++)
{
VEC_COPY(contact_data->m_points[mostdir] ,deep_points2[mostdir]);
}
}
else
{
contact_data->m_point_count = deep1_count;
for(mostdir=0;mostdir<deep1_count;mostdir++)
{
VEC_COPY(contact_data->m_points[mostdir] ,deep_points1[mostdir]);
}
}
return 1;
}
//! Finds the contact points from a collision of two triangles
/*!
Returns the contact points, the penetration depth and the separating normal of the collision
between two triangles. The normal is pointing toward triangle 1 from triangle 2
*/
int gim_triangle_triangle_collision(
GIM_TRIANGLE_DATA *tri1,
GIM_TRIANGLE_DATA *tri2,
GIM_TRIANGLE_CONTACT_DATA * contact_data)
{
vec3f _distances;
char out_of_face=0;
if(tri2->m_has_planes==0)
{
TRIANGLE_PLANE(tri2->m_vertices[0],
tri2->m_vertices[1],tri2->m_vertices[2],tri2->m_planes.m_planes[0]);
}
//Fast overlapp
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);
if(out_of_face==1) return 0;
if(tri1->m_has_planes==0)
{
TRIANGLE_PLANE(tri1->m_vertices[0],tri1->m_vertices[1],
tri1->m_vertices[2],tri1->m_planes.m_planes[0]);
}
//Fast overlapp
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);
if(out_of_face==1) return 0;
/*
if(tri1->m_has_planes==0)
{
EDGE_PLANE(tri1->m_vertices[0],tri1->m_vertices[1],
(tri1->m_planes.m_planes[0]),(tri1->m_planes.m_planes[1]));
}
//Fast overlapp
CLASSIFY_TRI_BY_PLANE(tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2],tri1->m_planes.m_planes[1],out_of_face);
if(out_of_face==1) return 0;
if(tri1->m_has_planes==0)
{
EDGE_PLANE(tri1->m_vertices[1],tri1->m_vertices[2],
(tri1->m_planes.m_planes[0]),(tri1->m_planes.m_planes[2]));
}
//Fast overlapp
CLASSIFY_TRI_BY_PLANE(tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2],tri1->m_planes.m_planes[2],out_of_face);
if(out_of_face==1) return 0;
if(tri1->m_has_planes==0)
{
EDGE_PLANE(tri1->m_vertices[2],tri1->m_vertices[0],
(tri1->m_planes.m_planes[0]),(tri1->m_planes.m_planes[3]));
}
//Fast overlapp
CLASSIFY_TRI_BY_PLANE(tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2],tri1->m_planes.m_planes[3],out_of_face);
if(out_of_face==1) return 0;
if(tri2->m_has_planes==0)
{
EDGE_PLANE(tri2->m_vertices[0],tri2->m_vertices[1],
(tri2->m_planes.m_planes[0]),(tri2->m_planes.m_planes[1]));
EDGE_PLANE(tri2->m_vertices[1],tri2->m_vertices[2],
(tri2->m_planes.m_planes[0]),(tri2->m_planes.m_planes[2]));
EDGE_PLANE(tri2->m_vertices[2],tri2->m_vertices[0],
(tri2->m_planes.m_planes[0]),(tri2->m_planes.m_planes[3]));
}*/
if(tri1->m_has_planes==0)
{
EDGE_PLANE(tri1->m_vertices[0],tri1->m_vertices[1],
(tri1->m_planes.m_planes[0]),(tri1->m_planes.m_planes[1]));
EDGE_PLANE(tri1->m_vertices[1],tri1->m_vertices[2],
(tri1->m_planes.m_planes[0]),(tri1->m_planes.m_planes[2]));
EDGE_PLANE(tri1->m_vertices[2],tri1->m_vertices[0],
(tri1->m_planes.m_planes[0]),(tri1->m_planes.m_planes[3]));
}
if(tri2->m_has_planes==0)
{
EDGE_PLANE(tri2->m_vertices[0],tri2->m_vertices[1],
(tri2->m_planes.m_planes[0]),(tri2->m_planes.m_planes[1]));
EDGE_PLANE(tri2->m_vertices[1],tri2->m_vertices[2],
(tri2->m_planes.m_planes[0]),(tri2->m_planes.m_planes[2]));
EDGE_PLANE(tri2->m_vertices[2],tri2->m_vertices[0],
(tri2->m_planes.m_planes[0]),(tri2->m_planes.m_planes[3]));
}
return _gim_triangle_triangle_collision(tri1,tri2,contact_data);
}
//! Trimesh Trimesh Collisions
/*!
In each contact
<ul>
<li> m_handle1 points to trimesh1.
<li> m_handle2 points to trimesh2.
<li> m_feature1 Is a triangle index of trimesh1.
<li> m_feature2 Is a triangle index of trimesh2.
</ul>
\param trimesh1 Collider
\param trimesh2 Collidee
\param contacts A GIM_CONTACT array. Must be initialized
*/
void gim_trimesh_trimesh_collision(GIM_TRIMESH * trimesh1, GIM_TRIMESH * trimesh2, GDYNAMIC_ARRAY * contacts)
{
contacts->m_size = 0;
GDYNAMIC_ARRAY collision_pairs;
GIM_CREATE_PAIR_SET(collision_pairs);
char swaped;
gim_trimesh_midphase_trimesh_collision(trimesh1,trimesh2,&collision_pairs,&swaped);
if(collision_pairs.m_size==0)
{
GIM_DYNARRAY_DESTROY(collision_pairs);
return; //no collisioin
}
//Locks meshes
gim_trimesh_locks_work_data(trimesh1);
gim_trimesh_locks_work_data(trimesh2);
//pair pointer
GUINT *pairs = GIM_DYNARRAY_POINTER(GUINT,collision_pairs);
//dummy contacts
GDYNAMIC_ARRAY dummycontacts;
GIM_CREATE_CONTACT_LIST(dummycontacts);
//Auxiliary triangle data
GIM_TRIANGLE_CONTACT_DATA tri_contact_data;
GIM_TRIANGLE_DATA tri1data,tri2data;
GUINT i, ti1,ti2,ci;
int colresult;
for (i=0;i<collision_pairs.m_size; i++)
{
ti1 = pairs[i*2 + swaped]; // m_index1
ti2 = pairs[i*2 + (!swaped) ]; // m_index2
//Get triangles data
gim_trimesh_get_triangle_data_lazy(trimesh1,ti1,&tri1data);
gim_trimesh_get_triangle_data_lazy(trimesh2,ti2,&tri2data);
//collide triangles
colresult = gim_triangle_triangle_collision(&tri1data,&tri2data,&tri_contact_data);
if(colresult == 1)
{
//Add contacts
for (ci=0;ci<tri_contact_data.m_point_count ;ci++ )
{
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);
}
}
}
if(dummycontacts.m_size == 0) //reject
{
//Unlocks meshes
gim_trimesh_unlocks_work_data(trimesh1);
gim_trimesh_unlocks_work_data(trimesh2);
GIM_DYNARRAY_DESTROY(dummycontacts);
GIM_DYNARRAY_DESTROY(collision_pairs);
return;
}
//merge contacts
gim_merge_contacts(&dummycontacts,contacts);
//Terminate
GIM_DYNARRAY_DESTROY(dummycontacts);
GIM_DYNARRAY_DESTROY(collision_pairs);
//Unlocks meshes
gim_trimesh_unlocks_work_data(trimesh1);
gim_trimesh_unlocks_work_data(trimesh2);
}
//! Trimesh Plane Collisions
/*!
\param trimesh
\param plane vec4f plane
\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.
*/
void gim_trimesh_plane_collision(GIM_TRIMESH * trimesh,vec4f plane, GDYNAMIC_ARRAY * contacts)
{
contacts->m_size = 0;
char classify;
aabb3f bound;
gim_trimesh_get_aabb(trimesh,&bound);
PLANE_CLASSIFY_BOX(plane,bound,classify);
if(classify>1) return; // in front of plane
//Locks mesh
gim_trimesh_locks_work_data(trimesh);
//Get vertices
GUINT i, vertcount = gim_trimesh_get_vertex_count(trimesh);
vec3f vec;
GREAL dist;
vec4f * result_contact;
for (i=0;i<vertcount;i++)
{
gim_trimesh_get_vertex(trimesh,i,vec);
dist = DISTANCE_PLANE_POINT(plane,vec);
if(dist<=0.0f)
{
GIM_DYNARRAY_PUSH_EMPTY(vec4f,(*contacts));
result_contact = GIM_DYNARRAY_POINTER_LAST(vec4f,(*contacts));
VEC_COPY((*result_contact),vec);
(*result_contact)[3] = -dist;
}
}
gim_trimesh_unlocks_work_data(trimesh);
}

View File

@@ -1,56 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. 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.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.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, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "GIMPACT/gim_vertex_buffer_util.h"
void gim_create_common_vertex_buffer(GBUFFER_ARRAY * vertex_buffer,GUINT vertex_count)
{
gim_create_common_buffer(vertex_count*sizeof(vec3f), &vertex_buffer->m_buffer_id);
GIM_BUFFER_ARRAY_INIT_TYPE(vec3f,(*vertex_buffer),vertex_buffer->m_buffer_id,vertex_count);
}
void gim_copy_vertex_buffers(GBUFFER_ARRAY * source_vertex_buffer,GUINT source_scalar_type,GBUFFER_ARRAY * dest_vertex_buffer,GUINT dest_scalar_type)
{
GIM_PROCESS_VERTEX_BUFFER_ARRAY(0,(*source_vertex_buffer),(*dest_vertex_buffer),COPY_VEC3_KERNEL,source_scalar_type,dest_scalar_type);
}
void gim_transform_vertex_buffers(GBUFFER_ARRAY * source_vertex_buffer,GUINT source_scalar_type,GBUFFER_ARRAY * dest_vertex_buffer,GUINT dest_scalar_type, mat4f transform)
{
GIM_PROCESS_VERTEX_BUFFER_ARRAY(transform,(*source_vertex_buffer),(*dest_vertex_buffer),MULT_MAT_VEC4_KERNEL,source_scalar_type,dest_scalar_type);
}
void gim_process_vertex_buffers(GBUFFER_ARRAY * source_vertex_buffer,GUINT source_scalar_type,GBUFFER_ARRAY * dest_vertex_buffer,GUINT dest_scalar_type, void *uniform_data,gim_kernel_func kernel_func)
{
GIM_PROCESS_VERTEX_BUFFER_ARRAY(uniform_data,(*source_vertex_buffer),(*dest_vertex_buffer),kernel_func,source_scalar_type,dest_scalar_type);
}

View File

@@ -1,43 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. 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.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.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, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "GIMPACT/gimpact.h"
void gimpact_init()
{
gim_init_math();
gim_init_buffer_managers();
gim_trimesh_data_manager_init();
}
void gimpact_terminate()
{
gim_terminate_buffer_managers();
gim_trimesh_data_manager_end();
}