01 Dec 2007
This commit is contained in:
parent
ef34b85e37
commit
66a08460c1
|
@ -26,7 +26,9 @@ scroll = visible_offset
|
|||
1. не выводится текущее значение переменной в консоль
|
||||
|
||||
Смена физического движка:
|
||||
1. Первичная имплементация
|
||||
1. Первичная имплементация OK
|
||||
2. Подключить инициализацию окружения
|
||||
3. Подключить DebugDrawer
|
||||
|
||||
//==================================================
|
||||
// то, что уже готово
|
||||
|
|
|
@ -270,9 +270,9 @@ void WbspMain ( bool option )
|
|||
Msg("---- CSG ---- [%s]\n", onlyents ? "onlyents" : "normal" );
|
||||
|
||||
// delete portal and line files
|
||||
std.sprintf (path, "%s/maps/%s.prt", std.GameInfo->gamedir, gs_mapname);
|
||||
com.sprintf (path, "%s/maps/%s.prt", com.GameInfo->gamedir, gs_mapname);
|
||||
remove(path);
|
||||
std.sprintf (path, "%s/maps/%s.lin", std.GameInfo->gamedir, gs_mapname);
|
||||
com.sprintf (path, "%s/maps/%s.lin", com.GameInfo->gamedir, gs_mapname);
|
||||
remove(path);
|
||||
|
||||
// if onlyents, just grab the entites and resave
|
||||
|
@ -301,8 +301,8 @@ bool PrepareBSPModel ( const char *dir, const char *name, byte params )
|
|||
{
|
||||
int numshaders;
|
||||
|
||||
if( dir ) std.strncpy(gs_basedir, dir, sizeof(gs_basedir));
|
||||
if( name ) std.strncpy(gs_mapname, name, sizeof(gs_mapname));
|
||||
if( dir ) com.strncpy(gs_basedir, dir, sizeof(gs_basedir));
|
||||
if( name ) com.strncpy(gs_mapname, name, sizeof(gs_mapname));
|
||||
|
||||
//copy state
|
||||
onlyents = (params & BSP_ONLYENTS) ? true : false;
|
||||
|
@ -336,11 +336,11 @@ bool CompileBSPModel ( void )
|
|||
if( onlyrad && onlyvis && full_compile )
|
||||
{
|
||||
// delete all temporary files after final compile
|
||||
std.sprintf(path, "%s/maps/%s.prt", std.GameInfo->gamedir, gs_mapname);
|
||||
com.sprintf(path, "%s/maps/%s.prt", com.GameInfo->gamedir, gs_mapname);
|
||||
remove(path);
|
||||
std.sprintf(path, "%s/maps/%s.lin", std.GameInfo->gamedir, gs_mapname);
|
||||
com.sprintf(path, "%s/maps/%s.lin", com.GameInfo->gamedir, gs_mapname);
|
||||
remove(path);
|
||||
std.sprintf(path, "%s/maps/%s.log", std.GameInfo->gamedir, gs_mapname);
|
||||
com.sprintf(path, "%s/maps/%s.log", com.GameInfo->gamedir, gs_mapname);
|
||||
remove(path);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -73,7 +73,7 @@ shader_t *FindShader( char *texture )
|
|||
// look for it
|
||||
for (i = 0, texshader = shaderInfo; i < numShaderInfo; i++, texshader++)
|
||||
{
|
||||
if(!std.strcmp(shader, texshader->name))
|
||||
if(!com.strcmp(shader, texshader->name))
|
||||
return texshader;
|
||||
}
|
||||
return NULL; //no shaders for this texture
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "roqlib.h"
|
||||
|
||||
bool host_debug = false;
|
||||
stdlib_api_t std;
|
||||
stdlib_api_t com;
|
||||
byte *basepool;
|
||||
byte *zonepool;
|
||||
static double start, end;
|
||||
|
@ -190,7 +190,7 @@ launch_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, void *unused )
|
|||
{
|
||||
static launch_exp_t Com;
|
||||
|
||||
std = *input;
|
||||
com = *input;
|
||||
|
||||
// generic functions
|
||||
Com.api_size = sizeof(launch_exp_t);
|
||||
|
|
|
@ -1978,7 +1978,7 @@ void PR_ParseWarning (int type, char *error, ...)
|
|||
{
|
||||
// instead of sys error
|
||||
pr_total_error_count++;
|
||||
std.error( "internal error C%i: %s\n", type, string );
|
||||
com.error( "internal error C%i: %s\n", type, string );
|
||||
}
|
||||
else if (type > ERR_INTERNAL)
|
||||
{
|
||||
|
@ -2019,7 +2019,7 @@ void PR_Message( char *message, ... )
|
|||
_vsnprintf (string, sizeof(string) - 1, message, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
std.print( string );
|
||||
com.print( string );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -25,7 +25,7 @@ double __g_ProfilerTotalMsec;
|
|||
|
||||
void Profile_Store( void )
|
||||
{
|
||||
if (std.GameInfo->rdtsc)
|
||||
if (com.GameInfo->rdtsc)
|
||||
{
|
||||
__g_ProfilerSpare = __g_ProfilerEnd - __g_ProfilerStart - (__g_ProfilerEnd2 - __g_ProfilerEnd);
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ void Profile_Store( void )
|
|||
|
||||
void Profile_RatioResults( void )
|
||||
{
|
||||
if (std.GameInfo->rdtsc)
|
||||
if (com.GameInfo->rdtsc)
|
||||
{
|
||||
unsigned __int64 total = __g_ProfilerEnd - __g_ProfilerStart - (__g_ProfilerEnd2 - __g_ProfilerEnd);
|
||||
double ratio;
|
||||
|
@ -54,10 +54,10 @@ void Profile_RatioResults( void )
|
|||
|
||||
void _Profile_Results( const char *function )
|
||||
{
|
||||
if (std.GameInfo->rdtsc)
|
||||
if (com.GameInfo->rdtsc)
|
||||
{
|
||||
unsigned __int64 total = __g_ProfilerEnd - __g_ProfilerStart - (__g_ProfilerEnd2 - __g_ProfilerEnd);
|
||||
double msec = (double)total / std.GameInfo->tickcount;
|
||||
double msec = (double)total / com.GameInfo->tickcount;
|
||||
Msg("Profiling stats for %s()\n", function );
|
||||
Msg("----- ticks: %I64d -----\n", total);
|
||||
Msg("----- secs %f ----- \n", msec );
|
||||
|
@ -69,7 +69,7 @@ void _Profile_Results( const char *function )
|
|||
|
||||
void Profile_Time( void )
|
||||
{
|
||||
if (std.GameInfo->rdtsc)
|
||||
if (com.GameInfo->rdtsc)
|
||||
{
|
||||
Msg("Profiling results:\n");
|
||||
Msg("----- total ticks: %I64d -----\n", __g_ProfilerTotalTicks);
|
||||
|
|
|
@ -35,7 +35,7 @@ extern byte *zonepool;
|
|||
|
||||
#define Profile_Start()\
|
||||
{\
|
||||
if (std.GameInfo->rdtsc) \
|
||||
if (com.GameInfo->rdtsc) \
|
||||
{ \
|
||||
__asm pushad \
|
||||
__asm rdtsc \
|
||||
|
@ -68,14 +68,10 @@ void Profile_Store( void );
|
|||
void Profile_Time( void ); // total profile time
|
||||
#define Profile_Results( name ) _Profile_Results( #name )
|
||||
|
||||
extern stdlib_api_t std;
|
||||
extern stdlib_api_t com;
|
||||
|
||||
#define Msg std.printf
|
||||
#define MsgDev std.dprintf
|
||||
#define MsgWarn std.wprintf
|
||||
#define Sys_Error std.error
|
||||
#define Sys_DoubleTime std.Com_DoubleTime
|
||||
|
||||
#define Sys_Error com.error
|
||||
#define Malloc(size) Mem_Alloc(basepool, size)
|
||||
#define Z_Malloc(size) Mem_Alloc(zonepool, size)
|
||||
#define Free(mem) Mem_Free(mem)
|
||||
|
@ -88,10 +84,6 @@ extern byte *qccpool;
|
|||
extern byte *studiopool;
|
||||
|
||||
// misc common functions
|
||||
#define strlower std.strlwr
|
||||
#define va std.va
|
||||
#define stristr std.stristr
|
||||
|
||||
byte *ReadBMP (char *filename, byte **palette, int *width, int *height);
|
||||
|
||||
// misc
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include "editor.h"
|
||||
|
||||
stdlib_api_t std;
|
||||
stdlib_api_t com;
|
||||
|
||||
/*
|
||||
==================
|
||||
|
@ -17,13 +17,14 @@ launch_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, void *unused )
|
|||
{
|
||||
static launch_exp_t Editor;
|
||||
|
||||
std = *input;
|
||||
com = *input;
|
||||
|
||||
Editor.api_size = sizeof(launch_exp_t);
|
||||
|
||||
Editor.Init = InitEditor;
|
||||
Editor.Main = EditorMain;
|
||||
Editor.Free = FreeEditor;
|
||||
Editor.CPrint = GUI_Print;
|
||||
|
||||
return &Editor;
|
||||
}
|
|
@ -39,11 +39,8 @@ void GUI_Msg( const char *pMsg, ... );
|
|||
void GUI_MsgDev( int level, const char *pMsg, ... );
|
||||
void GUI_MsgWarn( const char *pMsg, ... );
|
||||
|
||||
extern stdlib_api_t std;
|
||||
#define Msg GUI_Msg
|
||||
#define MsgDev GUI_MsgDev
|
||||
#define MsgWarn GUI_MsgWarn
|
||||
#define Sys_Error std.error
|
||||
extern stdlib_api_t com;
|
||||
#define Sys_Error com.error
|
||||
|
||||
typedef enum {
|
||||
Action,
|
||||
|
|
|
@ -628,7 +628,7 @@ void GUI_Msg( const char *pMsg, ... )
|
|||
GUI_Print( text );
|
||||
|
||||
//echo into system console
|
||||
std.print( text );
|
||||
com.print( text );
|
||||
}
|
||||
|
||||
void GUI_MsgDev( int level, const char *pMsg, ... )
|
||||
|
@ -644,7 +644,7 @@ void GUI_MsgDev( int level, const char *pMsg, ... )
|
|||
GUI_Print( text );
|
||||
|
||||
//echo into system console
|
||||
std.print( text );
|
||||
com.print( text );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -661,7 +661,7 @@ void GUI_MsgWarn( const char *pMsg, ... )
|
|||
GUI_Print( text );
|
||||
|
||||
//echo into system console
|
||||
std.print( text );
|
||||
com.print( text );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -675,12 +675,11 @@ void GUI_Error( const char *pMsg, ... )
|
|||
va_end (argptr);
|
||||
|
||||
GUI_DisableMenus();
|
||||
GUI_Print( text );
|
||||
std.print( text );//echo into system console
|
||||
com.print( text );//echo into system console
|
||||
|
||||
//3. waiting for user input
|
||||
|
||||
//std.exit();
|
||||
//com.exit();
|
||||
}
|
||||
|
||||
void GUI_CreateMenus( void )
|
||||
|
@ -918,9 +917,6 @@ void InitEditor ( uint funcname, int argc, char **argv )
|
|||
memset( &wc, 0, sizeof( wc ));
|
||||
s_gui.gHinst = (HINSTANCE)GetModuleHandle( NULL );
|
||||
|
||||
com_argc = argc;
|
||||
memcpy(com_argv, argv, MAX_NUM_ARGVS );
|
||||
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||
wc.lpfnWndProc = WndProc;
|
||||
wc.cbClsExtra = 0;
|
||||
|
|
|
@ -7,62 +7,6 @@
|
|||
|
||||
bool debug_mode = false;
|
||||
int dev_mode = 0;
|
||||
int com_argc;
|
||||
char *com_argv[MAX_NUM_ARGVS];
|
||||
/*
|
||||
================
|
||||
CheckParm
|
||||
|
||||
Returns the position (1 to argc-1) in the program's argument list
|
||||
where the given parameter apears, or 0 if not present
|
||||
================
|
||||
*/
|
||||
int CheckParm (const char *parm)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < com_argc; i++ )
|
||||
{
|
||||
// NEXTSTEP sometimes clears appkit vars.
|
||||
if (!com_argv[i]) continue;
|
||||
if (!strcmp (parm, com_argv[i])) return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool _GetParmFromCmdLine( char *parm, char *out, size_t size )
|
||||
{
|
||||
int argc = CheckParm( parm );
|
||||
|
||||
if(!argc) return false;
|
||||
if(!out) return false;
|
||||
if(!com_argv[argc + 1]) return false;
|
||||
|
||||
strncpy( out, com_argv[argc+1], size );
|
||||
return true;
|
||||
}
|
||||
|
||||
// search case-insensitive for string2 in string
|
||||
char *stristr( const char *string, const char *string2 )
|
||||
{
|
||||
int c, len;
|
||||
c = tolower( *string2 );
|
||||
len = strlen( string2 );
|
||||
|
||||
while (string)
|
||||
{
|
||||
for ( ; *string && tolower( *string ) != c; string++ );
|
||||
if (*string)
|
||||
{
|
||||
if (strnicmp( string, string2, len ) == 0)
|
||||
break;
|
||||
string++;
|
||||
}
|
||||
else return NULL;
|
||||
}
|
||||
return (char *)string;
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ skips color escape codes
|
|||
*/
|
||||
int CG_GetBigStringWidth( const char *str )
|
||||
{
|
||||
return std.cstrlen( str ) * 16;
|
||||
return com.cstrlen( str ) * 16;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -350,7 +350,7 @@ void CG_DrawCenterString( void )
|
|||
}
|
||||
linebuffer[l] = 0;
|
||||
|
||||
w = cl.centerPrintCharWidth * std.cstrlen( linebuffer );
|
||||
w = cl.centerPrintCharWidth * com.cstrlen( linebuffer );
|
||||
x = ( SCREEN_WIDTH - w )>>1;
|
||||
|
||||
SCR_DrawStringExt( x, y, cl.centerPrintCharWidth, BIGCHAR_HEIGHT, linebuffer, color, false );
|
||||
|
@ -406,7 +406,7 @@ void CG_DrawCenterPic( int w, int h, char *picname )
|
|||
|
||||
void CG_DrawCenterStringBig( char *text, float alpha )
|
||||
{
|
||||
int xpos = (SCREEN_WIDTH - std.cstrlen(text) * BIGCHAR_WIDTH)>>1;
|
||||
int xpos = (SCREEN_WIDTH - com.cstrlen(text) * BIGCHAR_WIDTH)>>1;
|
||||
int ypos = (SCREEN_HEIGHT - BIGCHAR_HEIGHT)>>1;
|
||||
|
||||
SCR_DrawBigString(xpos, ypos, text, alpha );
|
||||
|
|
|
@ -467,7 +467,7 @@ void Con_DrawSolidConsole (float frac)
|
|||
|
||||
// draw current time
|
||||
re->SetColor(g_color_table[ColorIndex(COLOR_YELLOW)]);
|
||||
std.snprintf( curtime, MAX_QPATH, "%s ", timestamp( TIME_TIME_ONLY));
|
||||
com.snprintf( curtime, MAX_QPATH, "%s ", timestamp( TIME_TIME_ONLY));
|
||||
i = strlen( curtime );
|
||||
for (x = 0; x < i; x++)
|
||||
SCR_DrawSmallChar(scr_width->integer - ( i - x ) * SMALLCHAR_WIDTH, (lines - (SMALLCHAR_HEIGHT+SMALLCHAR_HEIGHT/2)), curtime[x]);
|
||||
|
|
|
@ -131,20 +131,20 @@ static void FindMatches( const char *s, const char *unused1, const char *unused2
|
|||
{
|
||||
int i;
|
||||
|
||||
if(std.strnicmp( s, completionString, strlen( completionString )))
|
||||
if(com.strnicmp( s, completionString, strlen( completionString )))
|
||||
return;
|
||||
|
||||
matchCount++;
|
||||
if ( matchCount == 1 )
|
||||
{
|
||||
std.strncpy( shortestMatch, s, sizeof( shortestMatch ));
|
||||
com.strncpy( shortestMatch, s, sizeof( shortestMatch ));
|
||||
return;
|
||||
}
|
||||
|
||||
// cut shortestMatch to the amount common with s
|
||||
for ( i = 0; s[i]; i++ )
|
||||
{
|
||||
if ( std.tolower(shortestMatch[i]) != tolower(s[i]))
|
||||
if ( com.tolower(shortestMatch[i]) != tolower(s[i]))
|
||||
shortestMatch[i] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ PrintMatches
|
|||
*/
|
||||
static void PrintMatches( const char *s, const char *unused1, const char *m, void *unused2 )
|
||||
{
|
||||
if(!std.strnicmp( s, shortestMatch, strlen( shortestMatch )))
|
||||
if(!com.strnicmp( s, shortestMatch, strlen( shortestMatch )))
|
||||
if(m && *m) Msg( " %s ^3\"%s\"\n", s, m );
|
||||
else Msg( " %s\n", s ); // variable or command without description
|
||||
}
|
||||
|
@ -340,7 +340,7 @@ void Field_VariableSizeDraw( field_t *edit, int x, int y, int width, int size, b
|
|||
if( key_overstrikeMode ) cursorChar = 11;
|
||||
else cursorChar = 95;
|
||||
|
||||
i = drawLen - (std.cstrlen(str) + 1);
|
||||
i = drawLen - (com.cstrlen(str) + 1);
|
||||
|
||||
if(size == SMALLCHAR_WIDTH) SCR_DrawSmallChar( x + (edit->cursor - prestep - i) * size, y, cursorChar );
|
||||
else
|
||||
|
|
|
@ -400,7 +400,7 @@ void CL_CheckForResend (void)
|
|||
if (cls.state == ca_disconnected && Host_ServerState())
|
||||
{
|
||||
cls.state = ca_connecting;
|
||||
std.strncpy (cls.servername, "localhost", sizeof(cls.servername)-1);
|
||||
com.strncpy (cls.servername, "localhost", sizeof(cls.servername)-1);
|
||||
// we don't need a challenge on the localhost
|
||||
CL_SendConnectPacket ();
|
||||
return;
|
||||
|
@ -442,7 +442,7 @@ void CL_Connect_f (void)
|
|||
if(Host_ServerState())
|
||||
{
|
||||
// if running a local server, kill it and reissue
|
||||
std.strncpy( host.finalmsg, "Server quit\n", MAX_STRING );
|
||||
com.strncpy( host.finalmsg, "Server quit\n", MAX_STRING );
|
||||
SV_Shutdown( false );
|
||||
}
|
||||
else CL_Disconnect();
|
||||
|
|
|
@ -285,12 +285,12 @@ void SCR_DrawFPS( void )
|
|||
|
||||
if ((red = (calc < 1.0f)))
|
||||
{
|
||||
std.snprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
|
||||
com.snprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
|
||||
color = g_color_table[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
std.snprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
|
||||
com.snprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
|
||||
color = g_color_table[3];
|
||||
}
|
||||
SCR_DrawBigStringColor(SCREEN_WIDTH - 146, SCREEN_HEIGHT - 32, fpsstring, color );
|
||||
|
|
|
@ -380,8 +380,7 @@ void CL_PrepRefresh( void )
|
|||
// set sky textures and speed
|
||||
SCR_UpdateScreen();
|
||||
rotate = atof(cl.configstrings[CS_SKYROTATE]);
|
||||
std.atov( axis, cl.configstrings[CS_SKYAXIS], 3 );
|
||||
Msg("Sky Vector %g %g %g\n", axis[0], axis[1], axis[2] );
|
||||
com.atov( axis, cl.configstrings[CS_SKYAXIS], 3 );
|
||||
re->SetSky( cl.configstrings[CS_SKY], rotate, axis);
|
||||
Cvar_SetValue("scr_loading", 100.0f ); // all done
|
||||
|
||||
|
|
|
@ -1746,7 +1746,7 @@ cmodel_t *CM_StudioModel( char *name, edict_t *ent, byte *buffer)
|
|||
out = &map_cmodels[numcmodels + numsmodels];
|
||||
out->extradata = buffer;
|
||||
out->numframes = 0;//reset sprite info
|
||||
std.strncpy(out->name, name, sizeof(out->name));
|
||||
com.strncpy(out->name, name, sizeof(out->name));
|
||||
if(!out->mempool) out->mempool = Mem_AllocPool( out->name );// create pool
|
||||
else Mem_EmptyPool( out->mempool ); // clear pool
|
||||
|
||||
|
@ -1772,7 +1772,7 @@ cmodel_t *CM_SpriteModel( char *name, edict_t *ent, byte *buffer)
|
|||
|
||||
out = &map_cmodels[numcmodels + numsmodels];
|
||||
out->numframes = phdr->numframes;
|
||||
std.strncpy(out->name, name, sizeof(out->name));
|
||||
com.strncpy(out->name, name, sizeof(out->name));
|
||||
if(out->mempool) Mem_EmptyPool( out->mempool ); // clear pool
|
||||
else out->mempool = Mem_AllocPool( out->name ); // create pool
|
||||
|
||||
|
@ -1800,7 +1800,7 @@ cmodel_t *CM_LoadModel( edict_t *ent )
|
|||
for(i = numsmodels; i < max_models; i++ )
|
||||
{
|
||||
mod = &map_cmodels[i];
|
||||
if(!std.strcmp(name, mod->name))
|
||||
if(!com.strcmp(name, mod->name))
|
||||
return mod;
|
||||
}
|
||||
|
||||
|
|
|
@ -278,7 +278,7 @@ bool Cmd_GetMapList (const char *s, char *completedname, int length )
|
|||
int ver = -1, lumpofs = 0, lumplen = 0;
|
||||
const char *ext = FS_FileExtension( t->filenames[i] );
|
||||
|
||||
if( std.stricmp(ext, "bsp" )) continue;
|
||||
if( com.stricmp(ext, "bsp" )) continue;
|
||||
|
||||
strncpy(message, "^1error^7", sizeof(message));
|
||||
f = FS_Open(t->filenames[i], "rb" );
|
||||
|
@ -322,7 +322,7 @@ bool Cmd_GetMapList (const char *s, char *completedname, int length )
|
|||
}
|
||||
}
|
||||
|
||||
std.strncpy(entfilename, t->filenames[i], sizeof(entfilename));
|
||||
com.strncpy(entfilename, t->filenames[i], sizeof(entfilename));
|
||||
FS_StripExtension( entfilename );
|
||||
FS_DefaultExtension( entfilename, ".ent" );
|
||||
entities = (char *)FS_LoadFile(entfilename, NULL);
|
||||
|
@ -414,7 +414,7 @@ bool Cmd_GetDemoList (const char *s, char *completedname, int length )
|
|||
{
|
||||
const char *ext = FS_FileExtension( t->filenames[i] );
|
||||
|
||||
if( std.stricmp(ext, "dem" )) continue;
|
||||
if( com.stricmp(ext, "dem" )) continue;
|
||||
FS_FileBase(t->filenames[i], matchbuf );
|
||||
Msg("%16s\n", matchbuf );
|
||||
numdems++;
|
||||
|
@ -459,7 +459,7 @@ bool Cmd_GetMovieList (const char *s, char *completedname, int length )
|
|||
{
|
||||
const char *ext = FS_FileExtension( t->filenames[i] );
|
||||
|
||||
if( std.stricmp(ext, "roq" )) continue;
|
||||
if( com.stricmp(ext, "roq" )) continue;
|
||||
FS_FileBase(t->filenames[i], matchbuf );
|
||||
Msg("%16s\n", matchbuf );
|
||||
nummovies++;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "keycodes.h"
|
||||
#include "collision.h"
|
||||
|
||||
extern stdlib_api_t std;
|
||||
extern stdlib_api_t com;
|
||||
extern physic_exp_t *pe;
|
||||
extern byte *zonepool;
|
||||
|
||||
|
@ -85,16 +85,6 @@ memory manager
|
|||
#define Z_Malloc(size) Mem_Alloc(zonepool, size)
|
||||
#define Z_Free(data) Mem_Free(data)
|
||||
|
||||
/*
|
||||
===========================================
|
||||
System Events
|
||||
===========================================
|
||||
*/
|
||||
|
||||
#define Msg Host_Printf
|
||||
#define MsgDev Host_DPrintf
|
||||
#define MsgWarn Host_DWarnf
|
||||
|
||||
/*
|
||||
===========================================
|
||||
Host Interface
|
||||
|
@ -111,9 +101,6 @@ void Host_AbortCurrentFrame( void );
|
|||
|
||||
// message functions
|
||||
void Host_Print(const char *txt);
|
||||
void Host_Printf(const char *fmt, ...);
|
||||
void Host_DPrintf(int level, const char *fmt, ...);
|
||||
void Host_DWarnf( const char *fmt, ...);
|
||||
void Host_Error( const char *error, ... );
|
||||
|
||||
// host dlls managment
|
||||
|
@ -127,7 +114,6 @@ void Host_Error_f( void );
|
|||
System utilites
|
||||
===========================================
|
||||
*/
|
||||
double Sys_DoubleTime( void );
|
||||
void Sys_Error( const char *msg, ... );
|
||||
void Sys_SendKeyEvents( void );
|
||||
|
||||
|
|
111
engine/host.c
111
engine/host.c
|
@ -13,7 +13,7 @@
|
|||
physic_exp_t *pe;
|
||||
render_exp_t *re;
|
||||
host_parm_t host; // host parms
|
||||
stdlib_api_t std, newstd;
|
||||
stdlib_api_t com, newcom;
|
||||
|
||||
byte *zonepool;
|
||||
char *buildstring = __TIME__ " " __DATE__;
|
||||
|
@ -89,17 +89,10 @@ void Host_InitCommon( uint funcname, int argc, char **argv )
|
|||
{
|
||||
char dev_level[4];
|
||||
|
||||
newstd = std;
|
||||
newcom = com;
|
||||
|
||||
// overload some funcs
|
||||
newstd.print = Host_Print;
|
||||
newstd.printf = Host_Printf;
|
||||
newstd.dprintf = Host_DPrintf;
|
||||
newstd.wprintf = Host_DWarnf;
|
||||
newstd.error = Host_Error;
|
||||
|
||||
// callback
|
||||
std.Cmd_ForwardToServer = Cmd_ForwardToServer;
|
||||
newcom.error = Host_Error;
|
||||
|
||||
// determine debug and developer mode
|
||||
if(FS_CheckParm ("-debug")) host.debug = true;
|
||||
|
@ -129,7 +122,7 @@ void Host_InitPhysic( void )
|
|||
Sys_LoadLibrary( &physic_dll );
|
||||
|
||||
CreatePhysic = (void *)physic_dll.main;
|
||||
pe = CreatePhysic( &newstd, &pi );
|
||||
pe = CreatePhysic( &newcom, &pi );
|
||||
|
||||
pe->Init();
|
||||
}
|
||||
|
@ -158,7 +151,7 @@ void Host_InitRender( void )
|
|||
Sys_LoadLibrary( &render_dll );
|
||||
|
||||
CreateRender = (void *)render_dll.main;
|
||||
re = CreateRender( &newstd, &ri );
|
||||
re = CreateRender( &newcom, &ri );
|
||||
|
||||
if(!re->Init(GetModuleHandle(NULL), Host_WndProc ))
|
||||
Sys_Error("VID_InitRender: can't init render.dll\nUpdate your opengl drivers\n");
|
||||
|
@ -412,95 +405,7 @@ void Host_Print( const char *txt )
|
|||
strcat (host.rd.buffer, txt);
|
||||
return;
|
||||
}
|
||||
|
||||
Con_Print( txt ); // echo to client console
|
||||
Sys_Print( txt ); // echo to system console
|
||||
// sys print also stored messages into system log
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Host_Printf
|
||||
|
||||
Both client and server can use this, and it will output
|
||||
to the apropriate place.
|
||||
=============
|
||||
*/
|
||||
void Host_Printf( const char *fmt, ... )
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAX_INPUTLINE];
|
||||
|
||||
va_start( argptr, fmt );
|
||||
vsprintf( msg, fmt, argptr );
|
||||
va_end( argptr );
|
||||
|
||||
Host_Print( msg );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Host_DPrintf
|
||||
|
||||
A Msg that only shows up in developer mode
|
||||
================
|
||||
*/
|
||||
void Host_DPrintf( int level, const char *fmt, ... )
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAX_INPUTLINE];
|
||||
|
||||
// don't confuse non-developers with techie stuff...
|
||||
if(host.developer < level) return;
|
||||
|
||||
va_start( argptr, fmt );
|
||||
vsprintf( msg, fmt, argptr );
|
||||
va_end( argptr );
|
||||
|
||||
switch(level)
|
||||
{
|
||||
case D_INFO:
|
||||
Host_Print( msg );
|
||||
break;
|
||||
case D_WARN:
|
||||
Host_Print(va("^3Warning:^7 %s", msg));
|
||||
break;
|
||||
case D_ERROR:
|
||||
Host_Print(va("^1Error:^7 %s", msg));
|
||||
break;
|
||||
case D_LOAD:
|
||||
Host_Print(va("^2Loading: ^7%s", msg));
|
||||
break;
|
||||
case D_NOTE:
|
||||
Host_Print( msg );
|
||||
break;
|
||||
case D_MEMORY:
|
||||
Host_Print(va("^6Mem: ^7%s", msg));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Host_DWarnf
|
||||
|
||||
A Warning that only shows up in debug mode
|
||||
================
|
||||
*/
|
||||
void Host_DWarnf( const char *fmt, ... )
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAX_INPUTLINE];
|
||||
|
||||
// don't confuse non-developers with techie stuff...
|
||||
if (!host.debug) return;
|
||||
|
||||
va_start( argptr, fmt );
|
||||
vsprintf( msg, fmt, argptr );
|
||||
va_end( argptr );
|
||||
|
||||
Host_Print(va("^3Warning:^7 %s", msg));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -521,7 +426,7 @@ void Host_Error( const char *error, ... )
|
|||
|
||||
if( host.framecount < 3 || host.state == HOST_SHUTDOWN )
|
||||
Sys_Error ("%s", hosterror1 );
|
||||
else Host_Printf("Host_Error: %s", hosterror1);
|
||||
else Msg("Host_Error: %s", hosterror1);
|
||||
|
||||
if(recursive)
|
||||
{
|
||||
|
@ -532,7 +437,7 @@ void Host_Error( const char *error, ... )
|
|||
|
||||
recursive = true;
|
||||
sprintf( host.finalmsg, "Server crashed: %s\n", hosterror1 );
|
||||
std.strncpy( host.finalmsg, "Server shutdown\n", MAX_STRING );
|
||||
com.strncpy( host.finalmsg, "Server shutdown\n", MAX_STRING );
|
||||
|
||||
SV_Shutdown( false );
|
||||
CL_Drop(); // drop clients
|
||||
|
@ -640,7 +545,7 @@ void Host_Main( void )
|
|||
|
||||
// prepare host to normal shutdown
|
||||
host.state = HOST_SHUTDOWN;
|
||||
std.strncpy( host.finalmsg, "Server shutdown\n", MAX_STRING );
|
||||
com.strncpy( host.finalmsg, "Server shutdown\n", MAX_STRING );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ void SV_Map_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
std.snprintf( filename, MAX_QPATH, "%s.bsp", Cmd_Argv(1));
|
||||
com.snprintf( filename, MAX_QPATH, "%s.bsp", Cmd_Argv(1));
|
||||
if(!FS_FileExists(va("maps/%s", filename )))
|
||||
{
|
||||
Msg("Can't loading %s\n", filename );
|
||||
|
@ -135,7 +135,7 @@ void SV_Map_f( void )
|
|||
SV_BroadcastCommand ("reconnect\n");
|
||||
|
||||
// archive server state
|
||||
std.strncpy (svs.mapcmd, filename, sizeof(svs.mapcmd) - 1);
|
||||
com.strncpy (svs.mapcmd, filename, sizeof(svs.mapcmd) - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -155,7 +155,7 @@ void SV_Demo_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
std.snprintf( filename, MAX_QPATH, "%s.dem", Cmd_Argv(1));
|
||||
com.snprintf( filename, MAX_QPATH, "%s.dem", Cmd_Argv(1));
|
||||
if(!FS_FileExists(va("demos/%s", filename )))
|
||||
{
|
||||
Msg("Can't loading %s\n", filename );
|
||||
|
@ -187,7 +187,7 @@ void SV_Movie_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
std.snprintf( filename, MAX_QPATH, "%s.roq", Cmd_Argv(1));
|
||||
com.snprintf( filename, MAX_QPATH, "%s.roq", Cmd_Argv(1));
|
||||
if(!FS_FileExists(va("video/%s", filename )))
|
||||
{
|
||||
Msg("Can't loading %s\n", filename );
|
||||
|
@ -216,7 +216,7 @@ void SV_Load_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
std.snprintf( filename, MAX_QPATH, "%s.bin", Cmd_Argv(1));
|
||||
com.snprintf( filename, MAX_QPATH, "%s.bin", Cmd_Argv(1));
|
||||
if(!FS_FileExists(va("save/%s", filename )))
|
||||
{
|
||||
Msg("Can't loading %s\n", filename );
|
||||
|
@ -245,7 +245,7 @@ void SV_Save_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
std.snprintf( filename, MAX_QPATH, "%s.bin", Cmd_Argv(1));
|
||||
com.snprintf( filename, MAX_QPATH, "%s.bin", Cmd_Argv(1));
|
||||
SV_WriteSaveFile( filename );
|
||||
}
|
||||
|
||||
|
@ -267,7 +267,7 @@ void SV_ChangeLevel_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
std.snprintf( filename, MAX_QPATH, "%s.bsp", Cmd_Argv(1));
|
||||
com.snprintf( filename, MAX_QPATH, "%s.bsp", Cmd_Argv(1));
|
||||
if(!FS_FileExists(va("maps/%s", filename )))
|
||||
{
|
||||
Msg("Can't loading %s\n", filename );
|
||||
|
@ -303,7 +303,7 @@ void SV_ChangeLevel_f( void )
|
|||
SV_BroadcastCommand ("reconnect\n");
|
||||
|
||||
// archive server state
|
||||
std.strncpy (svs.mapcmd, filename, sizeof(svs.mapcmd) - 1);
|
||||
com.strncpy (svs.mapcmd, filename, sizeof(svs.mapcmd) - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -394,7 +394,7 @@ void SV_Status_f( void )
|
|||
}
|
||||
|
||||
Msg("%s", cl->name );
|
||||
l = 16 - std.strlen(cl->name);
|
||||
l = 16 - com.strlen(cl->name);
|
||||
for (j = 0; j < l; j++) Msg (" ");
|
||||
Msg ("%.5f ", svs.realtime - cl->lastmessage );
|
||||
s = NET_AdrToString ( cl->netchan.remote_address);
|
||||
|
@ -426,9 +426,9 @@ void SV_ConSay_f( void )
|
|||
if(*p == '"')
|
||||
{
|
||||
p++;
|
||||
p[std.strlen(p) - 1] = 0;
|
||||
p[com.strlen(p) - 1] = 0;
|
||||
}
|
||||
std.strncat(text, p, MAX_SYSPATH );
|
||||
com.strncat(text, p, MAX_SYSPATH );
|
||||
|
||||
for (i = 0, client = svs.clients; i < maxclients->integer; i++, client++)
|
||||
{
|
||||
|
@ -492,7 +492,7 @@ Kick everyone off, possibly in preparation for a new game
|
|||
void SV_KillServer_f (void)
|
||||
{
|
||||
if(!svs.initialized) return;
|
||||
std.strncpy( host.finalmsg, "Server was killed\n", MAX_STRING );
|
||||
com.strncpy( host.finalmsg, "Server was killed\n", MAX_STRING );
|
||||
SV_Shutdown( false );
|
||||
NET_Config( false );// close network sockets
|
||||
}
|
||||
|
|
|
@ -259,7 +259,7 @@ void SV_InitGame (void)
|
|||
if( svs.initialized )
|
||||
{
|
||||
// cause any connected clients to reconnect
|
||||
std.strncpy( host.finalmsg, "Server restarted\n", MAX_STRING );
|
||||
com.strncpy( host.finalmsg, "Server restarted\n", MAX_STRING );
|
||||
SV_Shutdown( true );
|
||||
}
|
||||
else
|
||||
|
|
|
@ -25,8 +25,8 @@ static void Cvar_AddToBuffer(const char *name, const char *string, const char *b
|
|||
MsgDev(D_NOTE, "cvar too long: %s = %s\n", name, string);
|
||||
return;
|
||||
}
|
||||
*bufsize = std.strpack((char *)buffer, *bufsize, (char *)name, strlen(name));
|
||||
*bufsize = std.strpack((char *)buffer, *bufsize, (char *)string, strlen(string));
|
||||
*bufsize = com.strpack((char *)buffer, *bufsize, (char *)name, strlen(name));
|
||||
*bufsize = com.strpack((char *)buffer, *bufsize, (char *)string, strlen(string));
|
||||
}
|
||||
|
||||
void SV_AddCvarLump( dsavehdr_t *hdr, file_t *f )
|
||||
|
@ -48,8 +48,8 @@ void SV_AddCStrLump( dsavehdr_t *hdr, file_t *f )
|
|||
// pack the cfg string data
|
||||
for(i = 0; i < MAX_CONFIGSTRINGS; i++)
|
||||
{
|
||||
stringsize = bound(0, std.strlen(sv.configstrings[i]), MAX_QPATH);
|
||||
bufsize = std.strpack(csbuffer, bufsize, sv.configstrings[i], stringsize );
|
||||
stringsize = bound(0, com.strlen(sv.configstrings[i]), MAX_QPATH);
|
||||
bufsize = com.strpack(csbuffer, bufsize, sv.configstrings[i], stringsize );
|
||||
}
|
||||
SV_AddSaveLump( hdr, f, LUMP_CFGSTRING, csbuffer, bufsize );
|
||||
Z_Free( csbuffer ); // free memory
|
||||
|
@ -123,7 +123,7 @@ void SV_WriteSaveFile( char *name )
|
|||
return;
|
||||
}
|
||||
|
||||
if(!std.strcmp(name, "save0.bin")) autosave = true;
|
||||
if(!com.strcmp(name, "save0.bin")) autosave = true;
|
||||
sprintf (path, "save/%s", name );
|
||||
savfile = FS_Open( path, "wb");
|
||||
|
||||
|
@ -182,8 +182,8 @@ void Sav_LoadCvars( lump_t *l )
|
|||
|
||||
while(pos < size)
|
||||
{
|
||||
pos = std.strunpack( in, pos, name );
|
||||
pos = std.strunpack( in, pos, string );
|
||||
pos = com.strunpack( in, pos, name );
|
||||
pos = com.strunpack( in, pos, string );
|
||||
Cvar_SetLatched(name, string);
|
||||
}
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ void Sav_LoadCfgString( lump_t *l )
|
|||
// unpack the cfg string data
|
||||
for(i = 0; i < MAX_CONFIGSTRINGS; i++)
|
||||
{
|
||||
pos = std.strunpack( in, pos, sv.configstrings[i] );
|
||||
pos = com.strunpack( in, pos, sv.configstrings[i] );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,7 +386,7 @@ bool Menu_ReadComment( char *comment, int savenum )
|
|||
|
||||
sav_base = (byte *)header;
|
||||
Sav_LoadComment(&header->lumps[LUMP_COMMENTS]);
|
||||
std.strncpy( comment, svs.comment, MAX_QPATH );
|
||||
com.strncpy( comment, svs.comment, MAX_QPATH );
|
||||
Mem_Free( savfile );
|
||||
|
||||
return true;
|
||||
|
|
|
@ -241,7 +241,7 @@ float *SV_GetModelVerts( sv_edict_t *ent, int *numvertices )
|
|||
|
||||
bool SV_CreateMeshBuffer( edict_t *in, cmodel_t *out )
|
||||
{
|
||||
int i, j;
|
||||
//int i, j;
|
||||
|
||||
// validate args
|
||||
if(!in || !out || !out->extradata)
|
||||
|
@ -260,7 +260,7 @@ bool SV_CreateMeshBuffer( edict_t *in, cmodel_t *out )
|
|||
CM_RoundUpHullSize(out->maxs, false ); // normalize maxs ( ceil )
|
||||
|
||||
Msg("create physmesh for %s\n", out->name );
|
||||
for( i = 0; i < m_BodyCount; i++)
|
||||
/*for( i = 0; i < m_BodyCount; i++)
|
||||
{
|
||||
// clear count
|
||||
iNumVertices = 0;
|
||||
|
@ -278,7 +278,7 @@ bool SV_CreateMeshBuffer( edict_t *in, cmodel_t *out )
|
|||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
MsgDev(D_ERROR, "m_pSubModel == NULL" );
|
||||
Sys_Error("m_pSubModel == NULL" );
|
||||
}
|
||||
if(iNumVertices)
|
||||
{
|
||||
|
@ -286,6 +286,7 @@ bool SV_CreateMeshBuffer( edict_t *in, cmodel_t *out )
|
|||
Mem_Copy(out->physmesh[i].verts,m_pModelVerts, iNumVertices * sizeof(vec3_t));
|
||||
out->physmesh[i].numverts = iNumVertices;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
|
@ -37,7 +37,7 @@ void Sys_Error( const char *error, ... )
|
|||
va_list argptr;
|
||||
|
||||
va_start( argptr, error );
|
||||
std.vsprintf( errorstring, error, argptr );
|
||||
com.vsprintf( errorstring, error, argptr );
|
||||
va_end( argptr );
|
||||
|
||||
// don't multiple executes
|
||||
|
@ -55,7 +55,7 @@ void Sys_Error( const char *error, ... )
|
|||
host.state = HOST_ERROR; // lock shutdown state
|
||||
Host_FreeRender();
|
||||
|
||||
std.error("%s", errorstring );
|
||||
com.error("%s", errorstring );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -74,13 +74,6 @@ void Sys_SendKeyEvents (void)
|
|||
|
||||
}
|
||||
|
||||
double Sys_DoubleTime( void )
|
||||
{
|
||||
// precision timer
|
||||
host.realtime = std.Com_DoubleTime();
|
||||
return host.realtime;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
DllMain
|
||||
|
@ -91,13 +84,15 @@ launch_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, void *unused )
|
|||
{
|
||||
static launch_exp_t Host;
|
||||
|
||||
std = *input;
|
||||
com = *input;
|
||||
|
||||
Host.api_size = sizeof(launch_exp_t);
|
||||
|
||||
Host.Init = Host_Init;
|
||||
Host.Main = Host_Main;
|
||||
Host.Free = Host_Free;
|
||||
Host.Cmd = Cmd_ForwardToServer;
|
||||
Host.CPrint = Host_Print;
|
||||
|
||||
return &Host;
|
||||
}
|
|
@ -1348,7 +1348,7 @@ void M_Credits_MenuDraw( void )
|
|||
{
|
||||
// skip not visible lines, but always draw end line
|
||||
if( y <= -16 && i != credit_numlines - 1) continue;
|
||||
x = ( SCREEN_WIDTH - BIGCHAR_WIDTH * std.cstrlen( credits[i] ))/2;
|
||||
x = ( SCREEN_WIDTH - BIGCHAR_WIDTH * com.cstrlen( credits[i] ))/2;
|
||||
|
||||
if((y < (SCREEN_HEIGHT - BIGCHAR_HEIGHT) / 2) && i == credit_numlines - 1)
|
||||
{
|
||||
|
@ -1419,7 +1419,7 @@ void M_Menu_Credits_f( void )
|
|||
|
||||
// run credits
|
||||
credits_start_time = cls.realtime;
|
||||
credits_show_time = bound(0.1f, (float)std.strlen(credits[credit_numlines - 1]), 12.0f );
|
||||
credits_show_time = bound(0.1f, (float)com.strlen(credits[credit_numlines - 1]), 12.0f );
|
||||
credits_fade_time = 0.0f;
|
||||
M_PushMenu( M_Credits_MenuDraw, M_Credits_Key);
|
||||
}
|
||||
|
@ -1783,12 +1783,12 @@ void M_AddToServerList (netadr_t adr, char *info)
|
|||
// ignore if duplicated
|
||||
for (i = 0; i < m_num_servers; i++)
|
||||
{
|
||||
if (!std.strcmp(info, local_server_names[i]))
|
||||
if (!com.strcmp(info, local_server_names[i]))
|
||||
return;
|
||||
}
|
||||
|
||||
local_server_netadr[m_num_servers] = adr;
|
||||
std.strncpy (local_server_names[m_num_servers], info, sizeof(local_server_names[0])-1);
|
||||
com.strncpy (local_server_names[m_num_servers], info, sizeof(local_server_names[0])-1);
|
||||
m_num_servers++;
|
||||
}
|
||||
|
||||
|
@ -1800,11 +1800,11 @@ void JoinServerFunc( void *self )
|
|||
|
||||
index = (menuaction_s *)self - s_joinserver_server_actions;
|
||||
|
||||
if(!std.stricmp( local_server_names[index], NO_SERVER_STRING ))
|
||||
if(!com.stricmp( local_server_names[index], NO_SERVER_STRING ))
|
||||
return;
|
||||
if(index >= m_num_servers) return;
|
||||
|
||||
std.sprintf(buffer, "connect %s\n", NET_AdrToString(local_server_netadr[index]));
|
||||
com.sprintf(buffer, "connect %s\n", NET_AdrToString(local_server_netadr[index]));
|
||||
Cbuf_AddText(buffer);
|
||||
M_ForceMenuOff();
|
||||
}
|
||||
|
@ -1820,7 +1820,7 @@ void SearchLocalGames( void )
|
|||
|
||||
m_num_servers = 0;
|
||||
for (i = 0; i < MAX_LOCAL_SERVERS; i++)
|
||||
std.strcpy(local_server_names[i], NO_SERVER_STRING);
|
||||
com.strcpy(local_server_names[i], NO_SERVER_STRING);
|
||||
|
||||
M_DrawTextBox( 8, 120 - 48, 36, 3 );
|
||||
M_Print( 16 + 16, 120 - 48 + 8, "Searching for local servers, this" );
|
||||
|
@ -1868,7 +1868,7 @@ void JoinServer_MenuInit( void )
|
|||
for( i = 0; i < MAX_LOCAL_SERVERS; i++ )
|
||||
{
|
||||
s_joinserver_server_actions[i].generic.type = MTYPE_ACTION;
|
||||
std.strcpy (local_server_names[i], NO_SERVER_STRING);
|
||||
com.strcpy (local_server_names[i], NO_SERVER_STRING);
|
||||
s_joinserver_server_actions[i].generic.name = local_server_names[i];
|
||||
s_joinserver_server_actions[i].generic.flags = QMF_LEFT_JUSTIFY;
|
||||
s_joinserver_server_actions[i].generic.x = 0;
|
||||
|
@ -1959,7 +1959,7 @@ void StartServerActionFunc( void *self )
|
|||
int fraglimit;
|
||||
int maxclients;
|
||||
|
||||
std.strcpy( startmap, strchr( mapnames[s_startmap_list.curvalue], '\n' ) + 1 );
|
||||
com.strcpy( startmap, strchr( mapnames[s_startmap_list.curvalue], '\n' ) + 1 );
|
||||
maxclients = atoi( s_maxclients_field.field.buffer );
|
||||
timelimit = atoi( s_timelimit_field.field.buffer );
|
||||
fraglimit = atoi( s_fraglimit_field.field.buffer );
|
||||
|
@ -2040,7 +2040,7 @@ bool Menu_CheckMapsList( void )
|
|||
break;
|
||||
}
|
||||
}
|
||||
std.strncpy(entfilename, t->filenames[i], sizeof(entfilename));
|
||||
com.strncpy(entfilename, t->filenames[i], sizeof(entfilename));
|
||||
FS_StripExtension( entfilename );
|
||||
FS_DefaultExtension( entfilename, ".ent" );
|
||||
entities = (char *)FS_LoadFile(entfilename, NULL);
|
||||
|
@ -2057,7 +2057,7 @@ bool Menu_CheckMapsList( void )
|
|||
// means there is no title, so clear the message string now
|
||||
message[0] = 0;
|
||||
data = entities;
|
||||
std.strncpy(message, "No Title", MAX_QPATH);
|
||||
com.strncpy(message, "No Title", MAX_QPATH);
|
||||
|
||||
while(Com_ParseToken(&data))
|
||||
{
|
||||
|
@ -2068,14 +2068,14 @@ bool Menu_CheckMapsList( void )
|
|||
// get the message contents
|
||||
Com_ParseToken(&data);
|
||||
if(!strcmp(com_token, "" )) continue;
|
||||
std.strncpy(message, com_token, sizeof(message));
|
||||
com.strncpy(message, com_token, sizeof(message));
|
||||
}
|
||||
else if(!strcmp(com_token, "classname" ))
|
||||
{
|
||||
Com_ParseToken(&data);
|
||||
if(!std.strcmp(com_token, "info_player_deatchmatch"))
|
||||
if(!com.strcmp(com_token, "info_player_deatchmatch"))
|
||||
num_spawnpoints++;
|
||||
else if(!std.strcmp(com_token, "info_player_start"))
|
||||
else if(!com.strcmp(com_token, "info_player_start"))
|
||||
num_spawnpoints++;
|
||||
}
|
||||
if(num_spawnpoints > 0) break; // valid map
|
||||
|
@ -2086,8 +2086,8 @@ bool Menu_CheckMapsList( void )
|
|||
if( f ) FS_Close(f);
|
||||
|
||||
// format: mapname "maptitle"/r
|
||||
std.sprintf(string, "%s \"%s\"\r", mapname, message );
|
||||
std.strcat(buffer, string); // add new string
|
||||
com.sprintf(string, "%s \"%s\"\r", mapname, message );
|
||||
com.strcat(buffer, string); // add new string
|
||||
}
|
||||
}
|
||||
if( t ) Z_Free(t); // free search result
|
||||
|
@ -2152,11 +2152,11 @@ void StartServer_MenuInit( void )
|
|||
char scratch[200];
|
||||
int j, l;
|
||||
|
||||
std.strncpy( shortname, Com_ParseToken( &s ), MAX_TOKEN_CHARS );
|
||||
l = std.strlen(shortname);
|
||||
for (j = 0; j < l; j++) shortname[j] = std.toupper(shortname[j]);
|
||||
std.strncpy( longname, Com_ParseToken( &s ), MAX_TOKEN_CHARS );
|
||||
std.snprintf( scratch, 200, "%s\n%s", longname, shortname );
|
||||
com.strncpy( shortname, Com_ParseToken( &s ), MAX_TOKEN_CHARS );
|
||||
l = com.strlen(shortname);
|
||||
for (j = 0; j < l; j++) shortname[j] = com.toupper(shortname[j]);
|
||||
com.strncpy( longname, Com_ParseToken( &s ), MAX_TOKEN_CHARS );
|
||||
com.snprintf( scratch, 200, "%s\n%s", longname, shortname );
|
||||
|
||||
mapnames[i] = Z_Malloc( strlen( scratch ) + 1 );
|
||||
strcpy( mapnames[i], scratch );
|
||||
|
|
|
@ -264,7 +264,7 @@ void VM_M_findkeysforcommand(void)
|
|||
(ret = VM_GetTempString())[0] = 0;
|
||||
|
||||
M_FindKeysForCommand((char *)cmd, keys);
|
||||
for(i = 0; i < 2; i++) std.strncat(ret, va(" \'%i\'", keys[i]), VM_STRINGTEMP_LENGTH);
|
||||
for(i = 0; i < 2; i++) com.strncat(ret, va(" \'%i\'", keys[i]), VM_STRINGTEMP_LENGTH);
|
||||
PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(ret);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ void UI_Error(const char *format, ...)
|
|||
va_list argptr;
|
||||
|
||||
va_start( argptr, format );
|
||||
std.vsnprintf(errorstring, sizeof(errorstring), format, argptr);
|
||||
com.vsnprintf(errorstring, sizeof(errorstring), format, argptr);
|
||||
va_end( argptr );
|
||||
Host_Error( "Menu_Error: %s\n", errorstring );
|
||||
|
||||
|
|
|
@ -870,7 +870,7 @@ void PRVM_ED_ParseGlobals (const char *data)
|
|||
PRVM_ERROR ("PRVM_ED_ParseGlobals: EOF without closing brace\n");
|
||||
if (com_token[0] == '}') break;
|
||||
if (com_token[0] == '{') continue;
|
||||
std.strncpy (keyname, com_token, sizeof(keyname));
|
||||
com.strncpy (keyname, com_token, sizeof(keyname));
|
||||
|
||||
// parse value
|
||||
if (!Com_ParseToken(&data))
|
||||
|
@ -1074,10 +1074,10 @@ const char *PRVM_ED_ParseEdict (const char *data, edict_t *ent)
|
|||
}
|
||||
else anglehack = false;
|
||||
|
||||
std.strncpy (keyname, com_token, sizeof(keyname));
|
||||
com.strncpy (keyname, com_token, sizeof(keyname));
|
||||
|
||||
// another hack to fix keynames with trailing spaces
|
||||
n = std.strlen(keyname);
|
||||
n = com.strlen(keyname);
|
||||
while(n && keyname[n-1] == ' ')
|
||||
{
|
||||
keyname[n-1] = 0;
|
||||
|
@ -1108,8 +1108,8 @@ const char *PRVM_ED_ParseEdict (const char *data, edict_t *ent)
|
|||
{
|
||||
char temp[32];
|
||||
|
||||
std.strncpy( temp, com_token, sizeof(temp));
|
||||
std.sprintf( com_token, "0 %s 0", temp );
|
||||
com.strncpy( temp, com_token, sizeof(temp));
|
||||
com.sprintf( com_token, "0 %s 0", temp );
|
||||
}
|
||||
if(!PRVM_ED_ParseEpair(ent, key, com_token)) PRVM_ERROR ("PRVM_ED_ParseEdict: parse error");
|
||||
}
|
||||
|
@ -1974,12 +1974,12 @@ int PRVM_GetProgNr()
|
|||
|
||||
void *_PRVM_Alloc(size_t buffersize, const char *filename, int fileline)
|
||||
{
|
||||
return std.malloc(prog->progs_mempool, buffersize, filename, fileline);
|
||||
return com.malloc(prog->progs_mempool, buffersize, filename, fileline);
|
||||
}
|
||||
|
||||
void _PRVM_Free(void *buffer, const char *filename, int fileline)
|
||||
{
|
||||
std.free(buffer, filename, fileline);
|
||||
com.free(buffer, filename, fileline);
|
||||
}
|
||||
|
||||
void _PRVM_FreeAll(const char *filename, int fileline)
|
||||
|
@ -1987,7 +1987,7 @@ void _PRVM_FreeAll(const char *filename, int fileline)
|
|||
prog->progs = NULL;
|
||||
prog->fielddefs = NULL;
|
||||
prog->functions = NULL;
|
||||
std.clearpool(prog->progs_mempool, filename, fileline);
|
||||
com.clearpool(prog->progs_mempool, filename, fileline);
|
||||
}
|
||||
|
||||
// LordHavoc: turned PRVM_EDICT_NUM into a #define for speed reasons
|
||||
|
|
|
@ -568,7 +568,7 @@ void Cmd_ExecuteString( const char *text )
|
|||
if(Cvar_Command()) return;
|
||||
|
||||
// send it as a server command if we are connected
|
||||
if(std.Cmd_ForwardToServer) std.Cmd_ForwardToServer();
|
||||
if(Sys.Cmd) Sys.Cmd();
|
||||
else MsgDev( D_ERROR, "Cmd_ExecuteString: can't send command to server\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -353,7 +353,7 @@ void Con_CreateConsole( void )
|
|||
else s_wcd.status = false;
|
||||
|
||||
// first text message into console or log
|
||||
MsgDev(D_ERROR, "Sys_LoadLibrary: Loading launch.dll - ok\n" );
|
||||
MsgDev(D_NOTE, "Sys_LoadLibrary: Loading launch.dll - ok\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -366,9 +366,8 @@ destroy win32 console
|
|||
void Con_DestroyConsole( void )
|
||||
{
|
||||
// last text message into console or log
|
||||
|
||||
if(Sys.crash) MsgDev(D_ERROR, "Sys_FreeLibrary: Hold launch.dll for debugging\n" );
|
||||
else MsgDev(D_ERROR, "Sys_FreeLibrary: Unloading launch.dll\n");
|
||||
if(Sys.crash) MsgDev(D_NOTE, "Sys_FreeLibrary: Hold launch.dll for debugging\n" );
|
||||
else MsgDev(D_NOTE, "Sys_FreeLibrary: Unloading launch.dll\n");
|
||||
|
||||
if(Sys.hooked_out)
|
||||
{
|
||||
|
|
|
@ -374,7 +374,7 @@ void Cvar_FullSet( char *var_name, char *value, int flags )
|
|||
if (var->flags & CVAR_USERINFO)
|
||||
{
|
||||
// transmit at next oportunity
|
||||
std.userinfo_modified = true;
|
||||
com.userinfo_modified = true;
|
||||
}
|
||||
|
||||
Mem_Free( var->string ); // free the old value string
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "mathlib.h"
|
||||
|
||||
system_t Sys;
|
||||
stdlib_api_t std;
|
||||
stdlib_api_t com;
|
||||
launch_exp_t *Host; // callback to mainframe
|
||||
FILE *logfile;
|
||||
|
||||
|
@ -21,171 +21,172 @@ static const char *show_credits = "\n\n\n\n\tCopyright XashXT Group 2007
|
|||
// stubs
|
||||
void NullInit( uint funcname, int argc, char **argv ) {}
|
||||
void NullFunc( void ) {}
|
||||
void Sys_NullPrint( const char *msg ) {}
|
||||
|
||||
void Sys_GetStdAPI( void )
|
||||
{
|
||||
// interface validator
|
||||
std.api_size = sizeof(stdlib_api_t);
|
||||
com.api_size = sizeof(stdlib_api_t);
|
||||
|
||||
// base events
|
||||
std.printf = Sys_Msg;
|
||||
std.dprintf = Sys_MsgDev;
|
||||
std.wprintf = Sys_MsgWarn;
|
||||
std.error = Sys_Error;
|
||||
std.abort = Sys_Break;
|
||||
std.exit = Sys_Exit;
|
||||
std.print = Sys_Print;
|
||||
std.input = Sys_Input;
|
||||
std.sleep = Sys_Sleep;
|
||||
std.clipboard = Sys_GetClipboardData;
|
||||
std.keyevents = Sys_SendKeyEvents;
|
||||
com.printf = Sys_Msg;
|
||||
com.dprintf = Sys_MsgDev;
|
||||
com.wprintf = Sys_MsgWarn;
|
||||
com.error = Sys_Error;
|
||||
com.abort = Sys_Break;
|
||||
com.exit = Sys_Exit;
|
||||
com.print = Sys_Print;
|
||||
com.input = Sys_Input;
|
||||
com.sleep = Sys_Sleep;
|
||||
com.clipboard = Sys_GetClipboardData;
|
||||
com.keyevents = Sys_SendKeyEvents;
|
||||
|
||||
// crclib.c funcs
|
||||
std.crc_init = CRC_Init;
|
||||
std.crc_block = CRC_Block;
|
||||
std.crc_process = CRC_ProcessByte;
|
||||
std.crc_sequence = CRC_BlockSequence;
|
||||
std.crc_blockchecksum = Com_BlockChecksum;
|
||||
std.crc_blockchecksumkey = Com_BlockChecksumKey;
|
||||
com.crc_init = CRC_Init;
|
||||
com.crc_block = CRC_Block;
|
||||
com.crc_process = CRC_ProcessByte;
|
||||
com.crc_sequence = CRC_BlockSequence;
|
||||
com.crc_blockchecksum = Com_BlockChecksum;
|
||||
com.crc_blockchecksumkey = Com_BlockChecksumKey;
|
||||
|
||||
// memlib.c
|
||||
std.memcpy = _mem_copy;
|
||||
std.memset = _mem_set;
|
||||
std.realloc = _mem_realloc;
|
||||
std.move = _mem_move;
|
||||
std.malloc = _mem_alloc;
|
||||
std.free = _mem_free;
|
||||
std.mallocpool = _mem_allocpool;
|
||||
std.freepool = _mem_freepool;
|
||||
std.clearpool = _mem_emptypool;
|
||||
std.memcheck = _mem_check;
|
||||
com.memcpy = _mem_copy;
|
||||
com.memset = _mem_set;
|
||||
com.realloc = _mem_realloc;
|
||||
com.move = _mem_move;
|
||||
com.malloc = _mem_alloc;
|
||||
com.free = _mem_free;
|
||||
com.mallocpool = _mem_allocpool;
|
||||
com.freepool = _mem_freepool;
|
||||
com.clearpool = _mem_emptypool;
|
||||
com.memcheck = _mem_check;
|
||||
|
||||
// common functions
|
||||
std.Com_InitRootDir = FS_InitRootDir; // init custom rootdir
|
||||
std.Com_LoadGameInfo = FS_LoadGameInfo; // gate game info from script file
|
||||
std.Com_AddGameHierarchy = FS_AddGameHierarchy; // add base directory in search list
|
||||
std.Com_CheckParm = FS_CheckParm; // get parm from cmdline
|
||||
std.Com_GetParm = FS_GetParmFromCmdLine; // get filename without path & ext
|
||||
std.Com_FileBase = FS_FileBase; // get filename without path & ext
|
||||
std.Com_FileExists = FS_FileExists; // return true if file exist
|
||||
std.Com_FileSize = FS_FileSize; // same as Com_FileExists but return filesize
|
||||
std.Com_FileExtension = FS_FileExtension; // return extension of file
|
||||
std.Com_RemovePath = FS_FileWithoutPath; // return file without path
|
||||
std.Com_StripExtension = FS_StripExtension; // remove extension if present
|
||||
std.Com_StripFilePath = FS_ExtractFilePath; // get file path without filename.ext
|
||||
std.Com_DefaultExtension = FS_DefaultExtension; // append extension if not present
|
||||
std.Com_ClearSearchPath = FS_ClearSearchPath; // delete all search pathes
|
||||
std.Com_CreateThread = Sys_RunThreadsOnIndividual;// run individual thread
|
||||
std.Com_ThreadLock = Sys_ThreadLock; // lock current thread
|
||||
std.Com_ThreadUnlock = Sys_ThreadUnlock; // unlock numthreads
|
||||
std.Com_NumThreads = Sys_GetNumThreads; // returns count of active threads
|
||||
std.Com_LoadScript = SC_LoadScript; // load script into stack from file or bufer
|
||||
std.Com_AddScript = SC_AddScript; // include script from file or buffer
|
||||
std.Com_ResetScript = SC_ResetScript; // reset current script state
|
||||
std.Com_ReadToken = SC_GetToken; // get next token on a line or newline
|
||||
std.Com_TryToken = SC_TryToken; // return 1 if have token on a line
|
||||
std.Com_FreeToken = SC_FreeToken; // free current token to may get it again
|
||||
std.Com_SkipToken = SC_SkipToken; // skip current token and jump into newline
|
||||
std.Com_MatchToken = SC_MatchToken; // compare current token with user keyword
|
||||
std.Com_ParseToken = SC_ParseToken; // parse token from char buffer
|
||||
std.Com_ParseWord = SC_ParseWord; // parse word from char buffer
|
||||
std.Com_Search = FS_Search; // returned list of found files
|
||||
std.Com_Filter = SC_FilterToken; // compare keyword by mask with filter
|
||||
std.com_token = token; // contains current token
|
||||
com.Com_InitRootDir = FS_InitRootDir; // init custom rootdir
|
||||
com.Com_LoadGameInfo = FS_LoadGameInfo; // gate game info from script file
|
||||
com.Com_AddGameHierarchy = FS_AddGameHierarchy; // add base directory in search list
|
||||
com.Com_CheckParm = FS_CheckParm; // get parm from cmdline
|
||||
com.Com_GetParm = FS_GetParmFromCmdLine; // get filename without path & ext
|
||||
com.Com_FileBase = FS_FileBase; // get filename without path & ext
|
||||
com.Com_FileExists = FS_FileExists; // return true if file exist
|
||||
com.Com_FileSize = FS_FileSize; // same as Com_FileExists but return filesize
|
||||
com.Com_FileExtension = FS_FileExtension; // return extension of file
|
||||
com.Com_RemovePath = FS_FileWithoutPath; // return file without path
|
||||
com.Com_StripExtension = FS_StripExtension; // remove extension if present
|
||||
com.Com_StripFilePath = FS_ExtractFilePath; // get file path without filename.ext
|
||||
com.Com_DefaultExtension = FS_DefaultExtension; // append extension if not present
|
||||
com.Com_ClearSearchPath = FS_ClearSearchPath; // delete all search pathes
|
||||
com.Com_CreateThread = Sys_RunThreadsOnIndividual;// run individual thread
|
||||
com.Com_ThreadLock = Sys_ThreadLock; // lock current thread
|
||||
com.Com_ThreadUnlock = Sys_ThreadUnlock; // unlock numthreads
|
||||
com.Com_NumThreads = Sys_GetNumThreads; // returns count of active threads
|
||||
com.Com_LoadScript = SC_LoadScript; // load script into stack from file or bufer
|
||||
com.Com_AddScript = SC_AddScript; // include script from file or buffer
|
||||
com.Com_ResetScript = SC_ResetScript; // reset current script state
|
||||
com.Com_ReadToken = SC_GetToken; // get next token on a line or newline
|
||||
com.Com_TryToken = SC_TryToken; // return 1 if have token on a line
|
||||
com.Com_FreeToken = SC_FreeToken; // free current token to may get it again
|
||||
com.Com_SkipToken = SC_SkipToken; // skip current token and jump into newline
|
||||
com.Com_MatchToken = SC_MatchToken; // compare current token with user keyword
|
||||
com.Com_ParseToken = SC_ParseToken; // parse token from char buffer
|
||||
com.Com_ParseWord = SC_ParseWord; // parse word from char buffer
|
||||
com.Com_Search = FS_Search; // returned list of found files
|
||||
com.Com_Filter = SC_FilterToken; // compare keyword by mask with filter
|
||||
com.com_token = token; // contains current token
|
||||
|
||||
// console variables
|
||||
std.Cvar_Get = Cvar_Get;
|
||||
std.Cvar_FullSet = Cvar_FullSet;
|
||||
std.Cvar_SetLatched = Cvar_SetLatched;
|
||||
std.Cvar_SetValue = Cvar_SetValue;
|
||||
std.Cvar_SetString = Cvar_Set;
|
||||
std.Cvar_GetValue = Cvar_VariableValue;
|
||||
std.Cvar_GetString = Cvar_VariableString;
|
||||
std.Cvar_LookupVars = Cvar_LookupVars;
|
||||
std.Cvar_FindVar = Cvar_FindVar;
|
||||
com.Cvar_Get = Cvar_Get;
|
||||
com.Cvar_FullSet = Cvar_FullSet;
|
||||
com.Cvar_SetLatched = Cvar_SetLatched;
|
||||
com.Cvar_SetValue = Cvar_SetValue;
|
||||
com.Cvar_SetString = Cvar_Set;
|
||||
com.Cvar_GetValue = Cvar_VariableValue;
|
||||
com.Cvar_GetString = Cvar_VariableString;
|
||||
com.Cvar_LookupVars = Cvar_LookupVars;
|
||||
com.Cvar_FindVar = Cvar_FindVar;
|
||||
|
||||
// console commands
|
||||
std.Cmd_Exec = Cbuf_ExecuteText; // process cmd buffer
|
||||
std.Cmd_Argc = Cmd_Argc;
|
||||
std.Cmd_Args = Cmd_Args;
|
||||
std.Cmd_Argv = Cmd_Argv;
|
||||
std.Cmd_LookupCmds = Cmd_LookupCmds;
|
||||
std.Cmd_AddCommand = Cmd_AddCommand;
|
||||
std.Cmd_DelCommand = Cmd_RemoveCommand;
|
||||
std.Cmd_TokenizeString = Cmd_TokenizeString;
|
||||
com.Cmd_Exec = Cbuf_ExecuteText; // process cmd buffer
|
||||
com.Cmd_Argc = Cmd_Argc;
|
||||
com.Cmd_Args = Cmd_Args;
|
||||
com.Cmd_Argv = Cmd_Argv;
|
||||
com.Cmd_LookupCmds = Cmd_LookupCmds;
|
||||
com.Cmd_AddCommand = Cmd_AddCommand;
|
||||
com.Cmd_DelCommand = Cmd_RemoveCommand;
|
||||
com.Cmd_TokenizeString = Cmd_TokenizeString;
|
||||
|
||||
|
||||
// real filesystem
|
||||
std.fopen = FS_Open; // same as fopen
|
||||
std.fclose = FS_Close; // same as fclose
|
||||
std.fwrite = FS_Write; // same as fwrite
|
||||
std.fread = FS_Read; // same as fread, can see trough pakfile
|
||||
std.fprint = FS_Print; // printed message into file
|
||||
std.fprintf = FS_Printf; // same as fprintf
|
||||
std.fgets = FS_Gets; // like a fgets, but can return EOF
|
||||
std.fseek = FS_Seek; // fseek, can seek in packfiles too
|
||||
std.ftell = FS_Tell; // like a ftell
|
||||
com.fopen = FS_Open; // same as fopen
|
||||
com.fclose = FS_Close; // same as fclose
|
||||
com.fwrite = FS_Write; // same as fwrite
|
||||
com.fread = FS_Read; // same as fread, can see trough pakfile
|
||||
com.fprint = FS_Print; // printed message into file
|
||||
com.fprintf = FS_Printf; // same as fprintf
|
||||
com.fgets = FS_Gets; // like a fgets, but can return EOF
|
||||
com.fseek = FS_Seek; // fseek, can seek in packfiles too
|
||||
com.ftell = FS_Tell; // like a ftell
|
||||
|
||||
// virtual filesystem
|
||||
std.vfcreate = VFS_Create; // create virtual stream
|
||||
std.vfopen = VFS_Open; // virtual fopen
|
||||
std.vfclose = VFS_Close; // free buffer or write dump
|
||||
std.vfwrite = VFS_Write; // write into buffer
|
||||
std.vfread = VFS_Read; // read from buffer
|
||||
std.vfgets = VFS_Gets; // read text line
|
||||
std.vfprint = VFS_Print; // write message
|
||||
std.vfprintf = VFS_Printf; // write formatted message
|
||||
std.vfseek = VFS_Seek; // fseek, can seek in packfiles too
|
||||
std.vfunpack = VFS_Unpack; // inflate zipped buffer
|
||||
std.vftell = VFS_Tell; // like a ftell
|
||||
com.vfcreate = VFS_Create; // create virtual stream
|
||||
com.vfopen = VFS_Open; // virtual fopen
|
||||
com.vfclose = VFS_Close; // free buffer or write dump
|
||||
com.vfwrite = VFS_Write; // write into buffer
|
||||
com.vfread = VFS_Read; // read from buffer
|
||||
com.vfgets = VFS_Gets; // read text line
|
||||
com.vfprint = VFS_Print; // write message
|
||||
com.vfprintf = VFS_Printf; // write formatted message
|
||||
com.vfseek = VFS_Seek; // fseek, can seek in packfiles too
|
||||
com.vfunpack = VFS_Unpack; // inflate zipped buffer
|
||||
com.vftell = VFS_Tell; // like a ftell
|
||||
|
||||
// filesystem simply user interface
|
||||
std.Com_LoadFile = FS_LoadFile; // load file into heap
|
||||
std.Com_WriteFile = FS_WriteFile; // write file into disk
|
||||
std.Com_LoadImage = FS_LoadImage; // extract image into rgba buffer
|
||||
std.Com_SaveImage = FS_SaveImage; // save image into specified format
|
||||
std.Com_ProcessImage = Image_Processing; // convert and resample image
|
||||
std.Com_FreeImage = FS_FreeImage; // free image buffer
|
||||
std.Com_LoadLibrary = Sys_LoadLibrary; // load library
|
||||
std.Com_FreeLibrary = Sys_FreeLibrary; // free library
|
||||
std.Com_GetProcAddress = Sys_GetProcAddress; // gpa
|
||||
std.Com_DoubleTime = Sys_DoubleTime; // hi-res timer
|
||||
com.Com_LoadFile = FS_LoadFile; // load file into heap
|
||||
com.Com_WriteFile = FS_WriteFile; // write file into disk
|
||||
com.Com_LoadImage = FS_LoadImage; // extract image into rgba buffer
|
||||
com.Com_SaveImage = FS_SaveImage; // save image into specified format
|
||||
com.Com_ProcessImage = Image_Processing; // convert and resample image
|
||||
com.Com_FreeImage = FS_FreeImage; // free image buffer
|
||||
com.Com_LoadLibrary = Sys_LoadLibrary; // load library
|
||||
com.Com_FreeLibrary = Sys_FreeLibrary; // free library
|
||||
com.Com_GetProcAddress = Sys_GetProcAddress; // gpa
|
||||
com.Com_DoubleTime = Sys_DoubleTime; // hi-res timer
|
||||
|
||||
// stdlib.c funcs
|
||||
std.strnupr = com_strnupr;
|
||||
std.strnlwr = com_strnlwr;
|
||||
std.strupr = com_strupr;
|
||||
std.strlwr = com_strlwr;
|
||||
std.strlen = com_strlen;
|
||||
std.cstrlen = com_cstrlen;
|
||||
std.toupper = com_toupper;
|
||||
std.tolower = com_tolower;
|
||||
std.strncat = com_strncat;
|
||||
std.strcat = com_strcat;
|
||||
std.strncpy = com_strncpy;
|
||||
std.strcpy = com_strcpy;
|
||||
std.stralloc = com_stralloc;
|
||||
std.atoi = com_atoi;
|
||||
std.atof = com_atof;
|
||||
std.atov = com_atov;
|
||||
std.strchr = com_strchr;
|
||||
std.strrchr = com_strrchr;
|
||||
std.strnicmp = com_strnicmp;
|
||||
std.stricmp = com_stricmp;
|
||||
std.strncmp = com_strncmp;
|
||||
std.strcmp = com_strcmp;
|
||||
std.stristr = com_stristr;
|
||||
std.strstr = com_stristr; // FIXME
|
||||
std.strpack = com_strpack;
|
||||
std.strunpack = com_strunpack;
|
||||
std.vsprintf = com_vsprintf;
|
||||
std.sprintf = com_sprintf;
|
||||
std.va = va;
|
||||
std.vsnprintf = com_vsnprintf;
|
||||
std.snprintf = com_snprintf;
|
||||
std.timestamp = com_timestamp;
|
||||
com.strnupr = com_strnupr;
|
||||
com.strnlwr = com_strnlwr;
|
||||
com.strupr = com_strupr;
|
||||
com.strlwr = com_strlwr;
|
||||
com.strlen = com_strlen;
|
||||
com.cstrlen = com_cstrlen;
|
||||
com.toupper = com_toupper;
|
||||
com.tolower = com_tolower;
|
||||
com.strncat = com_strncat;
|
||||
com.strcat = com_strcat;
|
||||
com.strncpy = com_strncpy;
|
||||
com.strcpy = com_strcpy;
|
||||
com.stralloc = com_stralloc;
|
||||
com.atoi = com_atoi;
|
||||
com.atof = com_atof;
|
||||
com.atov = com_atov;
|
||||
com.strchr = com_strchr;
|
||||
com.strrchr = com_strrchr;
|
||||
com.strnicmp = com_strnicmp;
|
||||
com.stricmp = com_stricmp;
|
||||
com.strncmp = com_strncmp;
|
||||
com.strcmp = com_strcmp;
|
||||
com.stristr = com_stristr;
|
||||
com.strstr = com_stristr; // FIXME
|
||||
com.strpack = com_strpack;
|
||||
com.strunpack = com_strunpack;
|
||||
com.vsprintf = com_vsprintf;
|
||||
com.sprintf = com_sprintf;
|
||||
com.va = va;
|
||||
com.vsnprintf = com_vsnprintf;
|
||||
com.snprintf = com_snprintf;
|
||||
com.timestamp = com_timestamp;
|
||||
|
||||
std.GameInfo = &GI;
|
||||
com.GameInfo = &GI;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -334,10 +335,12 @@ void Sys_CreateInstance( void )
|
|||
case STUDIO:
|
||||
case PAKLIB:
|
||||
CreateHost = (void *)Sys.linked_dll->main;
|
||||
Host = CreateHost( &std, NULL ); // second interface not allowed
|
||||
Host = CreateHost( &com, NULL ); // second interface not allowed
|
||||
Sys.Init = Host->Init;
|
||||
Sys.Main = Host->Main;
|
||||
Sys.Free = Host->Free;
|
||||
Sys.CPrint = Host->CPrint;
|
||||
Sys.Cmd = Host->Cmd;
|
||||
break;
|
||||
case CREDITS:
|
||||
Sys_Break( show_credits );
|
||||
|
@ -484,6 +487,7 @@ void Sys_Print(const char *pMsg)
|
|||
int i = 0;
|
||||
|
||||
if(Sys.con_silentmode) return;
|
||||
if(Sys.CPrint) Sys.CPrint( pMsg );
|
||||
|
||||
// if the message is REALLY long, use just the last portion of it
|
||||
if ( com_strlen( pMsg ) > MAX_INPUTLINE - 1 )
|
||||
|
@ -559,7 +563,28 @@ void Sys_MsgDev( int level, const char *pMsg, ... )
|
|||
va_start (argptr, pMsg);
|
||||
com_vsprintf (text, pMsg, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
switch(level)
|
||||
{
|
||||
case D_INFO:
|
||||
Sys_Print( text );
|
||||
break;
|
||||
case D_WARN:
|
||||
Sys_Print(va("^3Warning:^7 %s", text));
|
||||
break;
|
||||
case D_ERROR:
|
||||
Sys_Print(va("^1Error:^7 %s", text));
|
||||
break;
|
||||
case D_LOAD:
|
||||
Sys_Print(va("^2Loading: ^7%s", text));
|
||||
break;
|
||||
case D_NOTE:
|
||||
Sys_Print( text );
|
||||
break;
|
||||
case D_MEMORY:
|
||||
Sys_Print(va("^6Mem: ^7%s", text));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Sys_MsgWarn( const char *pMsg, ... )
|
||||
|
@ -572,7 +597,7 @@ void Sys_MsgWarn( const char *pMsg, ... )
|
|||
va_start (argptr, pMsg);
|
||||
com_vsprintf (text, pMsg, argptr);
|
||||
va_end (argptr);
|
||||
Sys_Print( text );
|
||||
Sys_Print(va("^3Warning:^7 %s", text));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -883,7 +908,7 @@ bool Sys_LoadLibrary ( dll_info_t *dll )
|
|||
if(!dll->name) return false; // nothing to load
|
||||
if(dll->link) return true; // already loaded
|
||||
|
||||
MsgDev(D_ERROR, "Sys_LoadLibrary: Loading %s", dll->name );
|
||||
MsgDev(D_NOTE, "Sys_LoadLibrary: Loading %s", dll->name );
|
||||
|
||||
if(dll->fcts)
|
||||
{
|
||||
|
@ -930,7 +955,7 @@ bool Sys_LoadLibrary ( dll_info_t *dll )
|
|||
|
||||
// NOTE: native dlls must support null import!
|
||||
// e.g. see ..\common\platform.c for details
|
||||
check = (void *)dll->main( &std, NULL ); // first iface always stdlib_api_t
|
||||
check = (void *)dll->main( &com, NULL ); // first iface always stdlib_api_t
|
||||
|
||||
if(!check)
|
||||
{
|
||||
|
@ -943,14 +968,14 @@ bool Sys_LoadLibrary ( dll_info_t *dll )
|
|||
goto error;
|
||||
}
|
||||
}
|
||||
MsgDev(D_ERROR, " - ok\n");
|
||||
MsgDev(D_NOTE, " - ok\n");
|
||||
|
||||
return true;
|
||||
error:
|
||||
MsgDev(D_ERROR, " - failed\n");
|
||||
MsgDev(D_NOTE, " - failed\n");
|
||||
Sys_FreeLibrary ( dll ); // trying to free
|
||||
if(dll->crash) Sys_Error( errorstring );
|
||||
else MsgDev( D_INFO, errorstring );
|
||||
else MsgDev( D_ERROR, errorstring );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -970,10 +995,10 @@ bool Sys_FreeLibrary ( dll_info_t *dll )
|
|||
if(Sys.crash)
|
||||
{
|
||||
// we need to hold down all modules, while MSVC can find erorr
|
||||
MsgDev(D_ERROR, "Sys_FreeLibrary: Hold %s for debugging\n", dll->name );
|
||||
MsgDev(D_NOTE, "Sys_FreeLibrary: Hold %s for debugging\n", dll->name );
|
||||
return false;
|
||||
}
|
||||
else MsgDev(D_ERROR, "Sys_FreeLibrary: Unloading %s\n", dll->name );
|
||||
else MsgDev(D_NOTE, "Sys_FreeLibrary: Unloading %s\n", dll->name );
|
||||
|
||||
FreeLibrary (dll->link);
|
||||
dll->link = NULL;
|
||||
|
|
|
@ -55,6 +55,8 @@ typedef struct system_s
|
|||
void ( *Init ) ( uint funcname, int argc, char **argv );
|
||||
void ( *Main ) ( void ); // host frame
|
||||
void ( *Free ) ( void ); // close host
|
||||
void ( *Cmd ) ( void ); // cmd forward to server
|
||||
void (*CPrint)( const char *msg ); // console print
|
||||
} system_t;
|
||||
|
||||
typedef struct cvar_s
|
||||
|
@ -77,7 +79,7 @@ typedef struct cvar_s
|
|||
|
||||
extern system_t Sys;
|
||||
extern gameinfo_t GI;
|
||||
extern stdlib_api_t std;
|
||||
extern stdlib_api_t com;
|
||||
|
||||
//
|
||||
// console.c
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
|
||||
//Bullet Continuous Collision Detection and Physics Library
|
||||
//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
|
||||
//
|
||||
// btAxisSweep3
|
||||
//
|
||||
// Copyright (c) 2006 Simon Hobbs
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
#include "btAxisSweep3.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache)
|
||||
:btAxisSweep3Internal<unsigned short int>(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache)
|
||||
{
|
||||
// 1 handle is reserved as sentinel
|
||||
btAssert(maxHandles > 1 && maxHandles < 32767);
|
||||
|
||||
}
|
||||
|
||||
|
||||
bt32BitAxisSweep3::bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache )
|
||||
:btAxisSweep3Internal<unsigned int>(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache)
|
||||
{
|
||||
// 1 handle is reserved as sentinel
|
||||
btAssert(maxHandles > 1 && maxHandles < 2147483647);
|
||||
}
|
|
@ -0,0 +1,858 @@
|
|||
//Bullet Continuous Collision Detection and Physics Library
|
||||
//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
//
|
||||
// btAxisSweep3.h
|
||||
//
|
||||
// Copyright (c) 2006 Simon Hobbs
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef AXIS_SWEEP_3_H
|
||||
#define AXIS_SWEEP_3_H
|
||||
|
||||
#include "LinearMath/btPoint3.h"
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "btOverlappingPairCache.h"
|
||||
#include "btBroadphaseInterface.h"
|
||||
#include "btBroadphaseProxy.h"
|
||||
|
||||
|
||||
//#define DEBUG_BROADPHASE 1
|
||||
|
||||
/// btAxisSweep3Internal is an internal template class that implements sweep and prune.
|
||||
/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead.
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
class btAxisSweep3Internal : public btBroadphaseInterface
|
||||
{
|
||||
protected:
|
||||
|
||||
BP_FP_INT_TYPE m_bpHandleMask;
|
||||
BP_FP_INT_TYPE m_handleSentinel;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
class Edge
|
||||
{
|
||||
public:
|
||||
BP_FP_INT_TYPE m_pos; // low bit is min/max
|
||||
BP_FP_INT_TYPE m_handle;
|
||||
|
||||
BP_FP_INT_TYPE IsMax() const {return m_pos & 1;}
|
||||
};
|
||||
|
||||
public:
|
||||
ATTRIBUTE_ALIGNED16(class) Handle : public btBroadphaseProxy
|
||||
{
|
||||
public:
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
// indexes into the edge arrays
|
||||
BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12
|
||||
// BP_FP_INT_TYPE m_uniqueId;
|
||||
BP_FP_INT_TYPE m_pad;
|
||||
|
||||
//void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
|
||||
|
||||
SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;}
|
||||
SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];}
|
||||
}; // 24 bytes + 24 for Edge structures = 44 bytes total per entry
|
||||
|
||||
|
||||
protected:
|
||||
btPoint3 m_worldAabbMin; // overall system bounds
|
||||
btPoint3 m_worldAabbMax; // overall system bounds
|
||||
|
||||
btVector3 m_quantize; // scaling factor for quantization
|
||||
|
||||
BP_FP_INT_TYPE m_numHandles; // number of active handles
|
||||
BP_FP_INT_TYPE m_maxHandles; // max number of handles
|
||||
Handle* m_pHandles; // handles pool
|
||||
BP_FP_INT_TYPE m_firstFreeHandle; // free handles list
|
||||
|
||||
Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
|
||||
|
||||
btOverlappingPairCache* m_pairCache;
|
||||
bool m_ownsPairCache;
|
||||
|
||||
int m_invalidPair;
|
||||
|
||||
// allocation/deallocation
|
||||
BP_FP_INT_TYPE allocHandle();
|
||||
void freeHandle(BP_FP_INT_TYPE handle);
|
||||
|
||||
|
||||
bool testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB);
|
||||
|
||||
#ifdef DEBUG_BROADPHASE
|
||||
void debugPrintAxis(int axis,bool checkCardinality=true);
|
||||
#endif //DEBUG_BROADPHASE
|
||||
|
||||
//Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
|
||||
//void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
|
||||
|
||||
void quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const;
|
||||
|
||||
void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
|
||||
void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
|
||||
void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
|
||||
void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
|
||||
|
||||
public:
|
||||
|
||||
btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0);
|
||||
|
||||
virtual ~btAxisSweep3Internal();
|
||||
|
||||
|
||||
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
|
||||
|
||||
BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher);
|
||||
void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher);
|
||||
void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher);
|
||||
SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
|
||||
|
||||
void processAllOverlappingPairs(btOverlapCallback* callback);
|
||||
|
||||
//Broadphase Interface
|
||||
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher);
|
||||
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
|
||||
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
|
||||
|
||||
bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
|
||||
|
||||
btOverlappingPairCache* getOverlappingPairCache()
|
||||
{
|
||||
return m_pairCache;
|
||||
}
|
||||
const btOverlappingPairCache* getOverlappingPairCache() const
|
||||
{
|
||||
return m_pairCache;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG_BROADPHASE
|
||||
#include <stdio.h>
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
void btAxisSweep3<BP_FP_INT_TYPE>::debugPrintAxis(int axis, bool checkCardinality)
|
||||
{
|
||||
int numEdges = m_pHandles[0].m_maxEdges[axis];
|
||||
printf("SAP Axis %d, numEdges=%d\n",axis,numEdges);
|
||||
|
||||
int i;
|
||||
for (i=0;i<numEdges+1;i++)
|
||||
{
|
||||
Edge* pEdge = m_pEdges[axis] + i;
|
||||
Handle* pHandlePrev = getHandle(pEdge->m_handle);
|
||||
int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis];
|
||||
char beginOrEnd;
|
||||
beginOrEnd=pEdge->IsMax()?'E':'B';
|
||||
printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex);
|
||||
}
|
||||
|
||||
if (checkCardinality)
|
||||
assert(numEdges == m_numHandles*2+1);
|
||||
}
|
||||
#endif //DEBUG_BROADPHASE
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
btBroadphaseProxy* btAxisSweep3Internal<BP_FP_INT_TYPE>::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher)
|
||||
{
|
||||
(void)shapeType;
|
||||
BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher);
|
||||
|
||||
Handle* handle = getHandle(handleId);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
void btAxisSweep3Internal<BP_FP_INT_TYPE>::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
|
||||
{
|
||||
Handle* handle = static_cast<Handle*>(proxy);
|
||||
removeHandle(handle->m_uniqueId,dispatcher);
|
||||
}
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
void btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
|
||||
{
|
||||
Handle* handle = static_cast<Handle*>(proxy);
|
||||
updateHandle(handle->m_uniqueId,aabbMin,aabbMax,dispatcher);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
btAxisSweep3Internal<BP_FP_INT_TYPE>::btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE maxHandles, btOverlappingPairCache* pairCache )
|
||||
:m_bpHandleMask(handleMask),
|
||||
m_handleSentinel(handleSentinel),
|
||||
m_pairCache(pairCache),
|
||||
m_ownsPairCache(false),
|
||||
m_invalidPair(0)
|
||||
{
|
||||
if (!m_pairCache)
|
||||
{
|
||||
void* ptr = btAlignedAlloc(sizeof(btOverlappingPairCache),16);
|
||||
m_pairCache = new(ptr) btOverlappingPairCache();
|
||||
m_ownsPairCache = true;
|
||||
}
|
||||
|
||||
//assert(bounds.HasVolume());
|
||||
|
||||
// init bounds
|
||||
m_worldAabbMin = worldAabbMin;
|
||||
m_worldAabbMax = worldAabbMax;
|
||||
|
||||
btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
|
||||
|
||||
BP_FP_INT_TYPE maxInt = m_handleSentinel;
|
||||
|
||||
m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize;
|
||||
|
||||
// allocate handles buffer and put all handles on free list
|
||||
void* ptr = btAlignedAlloc(sizeof(Handle)*maxHandles,16);
|
||||
m_pHandles = new(ptr) Handle[maxHandles];
|
||||
m_maxHandles = maxHandles;
|
||||
m_numHandles = 0;
|
||||
|
||||
// handle 0 is reserved as the null index, and is also used as the sentinel
|
||||
m_firstFreeHandle = 1;
|
||||
{
|
||||
for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++)
|
||||
m_pHandles[i].SetNextFree(i + 1);
|
||||
m_pHandles[maxHandles - 1].SetNextFree(0);
|
||||
}
|
||||
|
||||
{
|
||||
// allocate edge buffers
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
void* ptr = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16);
|
||||
m_pEdges[i] = new(ptr) Edge[maxHandles * 2];
|
||||
}
|
||||
}
|
||||
//removed overlap management
|
||||
|
||||
// make boundary sentinels
|
||||
|
||||
m_pHandles[0].m_clientObject = 0;
|
||||
|
||||
for (int axis = 0; axis < 3; axis++)
|
||||
{
|
||||
m_pHandles[0].m_minEdges[axis] = 0;
|
||||
m_pHandles[0].m_maxEdges[axis] = 1;
|
||||
|
||||
m_pEdges[axis][0].m_pos = 0;
|
||||
m_pEdges[axis][0].m_handle = 0;
|
||||
m_pEdges[axis][1].m_pos = m_handleSentinel;
|
||||
m_pEdges[axis][1].m_handle = 0;
|
||||
#ifdef DEBUG_BROADPHASE
|
||||
debugPrintAxis(axis);
|
||||
#endif //DEBUG_BROADPHASE
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
btAxisSweep3Internal<BP_FP_INT_TYPE>::~btAxisSweep3Internal()
|
||||
{
|
||||
|
||||
for (int i = 2; i >= 0; i--)
|
||||
{
|
||||
btAlignedFree(m_pEdges[i]);
|
||||
}
|
||||
btAlignedFree(m_pHandles);
|
||||
|
||||
if (m_ownsPairCache)
|
||||
{
|
||||
btAlignedFree(m_pairCache);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
void btAxisSweep3Internal<BP_FP_INT_TYPE>::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const
|
||||
{
|
||||
btPoint3 clampedPoint(point);
|
||||
|
||||
|
||||
|
||||
clampedPoint.setMax(m_worldAabbMin);
|
||||
clampedPoint.setMin(m_worldAabbMax);
|
||||
|
||||
btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize;
|
||||
out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax);
|
||||
out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax);
|
||||
out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax);
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
|
||||
{
|
||||
assert(m_firstFreeHandle);
|
||||
|
||||
BP_FP_INT_TYPE handle = m_firstFreeHandle;
|
||||
m_firstFreeHandle = getHandle(handle)->GetNextFree();
|
||||
m_numHandles++;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
void btAxisSweep3Internal<BP_FP_INT_TYPE>::freeHandle(BP_FP_INT_TYPE handle)
|
||||
{
|
||||
assert(handle > 0 && handle < m_maxHandles);
|
||||
|
||||
getHandle(handle)->SetNextFree(m_firstFreeHandle);
|
||||
m_firstFreeHandle = handle;
|
||||
|
||||
m_numHandles--;
|
||||
}
|
||||
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher)
|
||||
{
|
||||
// quantize the bounds
|
||||
BP_FP_INT_TYPE min[3], max[3];
|
||||
quantize(min, aabbMin, 0);
|
||||
quantize(max, aabbMax, 1);
|
||||
|
||||
// allocate a handle
|
||||
BP_FP_INT_TYPE handle = allocHandle();
|
||||
|
||||
|
||||
Handle* pHandle = getHandle(handle);
|
||||
|
||||
pHandle->m_uniqueId = handle;
|
||||
//pHandle->m_pOverlaps = 0;
|
||||
pHandle->m_clientObject = pOwner;
|
||||
pHandle->m_collisionFilterGroup = collisionFilterGroup;
|
||||
pHandle->m_collisionFilterMask = collisionFilterMask;
|
||||
|
||||
// compute current limit of edge arrays
|
||||
BP_FP_INT_TYPE limit = m_numHandles * 2;
|
||||
|
||||
|
||||
// insert new edges just inside the max boundary edge
|
||||
for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++)
|
||||
{
|
||||
|
||||
m_pHandles[0].m_maxEdges[axis] += 2;
|
||||
|
||||
m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1];
|
||||
|
||||
m_pEdges[axis][limit - 1].m_pos = min[axis];
|
||||
m_pEdges[axis][limit - 1].m_handle = handle;
|
||||
|
||||
m_pEdges[axis][limit].m_pos = max[axis];
|
||||
m_pEdges[axis][limit].m_handle = handle;
|
||||
|
||||
pHandle->m_minEdges[axis] = limit - 1;
|
||||
pHandle->m_maxEdges[axis] = limit;
|
||||
}
|
||||
|
||||
// now sort the new edges to their correct position
|
||||
sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false);
|
||||
sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false);
|
||||
sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false);
|
||||
sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false);
|
||||
sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true);
|
||||
sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true);
|
||||
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
Handle* pHandle = getHandle(handle);
|
||||
|
||||
//explicitly remove the pairs containing the proxy
|
||||
//we could do it also in the sortMinUp (passing true)
|
||||
//todo: compare performance
|
||||
m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher);
|
||||
|
||||
|
||||
// compute current limit of edge arrays
|
||||
int limit = m_numHandles * 2;
|
||||
|
||||
int axis;
|
||||
|
||||
for (axis = 0;axis<3;axis++)
|
||||
{
|
||||
m_pHandles[0].m_maxEdges[axis] -= 2;
|
||||
}
|
||||
|
||||
// remove the edges by sorting them up to the end of the list
|
||||
for ( axis = 0; axis < 3; axis++)
|
||||
{
|
||||
Edge* pEdges = m_pEdges[axis];
|
||||
BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis];
|
||||
pEdges[max].m_pos = m_handleSentinel;
|
||||
|
||||
sortMaxUp(axis,max,dispatcher,false);
|
||||
|
||||
|
||||
BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
|
||||
pEdges[i].m_pos = m_handleSentinel;
|
||||
|
||||
|
||||
sortMinUp(axis,i,dispatcher,false);
|
||||
|
||||
pEdges[limit-1].m_handle = 0;
|
||||
pEdges[limit-1].m_pos = m_handleSentinel;
|
||||
|
||||
#ifdef DEBUG_BROADPHASE
|
||||
debugPrintAxis(axis,false);
|
||||
#endif //DEBUG_BROADPHASE
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// free the handle
|
||||
freeHandle(handle);
|
||||
|
||||
|
||||
}
|
||||
|
||||
extern int gOverlappingPairs;
|
||||
#include <stdio.h>
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
void btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatcher* dispatcher)
|
||||
{
|
||||
#ifdef USE_LAZY_REMOVAL
|
||||
|
||||
if (m_ownsPairCache)
|
||||
{
|
||||
|
||||
btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
|
||||
|
||||
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
|
||||
overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
|
||||
|
||||
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
|
||||
m_invalidPair = 0;
|
||||
|
||||
|
||||
int i;
|
||||
|
||||
btBroadphasePair previousPair;
|
||||
previousPair.m_pProxy0 = 0;
|
||||
previousPair.m_pProxy1 = 0;
|
||||
previousPair.m_algorithm = 0;
|
||||
|
||||
|
||||
for (i=0;i<overlappingPairArray.size();i++)
|
||||
{
|
||||
|
||||
btBroadphasePair& pair = overlappingPairArray[i];
|
||||
|
||||
bool isDuplicate = (pair == previousPair);
|
||||
|
||||
previousPair = pair;
|
||||
|
||||
bool needsRemoval = false;
|
||||
|
||||
if (!isDuplicate)
|
||||
{
|
||||
bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
|
||||
|
||||
if (hasOverlap)
|
||||
{
|
||||
needsRemoval = false;//callback->processOverlap(pair);
|
||||
} else
|
||||
{
|
||||
needsRemoval = true;
|
||||
}
|
||||
} else
|
||||
{
|
||||
//remove duplicate
|
||||
needsRemoval = true;
|
||||
//should have no algorithm
|
||||
btAssert(!pair.m_algorithm);
|
||||
}
|
||||
|
||||
if (needsRemoval)
|
||||
{
|
||||
m_pairCache->cleanOverlappingPair(pair,dispatcher);
|
||||
|
||||
// m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
|
||||
// m_overlappingPairArray.pop_back();
|
||||
pair.m_pProxy0 = 0;
|
||||
pair.m_pProxy1 = 0;
|
||||
m_invalidPair++;
|
||||
gOverlappingPairs--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///if you don't like to skip the invalid pairs in the array, execute following code:
|
||||
#define CLEAN_INVALID_PAIRS 1
|
||||
#ifdef CLEAN_INVALID_PAIRS
|
||||
|
||||
//perform a sort, to sort 'invalid' pairs to the end
|
||||
overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
|
||||
|
||||
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
|
||||
m_invalidPair = 0;
|
||||
#endif//CLEAN_INVALID_PAIRS
|
||||
|
||||
//printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
|
||||
}
|
||||
#endif //USE_LAZY_REMOVAL
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
|
||||
{
|
||||
const Handle* pHandleA = static_cast<Handle*>(proxy0);
|
||||
const Handle* pHandleB = static_cast<Handle*>(proxy1);
|
||||
|
||||
//optimization 1: check the array index (memory address), instead of the m_pos
|
||||
|
||||
for (int axis = 0; axis < 3; axis++)
|
||||
{
|
||||
if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
|
||||
pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB)
|
||||
{
|
||||
//optimization 1: check the array index (memory address), instead of the m_pos
|
||||
|
||||
for (int axis = 0; axis < 3; axis++)
|
||||
{
|
||||
if (axis != ignoreAxis)
|
||||
{
|
||||
if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
|
||||
pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization)
|
||||
|
||||
/*for (int axis = 0; axis < 3; axis++)
|
||||
{
|
||||
if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos ||
|
||||
m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher)
|
||||
{
|
||||
// assert(bounds.IsFinite());
|
||||
//assert(bounds.HasVolume());
|
||||
|
||||
Handle* pHandle = getHandle(handle);
|
||||
|
||||
// quantize the new bounds
|
||||
BP_FP_INT_TYPE min[3], max[3];
|
||||
quantize(min, aabbMin, 0);
|
||||
quantize(max, aabbMax, 1);
|
||||
|
||||
// update changed edges
|
||||
for (int axis = 0; axis < 3; axis++)
|
||||
{
|
||||
BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis];
|
||||
BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis];
|
||||
|
||||
int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos;
|
||||
int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos;
|
||||
|
||||
m_pEdges[axis][emin].m_pos = min[axis];
|
||||
m_pEdges[axis][emax].m_pos = max[axis];
|
||||
|
||||
// expand (only adds overlaps)
|
||||
if (dmin < 0)
|
||||
sortMinDown(axis, emin,dispatcher,true);
|
||||
|
||||
if (dmax > 0)
|
||||
sortMaxUp(axis, emax,dispatcher,true);
|
||||
|
||||
// shrink (only removes overlaps)
|
||||
if (dmin > 0)
|
||||
sortMinUp(axis, emin,dispatcher,true);
|
||||
|
||||
if (dmax < 0)
|
||||
sortMaxDown(axis, emax,dispatcher,true);
|
||||
|
||||
#ifdef DEBUG_BROADPHASE
|
||||
debugPrintAxis(axis);
|
||||
#endif //DEBUG_BROADPHASE
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// sorting a min edge downwards can only ever *add* overlaps
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
|
||||
{
|
||||
|
||||
Edge* pEdge = m_pEdges[axis] + edge;
|
||||
Edge* pPrev = pEdge - 1;
|
||||
Handle* pHandleEdge = getHandle(pEdge->m_handle);
|
||||
|
||||
while (pEdge->m_pos < pPrev->m_pos)
|
||||
{
|
||||
Handle* pHandlePrev = getHandle(pPrev->m_handle);
|
||||
|
||||
if (pPrev->IsMax())
|
||||
{
|
||||
// if previous edge is a maximum check the bounds and add an overlap if necessary
|
||||
if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev))
|
||||
{
|
||||
m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev);
|
||||
|
||||
//AddOverlap(pEdge->m_handle, pPrev->m_handle);
|
||||
|
||||
}
|
||||
|
||||
// update edge reference in other handle
|
||||
pHandlePrev->m_maxEdges[axis]++;
|
||||
}
|
||||
else
|
||||
pHandlePrev->m_minEdges[axis]++;
|
||||
|
||||
pHandleEdge->m_minEdges[axis]--;
|
||||
|
||||
// swap the edges
|
||||
Edge swap = *pEdge;
|
||||
*pEdge = *pPrev;
|
||||
*pPrev = swap;
|
||||
|
||||
// decrement
|
||||
pEdge--;
|
||||
pPrev--;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_BROADPHASE
|
||||
debugPrintAxis(axis);
|
||||
#endif //DEBUG_BROADPHASE
|
||||
|
||||
}
|
||||
|
||||
// sorting a min edge upwards can only ever *remove* overlaps
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
|
||||
{
|
||||
Edge* pEdge = m_pEdges[axis] + edge;
|
||||
Edge* pNext = pEdge + 1;
|
||||
Handle* pHandleEdge = getHandle(pEdge->m_handle);
|
||||
|
||||
while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
|
||||
{
|
||||
Handle* pHandleNext = getHandle(pNext->m_handle);
|
||||
|
||||
if (pNext->IsMax())
|
||||
{
|
||||
#ifndef USE_LAZY_REMOVAL
|
||||
// if next edge is maximum remove any overlap between the two handles
|
||||
if (updateOverlaps)
|
||||
{
|
||||
Handle* handle0 = getHandle(pEdge->m_handle);
|
||||
Handle* handle1 = getHandle(pNext->m_handle);
|
||||
|
||||
m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
|
||||
}
|
||||
#endif //USE_LAZY_REMOVAL
|
||||
|
||||
// update edge reference in other handle
|
||||
pHandleNext->m_maxEdges[axis]--;
|
||||
}
|
||||
else
|
||||
pHandleNext->m_minEdges[axis]--;
|
||||
|
||||
pHandleEdge->m_minEdges[axis]++;
|
||||
|
||||
// swap the edges
|
||||
Edge swap = *pEdge;
|
||||
*pEdge = *pNext;
|
||||
*pNext = swap;
|
||||
|
||||
// increment
|
||||
pEdge++;
|
||||
pNext++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// sorting a max edge downwards can only ever *remove* overlaps
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
|
||||
{
|
||||
|
||||
Edge* pEdge = m_pEdges[axis] + edge;
|
||||
Edge* pPrev = pEdge - 1;
|
||||
Handle* pHandleEdge = getHandle(pEdge->m_handle);
|
||||
|
||||
while (pEdge->m_pos < pPrev->m_pos)
|
||||
{
|
||||
Handle* pHandlePrev = getHandle(pPrev->m_handle);
|
||||
|
||||
if (!pPrev->IsMax())
|
||||
{
|
||||
// if previous edge was a minimum remove any overlap between the two handles
|
||||
if (updateOverlaps)
|
||||
{
|
||||
//this is done during the overlappingpairarray iteration/narrowphase collision
|
||||
#ifndef USE_LAZY_REMOVAL
|
||||
Handle* handle0 = getHandle(pEdge->m_handle);
|
||||
Handle* handle1 = getHandle(pPrev->m_handle);
|
||||
m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
|
||||
|
||||
#endif //USE_LAZY_REMOVAL
|
||||
|
||||
}
|
||||
|
||||
// update edge reference in other handle
|
||||
pHandlePrev->m_minEdges[axis]++;;
|
||||
}
|
||||
else
|
||||
pHandlePrev->m_maxEdges[axis]++;
|
||||
|
||||
pHandleEdge->m_maxEdges[axis]--;
|
||||
|
||||
// swap the edges
|
||||
Edge swap = *pEdge;
|
||||
*pEdge = *pPrev;
|
||||
*pPrev = swap;
|
||||
|
||||
// decrement
|
||||
pEdge--;
|
||||
pPrev--;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_BROADPHASE
|
||||
debugPrintAxis(axis);
|
||||
#endif //DEBUG_BROADPHASE
|
||||
|
||||
}
|
||||
|
||||
// sorting a max edge upwards can only ever *add* overlaps
|
||||
template <typename BP_FP_INT_TYPE>
|
||||
void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
|
||||
{
|
||||
Edge* pEdge = m_pEdges[axis] + edge;
|
||||
Edge* pNext = pEdge + 1;
|
||||
Handle* pHandleEdge = getHandle(pEdge->m_handle);
|
||||
|
||||
while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
|
||||
{
|
||||
Handle* pHandleNext = getHandle(pNext->m_handle);
|
||||
|
||||
if (!pNext->IsMax())
|
||||
{
|
||||
// if next edge is a minimum check the bounds and add an overlap if necessary
|
||||
if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext))
|
||||
{
|
||||
Handle* handle0 = getHandle(pEdge->m_handle);
|
||||
Handle* handle1 = getHandle(pNext->m_handle);
|
||||
m_pairCache->addOverlappingPair(handle0,handle1);
|
||||
}
|
||||
|
||||
// update edge reference in other handle
|
||||
pHandleNext->m_minEdges[axis]--;
|
||||
}
|
||||
else
|
||||
pHandleNext->m_maxEdges[axis]--;
|
||||
|
||||
pHandleEdge->m_maxEdges[axis]++;
|
||||
|
||||
// swap the edges
|
||||
Edge swap = *pEdge;
|
||||
*pEdge = *pNext;
|
||||
*pNext = swap;
|
||||
|
||||
// increment
|
||||
pEdge++;
|
||||
pNext++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
|
||||
/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats.
|
||||
/// For large worlds and many objects, use bt32BitAxisSweep3 instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance.
|
||||
class btAxisSweep3 : public btAxisSweep3Internal<unsigned short int>
|
||||
{
|
||||
public:
|
||||
|
||||
btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0);
|
||||
|
||||
};
|
||||
|
||||
/// bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune.
|
||||
/// This comes at the cost of more memory per handle, and a bit slower performance.
|
||||
/// It uses arrays rather then lists for storage of the 3 axis.
|
||||
class bt32BitAxisSweep3 : public btAxisSweep3Internal<unsigned int>
|
||||
{
|
||||
public:
|
||||
|
||||
bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef BROADPHASE_INTERFACE_H
|
||||
#define BROADPHASE_INTERFACE_H
|
||||
|
||||
|
||||
|
||||
struct btDispatcherInfo;
|
||||
class btDispatcher;
|
||||
#include "btBroadphaseProxy.h"
|
||||
class btOverlappingPairCache;
|
||||
|
||||
#include "LinearMath/btVector3.h"
|
||||
|
||||
///BroadphaseInterface for aabb-overlapping object pairs
|
||||
class btBroadphaseInterface
|
||||
{
|
||||
public:
|
||||
virtual ~btBroadphaseInterface() {}
|
||||
|
||||
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher) =0;
|
||||
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0;
|
||||
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0;
|
||||
|
||||
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
|
||||
virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0;
|
||||
|
||||
virtual btOverlappingPairCache* getOverlappingPairCache()=0;
|
||||
virtual const btOverlappingPairCache* getOverlappingPairCache() const =0;
|
||||
|
||||
};
|
||||
|
||||
#endif //BROADPHASE_INTERFACE_H
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btBroadphaseProxy.h"
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef BROADPHASE_PROXY_H
|
||||
#define BROADPHASE_PROXY_H
|
||||
|
||||
#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
|
||||
#include "LinearMath/btAlignedAllocator.h"
|
||||
|
||||
|
||||
/// btDispatcher uses these types
|
||||
/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave
|
||||
/// to facilitate type checking
|
||||
enum BroadphaseNativeTypes
|
||||
{
|
||||
// polyhedral convex shapes
|
||||
BOX_SHAPE_PROXYTYPE,
|
||||
TRIANGLE_SHAPE_PROXYTYPE,
|
||||
TETRAHEDRAL_SHAPE_PROXYTYPE,
|
||||
CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE,
|
||||
CONVEX_HULL_SHAPE_PROXYTYPE,
|
||||
//implicit convex shapes
|
||||
IMPLICIT_CONVEX_SHAPES_START_HERE,
|
||||
SPHERE_SHAPE_PROXYTYPE,
|
||||
MULTI_SPHERE_SHAPE_PROXYTYPE,
|
||||
CAPSULE_SHAPE_PROXYTYPE,
|
||||
CONE_SHAPE_PROXYTYPE,
|
||||
CONVEX_SHAPE_PROXYTYPE,
|
||||
CYLINDER_SHAPE_PROXYTYPE,
|
||||
UNIFORM_SCALING_SHAPE_PROXYTYPE,
|
||||
MINKOWSKI_SUM_SHAPE_PROXYTYPE,
|
||||
MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE,
|
||||
//concave shapes
|
||||
CONCAVE_SHAPES_START_HERE,
|
||||
//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
|
||||
TRIANGLE_MESH_SHAPE_PROXYTYPE,
|
||||
///used for demo integration FAST/Swift collision library and Bullet
|
||||
FAST_CONCAVE_MESH_PROXYTYPE,
|
||||
//terrain
|
||||
TERRAIN_SHAPE_PROXYTYPE,
|
||||
///Used for GIMPACT Trimesh integration
|
||||
GIMPACT_SHAPE_PROXYTYPE,
|
||||
|
||||
EMPTY_SHAPE_PROXYTYPE,
|
||||
STATIC_PLANE_PROXYTYPE,
|
||||
CONCAVE_SHAPES_END_HERE,
|
||||
|
||||
COMPOUND_SHAPE_PROXYTYPE,
|
||||
|
||||
MAX_BROADPHASE_COLLISION_TYPES
|
||||
};
|
||||
|
||||
|
||||
///btBroadphaseProxy
|
||||
//ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy
|
||||
struct btBroadphaseProxy
|
||||
{
|
||||
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
///optional filtering to cull potential collisions
|
||||
enum CollisionFilterGroups
|
||||
{
|
||||
DefaultFilter = 1,
|
||||
StaticFilter = 2,
|
||||
KinematicFilter = 4,
|
||||
DebrisFilter = 8,
|
||||
SensorTrigger = 16,
|
||||
AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
|
||||
};
|
||||
|
||||
//Usually the client btCollisionObject or Rigidbody class
|
||||
void* m_clientObject;
|
||||
|
||||
///in the case of btMultiSapBroadphase, we store the collifionFilterGroup/Mask in the m_multiSapParentProxy
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
short int m_collisionFilterGroup;
|
||||
short int m_collisionFilterMask;
|
||||
};
|
||||
|
||||
void* m_multiSapParentProxy;
|
||||
|
||||
};
|
||||
|
||||
int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
|
||||
int m_unusedPadding; //making the structure 16 bytes, better for alignment etc.
|
||||
|
||||
SIMD_FORCE_INLINE int getUid()
|
||||
{
|
||||
return m_uniqueId;//(int)this;
|
||||
}
|
||||
|
||||
//used for memory pools
|
||||
btBroadphaseProxy() :m_clientObject(0){}
|
||||
|
||||
btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask)
|
||||
:m_clientObject(userPtr),
|
||||
m_collisionFilterGroup(collisionFilterGroup),
|
||||
m_collisionFilterMask(collisionFilterMask)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType)
|
||||
{
|
||||
return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE);
|
||||
}
|
||||
|
||||
static SIMD_FORCE_INLINE bool isConvex(int proxyType)
|
||||
{
|
||||
return (proxyType < CONCAVE_SHAPES_START_HERE);
|
||||
}
|
||||
|
||||
static SIMD_FORCE_INLINE bool isConcave(int proxyType)
|
||||
{
|
||||
return ((proxyType > CONCAVE_SHAPES_START_HERE) &&
|
||||
(proxyType < CONCAVE_SHAPES_END_HERE));
|
||||
}
|
||||
static SIMD_FORCE_INLINE bool isCompound(int proxyType)
|
||||
{
|
||||
return (proxyType == COMPOUND_SHAPE_PROXYTYPE);
|
||||
}
|
||||
static SIMD_FORCE_INLINE bool isInfinite(int proxyType)
|
||||
{
|
||||
return (proxyType == STATIC_PLANE_PROXYTYPE);
|
||||
}
|
||||
|
||||
}
|
||||
;
|
||||
|
||||
class btCollisionAlgorithm;
|
||||
|
||||
struct btBroadphaseProxy;
|
||||
|
||||
|
||||
|
||||
/// contains a pair of aabb-overlapping objects
|
||||
ATTRIBUTE_ALIGNED16(struct) btBroadphasePair
|
||||
{
|
||||
btBroadphasePair ()
|
||||
:
|
||||
m_pProxy0(0),
|
||||
m_pProxy1(0),
|
||||
m_algorithm(0),
|
||||
m_userInfo(0)
|
||||
{
|
||||
}
|
||||
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
btBroadphasePair(const btBroadphasePair& other)
|
||||
: m_pProxy0(other.m_pProxy0),
|
||||
m_pProxy1(other.m_pProxy1),
|
||||
m_algorithm(other.m_algorithm),
|
||||
m_userInfo(other.m_userInfo)
|
||||
{
|
||||
}
|
||||
btBroadphasePair(btBroadphaseProxy& proxy0,btBroadphaseProxy& proxy1)
|
||||
{
|
||||
|
||||
//keep them sorted, so the std::set operations work
|
||||
if (&proxy0 < &proxy1)
|
||||
{
|
||||
m_pProxy0 = &proxy0;
|
||||
m_pProxy1 = &proxy1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pProxy0 = &proxy1;
|
||||
m_pProxy1 = &proxy0;
|
||||
}
|
||||
|
||||
m_algorithm = 0;
|
||||
m_userInfo = 0;
|
||||
|
||||
}
|
||||
|
||||
btBroadphaseProxy* m_pProxy0;
|
||||
btBroadphaseProxy* m_pProxy1;
|
||||
|
||||
mutable btCollisionAlgorithm* m_algorithm;
|
||||
mutable void* m_userInfo;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
//comparison for set operation, see Solid DT_Encounter
|
||||
SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePair& b)
|
||||
{
|
||||
return a.m_pProxy0 < b.m_pProxy0 ||
|
||||
(a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 < b.m_pProxy1);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
class btBroadphasePairSortPredicate
|
||||
{
|
||||
public:
|
||||
|
||||
bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b )
|
||||
{
|
||||
return a.m_pProxy0 > b.m_pProxy0 ||
|
||||
(a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 > b.m_pProxy1) ||
|
||||
(a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b)
|
||||
{
|
||||
return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1);
|
||||
}
|
||||
|
||||
|
||||
#endif //BROADPHASE_PROXY_H
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btCollisionAlgorithm.h"
|
||||
#include "btDispatcher.h"
|
||||
|
||||
btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
|
||||
{
|
||||
m_dispatcher = ci.m_dispatcher1;
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef COLLISION_ALGORITHM_H
|
||||
#define COLLISION_ALGORITHM_H
|
||||
|
||||
#include "LinearMath/btScalar.h"
|
||||
|
||||
struct btBroadphaseProxy;
|
||||
class btDispatcher;
|
||||
class btManifoldResult;
|
||||
class btCollisionObject;
|
||||
struct btDispatcherInfo;
|
||||
class btPersistentManifold;
|
||||
|
||||
|
||||
struct btCollisionAlgorithmConstructionInfo
|
||||
{
|
||||
btCollisionAlgorithmConstructionInfo()
|
||||
:m_dispatcher1(0),
|
||||
m_manifold(0)
|
||||
{
|
||||
}
|
||||
btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp)
|
||||
:m_dispatcher1(dispatcher)
|
||||
{
|
||||
(void)temp;
|
||||
}
|
||||
|
||||
btDispatcher* m_dispatcher1;
|
||||
btPersistentManifold* m_manifold;
|
||||
|
||||
int getDispatcherId();
|
||||
|
||||
};
|
||||
|
||||
|
||||
///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher.
|
||||
///It is persistent over frames
|
||||
class btCollisionAlgorithm
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
btDispatcher* m_dispatcher;
|
||||
|
||||
protected:
|
||||
int getDispatcherId();
|
||||
|
||||
public:
|
||||
|
||||
btCollisionAlgorithm() {};
|
||||
|
||||
btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
|
||||
|
||||
virtual ~btCollisionAlgorithm() {};
|
||||
|
||||
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
|
||||
|
||||
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //COLLISION_ALGORITHM_H
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btDispatcher.h"
|
||||
|
||||
btDispatcher::~btDispatcher()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef _DISPATCHER_H
|
||||
#define _DISPATCHER_H
|
||||
|
||||
#include "LinearMath/btScalar.h"
|
||||
|
||||
class btCollisionAlgorithm;
|
||||
struct btBroadphaseProxy;
|
||||
class btRigidBody;
|
||||
class btCollisionObject;
|
||||
class btOverlappingPairCache;
|
||||
|
||||
|
||||
class btPersistentManifold;
|
||||
class btStackAlloc;
|
||||
|
||||
struct btDispatcherInfo
|
||||
{
|
||||
enum DispatchFunc
|
||||
{
|
||||
DISPATCH_DISCRETE = 1,
|
||||
DISPATCH_CONTINUOUS
|
||||
};
|
||||
btDispatcherInfo()
|
||||
:m_timeStep(btScalar(0.)),
|
||||
m_stepCount(0),
|
||||
m_dispatchFunc(DISPATCH_DISCRETE),
|
||||
m_timeOfImpact(btScalar(1.)),
|
||||
m_useContinuous(false),
|
||||
m_debugDraw(0),
|
||||
m_enableSatConvex(false),
|
||||
m_enableSPU(false),
|
||||
m_stackAllocator(0)
|
||||
{
|
||||
|
||||
}
|
||||
btScalar m_timeStep;
|
||||
int m_stepCount;
|
||||
int m_dispatchFunc;
|
||||
btScalar m_timeOfImpact;
|
||||
bool m_useContinuous;
|
||||
class btIDebugDraw* m_debugDraw;
|
||||
bool m_enableSatConvex;
|
||||
bool m_enableSPU;
|
||||
btStackAlloc* m_stackAllocator;
|
||||
|
||||
};
|
||||
|
||||
/// btDispatcher can be used in combination with broadphase to dispatch overlapping pairs.
|
||||
/// For example for pairwise collision detection or user callbacks (game logic).
|
||||
class btDispatcher
|
||||
{
|
||||
|
||||
|
||||
public:
|
||||
virtual ~btDispatcher() ;
|
||||
|
||||
virtual btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold=0) = 0;
|
||||
|
||||
virtual btPersistentManifold* getNewManifold(void* body0,void* body1)=0;
|
||||
|
||||
virtual void releaseManifold(btPersistentManifold* manifold)=0;
|
||||
|
||||
virtual void clearManifold(btPersistentManifold* manifold)=0;
|
||||
|
||||
virtual bool needsCollision(btCollisionObject* body0,btCollisionObject* body1) = 0;
|
||||
|
||||
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0;
|
||||
|
||||
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)=0;
|
||||
|
||||
virtual int getNumManifolds() const = 0;
|
||||
|
||||
virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0;
|
||||
|
||||
virtual btPersistentManifold** getInternalManifoldPointer() = 0;
|
||||
|
||||
virtual void* allocateCollisionAlgorithm(int size) = 0;
|
||||
|
||||
virtual void freeCollisionAlgorithm(void* ptr) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //_DISPATCHER_H
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btMultiSapBroadphase.h"
|
||||
|
||||
#include "btSimpleBroadphase.h"
|
||||
#include "LinearMath/btAabbUtil2.h"
|
||||
|
||||
/// btSapBroadphaseArray m_sapBroadphases;
|
||||
|
||||
/// btOverlappingPairCache* m_overlappingPairs;
|
||||
extern int gOverlappingPairs;
|
||||
|
||||
btMultiSapBroadphase::btMultiSapBroadphase(int maxProxies,btOverlappingPairCache* pairCache)
|
||||
:m_overlappingPairs(pairCache),
|
||||
m_ownsPairCache(false),
|
||||
m_invalidPair(0)
|
||||
{
|
||||
if (!m_overlappingPairs)
|
||||
{
|
||||
m_ownsPairCache = true;
|
||||
void* mem = btAlignedAlloc(sizeof(btOverlappingPairCache),16);
|
||||
m_overlappingPairs = new (mem)btOverlappingPairCache();
|
||||
}
|
||||
|
||||
struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback
|
||||
{
|
||||
virtual ~btMultiSapOverlapFilterCallback()
|
||||
{}
|
||||
// return true when pairs need collision
|
||||
virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const
|
||||
{
|
||||
btMultiSapBroadphase::btMultiSapProxy* multiSapProxy0 = (btMultiSapBroadphase::btMultiSapProxy*)childProxy0->m_multiSapParentProxy;
|
||||
btMultiSapBroadphase::btMultiSapProxy* multiSapProxy1 = (btMultiSapBroadphase::btMultiSapProxy*)childProxy1->m_multiSapParentProxy;
|
||||
|
||||
bool collides = (multiSapProxy0->m_collisionFilterGroup & multiSapProxy1->m_collisionFilterMask) != 0;
|
||||
collides = collides && (multiSapProxy1->m_collisionFilterGroup & multiSapProxy0->m_collisionFilterMask);
|
||||
|
||||
return collides;
|
||||
}
|
||||
};
|
||||
|
||||
m_filterCallback = new btMultiSapOverlapFilterCallback();
|
||||
|
||||
m_overlappingPairs->setOverlapFilterCallback(m_filterCallback);
|
||||
|
||||
m_simpleBroadphase = new btSimpleBroadphase(maxProxies,m_overlappingPairs);
|
||||
}
|
||||
|
||||
btMultiSapBroadphase::~btMultiSapBroadphase()
|
||||
{
|
||||
if (m_ownsPairCache)
|
||||
{
|
||||
btAlignedFree(m_overlappingPairs);
|
||||
}
|
||||
}
|
||||
|
||||
btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher)
|
||||
{
|
||||
btMultiSapProxy* proxy = new btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask);
|
||||
m_multiSapProxies.push_back(proxy);
|
||||
|
||||
///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
|
||||
///this is needed to be able to calculate the aabb overlap
|
||||
btBroadphaseProxy* simpleProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask, dispatcher);
|
||||
simpleProxy->m_multiSapParentProxy = proxy;
|
||||
|
||||
btChildProxy* childProxyRef = new btChildProxy();
|
||||
childProxyRef->m_proxy = simpleProxy;
|
||||
childProxyRef->m_childBroadphase = m_simpleBroadphase;
|
||||
proxy->m_childProxies.push_back(childProxyRef);
|
||||
|
||||
///this should deal with inserting/removal into child broadphases
|
||||
setAabb(proxy,aabbMin,aabbMax,dispatcher);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
|
||||
{
|
||||
///not yet
|
||||
btAssert(0);
|
||||
|
||||
}
|
||||
void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
|
||||
{
|
||||
btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
|
||||
multiProxy->m_aabbMin = aabbMin;
|
||||
multiProxy->m_aabbMax = aabbMax;
|
||||
|
||||
for (int i=0;i<multiProxy->m_childProxies.size();i++)
|
||||
{
|
||||
btChildProxy* childProxyRef = multiProxy->m_childProxies[i];
|
||||
childProxyRef->m_childBroadphase->setAabb(childProxyRef->m_proxy,aabbMin,aabbMax,dispatcher);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
|
||||
void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
|
||||
{
|
||||
m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
|
||||
|
||||
#ifndef USE_HASH_PAIRCACHE
|
||||
|
||||
btBroadphasePairArray& overlappingPairArray = m_overlappingPairs->getOverlappingPairArray();
|
||||
|
||||
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
|
||||
overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
|
||||
|
||||
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
|
||||
m_invalidPair = 0;
|
||||
|
||||
|
||||
btBroadphasePair previousPair;
|
||||
previousPair.m_pProxy0 = 0;
|
||||
previousPair.m_pProxy1 = 0;
|
||||
previousPair.m_algorithm = 0;
|
||||
|
||||
int i;
|
||||
|
||||
for (i=0;i<overlappingPairArray.size();i++)
|
||||
{
|
||||
|
||||
btBroadphasePair& pair = overlappingPairArray[i];
|
||||
|
||||
bool isDuplicate = (pair == previousPair);
|
||||
|
||||
previousPair = pair;
|
||||
|
||||
bool needsRemoval = false;
|
||||
|
||||
if (!isDuplicate)
|
||||
{
|
||||
bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
|
||||
|
||||
if (hasOverlap)
|
||||
{
|
||||
needsRemoval = false;//callback->processOverlap(pair);
|
||||
} else
|
||||
{
|
||||
needsRemoval = true;
|
||||
}
|
||||
} else
|
||||
{
|
||||
//remove duplicate
|
||||
needsRemoval = true;
|
||||
//should have no algorithm
|
||||
btAssert(!pair.m_algorithm);
|
||||
}
|
||||
|
||||
if (needsRemoval)
|
||||
{
|
||||
m_overlappingPairs->cleanOverlappingPair(pair,dispatcher);
|
||||
|
||||
// m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
|
||||
// m_overlappingPairArray.pop_back();
|
||||
pair.m_pProxy0 = 0;
|
||||
pair.m_pProxy1 = 0;
|
||||
m_invalidPair++;
|
||||
gOverlappingPairs--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///if you don't like to skip the invalid pairs in the array, execute following code:
|
||||
#define CLEAN_INVALID_PAIRS 1
|
||||
#ifdef CLEAN_INVALID_PAIRS
|
||||
|
||||
//perform a sort, to sort 'invalid' pairs to the end
|
||||
overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
|
||||
|
||||
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
|
||||
m_invalidPair = 0;
|
||||
#endif//CLEAN_INVALID_PAIRS
|
||||
|
||||
#endif //USE_HASH_PAIRCACHE
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1)
|
||||
{
|
||||
btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy;
|
||||
btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy;
|
||||
|
||||
return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax,
|
||||
multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax);
|
||||
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#ifndef BT_MULTI_SAP_BROADPHASE
|
||||
#define BT_MULTI_SAP_BROADPHASE
|
||||
|
||||
#include "btBroadphaseInterface.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
#include "btOverlappingPairCache.h"
|
||||
|
||||
class btAxisSweep3;
|
||||
class btSimpleBroadphase;
|
||||
|
||||
|
||||
typedef btAlignedObjectArray<btAxisSweep3*> btSapBroadphaseArray;
|
||||
|
||||
///multi SAP broadphase
|
||||
///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328
|
||||
///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329
|
||||
class btMultiSapBroadphase :public btBroadphaseInterface
|
||||
{
|
||||
btSapBroadphaseArray m_sapBroadphases;
|
||||
|
||||
btSimpleBroadphase* m_simpleBroadphase;
|
||||
|
||||
btOverlappingPairCache* m_overlappingPairs;
|
||||
|
||||
bool m_ownsPairCache;
|
||||
|
||||
btOverlapFilterCallback* m_filterCallback;
|
||||
|
||||
int m_invalidPair;
|
||||
|
||||
struct btChildProxy
|
||||
{
|
||||
btBroadphaseProxy* m_proxy;
|
||||
btBroadphaseInterface* m_childBroadphase;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
struct btMultiSapProxy : public btBroadphaseProxy
|
||||
{
|
||||
|
||||
///array with all the entries that this proxy belongs to
|
||||
btAlignedObjectArray<btChildProxy*> m_childProxies;
|
||||
btVector3 m_aabbMin;
|
||||
btVector3 m_aabbMax;
|
||||
|
||||
int m_shapeType;
|
||||
void* m_userPtr;
|
||||
short int m_collisionFilterGroup;
|
||||
short int m_collisionFilterMask;
|
||||
|
||||
btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask)
|
||||
:m_aabbMin(aabbMin),
|
||||
m_aabbMax(aabbMax),
|
||||
m_shapeType(shapeType),
|
||||
m_userPtr(userPtr),
|
||||
m_collisionFilterGroup(collisionFilterGroup),
|
||||
m_collisionFilterMask(collisionFilterMask)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
btAlignedObjectArray<btMultiSapProxy*> m_multiSapProxies;
|
||||
|
||||
public:
|
||||
|
||||
btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0);
|
||||
|
||||
btSapBroadphaseArray getBroadphaseArray()
|
||||
{
|
||||
return m_sapBroadphases;
|
||||
}
|
||||
|
||||
const btSapBroadphaseArray getBroadphaseArray() const
|
||||
{
|
||||
return m_sapBroadphases;
|
||||
}
|
||||
|
||||
virtual ~btMultiSapBroadphase();
|
||||
|
||||
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher);
|
||||
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
|
||||
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
|
||||
|
||||
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
|
||||
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
|
||||
|
||||
bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
|
||||
|
||||
virtual btOverlappingPairCache* getOverlappingPairCache()
|
||||
{
|
||||
return m_overlappingPairs;
|
||||
}
|
||||
virtual const btOverlappingPairCache* getOverlappingPairCache() const
|
||||
{
|
||||
return m_overlappingPairs;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //BT_MULTI_SAP_BROADPHASE
|
|
@ -0,0 +1,474 @@
|
|||
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "btOverlappingPairCache.h"
|
||||
|
||||
#include "btDispatcher.h"
|
||||
#include "btCollisionAlgorithm.h"
|
||||
|
||||
int gOverlappingPairs = 0;
|
||||
|
||||
int gRemovePairs =0;
|
||||
int gAddedPairs =0;
|
||||
int gFindPairs =0;
|
||||
|
||||
btOverlappingPairCache::btOverlappingPairCache():
|
||||
m_overlapFilterCallback(0),
|
||||
m_blockedForChanges(false)
|
||||
{
|
||||
int initialAllocatedSize= 2;
|
||||
m_overlappingPairArray.reserve(initialAllocatedSize);
|
||||
#ifdef USE_HASH_PAIRCACHE
|
||||
growTables();
|
||||
#endif //USE_HASH_PAIRCACHE
|
||||
}
|
||||
|
||||
|
||||
btOverlappingPairCache::~btOverlappingPairCache()
|
||||
{
|
||||
//todo/test: show we erase/delete data, or is it automatic
|
||||
}
|
||||
|
||||
void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
|
||||
{
|
||||
if (pair.m_algorithm)
|
||||
{
|
||||
{
|
||||
pair.m_algorithm->~btCollisionAlgorithm();
|
||||
dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
|
||||
pair.m_algorithm=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
class CleanPairCallback : public btOverlapCallback
|
||||
{
|
||||
btBroadphaseProxy* m_cleanProxy;
|
||||
btOverlappingPairCache* m_pairCache;
|
||||
btDispatcher* m_dispatcher;
|
||||
|
||||
public:
|
||||
CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
|
||||
:m_cleanProxy(cleanProxy),
|
||||
m_pairCache(pairCache),
|
||||
m_dispatcher(dispatcher)
|
||||
{
|
||||
}
|
||||
virtual bool processOverlap(btBroadphasePair& pair)
|
||||
{
|
||||
if ((pair.m_pProxy0 == m_cleanProxy) ||
|
||||
(pair.m_pProxy1 == m_cleanProxy))
|
||||
{
|
||||
m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CleanPairCallback cleanPairs(proxy,this,dispatcher);
|
||||
|
||||
processAllOverlappingPairs(&cleanPairs,dispatcher);
|
||||
|
||||
}
|
||||
|
||||
void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
class RemovePairCallback : public btOverlapCallback
|
||||
{
|
||||
btBroadphaseProxy* m_obsoleteProxy;
|
||||
|
||||
public:
|
||||
RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
|
||||
:m_obsoleteProxy(obsoleteProxy)
|
||||
{
|
||||
}
|
||||
virtual bool processOverlap(btBroadphasePair& pair)
|
||||
{
|
||||
return ((pair.m_pProxy0 == m_obsoleteProxy) ||
|
||||
(pair.m_pProxy1 == m_obsoleteProxy));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
RemovePairCallback removeCallback(proxy);
|
||||
|
||||
processAllOverlappingPairs(&removeCallback,dispatcher);
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_HASH_PAIRCACHE
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
btBroadphasePair* btOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
|
||||
{
|
||||
gFindPairs++;
|
||||
|
||||
int proxyId1 = proxy0->getUid();
|
||||
int proxyId2 = proxy1->getUid();
|
||||
|
||||
if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);
|
||||
|
||||
int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1);
|
||||
|
||||
int index = m_hashTable[hash];
|
||||
while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
|
||||
{
|
||||
index = m_next[index];
|
||||
}
|
||||
|
||||
if (index == BT_NULL_PAIR)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
btAssert(index < m_overlappingPairArray.size());
|
||||
|
||||
return &m_overlappingPairArray[index];
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void btOverlappingPairCache::growTables()
|
||||
{
|
||||
|
||||
int newCapacity = m_overlappingPairArray.capacity();
|
||||
|
||||
if (m_hashTable.size() < newCapacity)
|
||||
{
|
||||
//grow hashtable and next table
|
||||
int curHashtableSize = m_hashTable.size();
|
||||
|
||||
m_hashTable.resize(newCapacity);
|
||||
m_next.resize(newCapacity);
|
||||
|
||||
|
||||
int i;
|
||||
|
||||
for (i= 0; i < newCapacity; ++i)
|
||||
{
|
||||
m_hashTable[i] = BT_NULL_PAIR;
|
||||
}
|
||||
for (i = 0; i < newCapacity; ++i)
|
||||
{
|
||||
m_next[i] = BT_NULL_PAIR;
|
||||
}
|
||||
|
||||
for(i=0;i<curHashtableSize;i++)
|
||||
{
|
||||
|
||||
const btBroadphasePair& pair = m_overlappingPairArray[i];
|
||||
int proxyId1 = pair.m_pProxy0->getUid();
|
||||
int proxyId2 = pair.m_pProxy1->getUid();
|
||||
if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);
|
||||
int hashValue = getHash(proxyId1,proxyId2) & (m_overlappingPairArray.capacity()-1); // New hash value with new mask
|
||||
m_next[i] = m_hashTable[hashValue];
|
||||
m_hashTable[hashValue] = i;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
btBroadphasePair* btOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
|
||||
{
|
||||
int proxyId1 = proxy0->getUid();
|
||||
int proxyId2 = proxy1->getUid();
|
||||
|
||||
if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);
|
||||
|
||||
int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1);
|
||||
|
||||
|
||||
|
||||
btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
|
||||
if (pair != NULL)
|
||||
{
|
||||
return pair;
|
||||
}
|
||||
|
||||
int count = m_overlappingPairArray.size();
|
||||
int oldCapacity = m_overlappingPairArray.capacity();
|
||||
void* mem = &m_overlappingPairArray.expand();
|
||||
int newCapacity = m_overlappingPairArray.capacity();
|
||||
|
||||
if (oldCapacity < newCapacity)
|
||||
{
|
||||
growTables();
|
||||
//hash with new capacity
|
||||
hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1);
|
||||
}
|
||||
|
||||
pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
|
||||
// pair->m_pProxy0 = proxy0;
|
||||
// pair->m_pProxy1 = proxy1;
|
||||
pair->m_algorithm = 0;
|
||||
pair->m_userInfo = 0;
|
||||
|
||||
|
||||
m_next[count] = m_hashTable[hash];
|
||||
m_hashTable[hash] = count;
|
||||
|
||||
return pair;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void* btOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
|
||||
{
|
||||
gRemovePairs++;
|
||||
|
||||
int proxyId1 = proxy0->getUid();
|
||||
int proxyId2 = proxy1->getUid();
|
||||
|
||||
if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);
|
||||
|
||||
int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1);
|
||||
|
||||
btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
|
||||
if (pair == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
cleanOverlappingPair(*pair,dispatcher);
|
||||
|
||||
void* userData = pair->m_userInfo;
|
||||
|
||||
btAssert(pair->m_pProxy0->getUid() == proxyId1);
|
||||
btAssert(pair->m_pProxy1->getUid() == proxyId2);
|
||||
|
||||
int pairIndex = int(pair - &m_overlappingPairArray[0]);
|
||||
btAssert(pairIndex < m_overlappingPairArray.size());
|
||||
|
||||
// Remove the pair from the hash table.
|
||||
int index = m_hashTable[hash];
|
||||
btAssert(index != BT_NULL_PAIR);
|
||||
|
||||
int previous = BT_NULL_PAIR;
|
||||
while (index != pairIndex)
|
||||
{
|
||||
previous = index;
|
||||
index = m_next[index];
|
||||
}
|
||||
|
||||
if (previous != BT_NULL_PAIR)
|
||||
{
|
||||
btAssert(m_next[previous] == pairIndex);
|
||||
m_next[previous] = m_next[pairIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hashTable[hash] = m_next[pairIndex];
|
||||
}
|
||||
|
||||
// We now move the last pair into spot of the
|
||||
// pair being removed. We need to fix the hash
|
||||
// table indices to support the move.
|
||||
|
||||
int lastPairIndex = m_overlappingPairArray.size() - 1;
|
||||
|
||||
// If the removed pair is the last pair, we are done.
|
||||
if (lastPairIndex == pairIndex)
|
||||
{
|
||||
m_overlappingPairArray.pop_back();
|
||||
return userData;
|
||||
}
|
||||
|
||||
// Remove the last pair from the hash table.
|
||||
const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
|
||||
int lastHash = getHash(last->m_pProxy0->getUid(), last->m_pProxy1->getUid()) & (m_overlappingPairArray.capacity()-1);
|
||||
|
||||
index = m_hashTable[lastHash];
|
||||
btAssert(index != BT_NULL_PAIR);
|
||||
|
||||
previous = BT_NULL_PAIR;
|
||||
while (index != lastPairIndex)
|
||||
{
|
||||
previous = index;
|
||||
index = m_next[index];
|
||||
}
|
||||
|
||||
if (previous != BT_NULL_PAIR)
|
||||
{
|
||||
btAssert(m_next[previous] == lastPairIndex);
|
||||
m_next[previous] = m_next[lastPairIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hashTable[lastHash] = m_next[lastPairIndex];
|
||||
}
|
||||
|
||||
// Copy the last pair into the remove pair's spot.
|
||||
m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
|
||||
|
||||
// Insert the last pair into the hash table
|
||||
m_next[pairIndex] = m_hashTable[lastHash];
|
||||
m_hashTable[lastHash] = pairIndex;
|
||||
|
||||
m_overlappingPairArray.pop_back();
|
||||
|
||||
return userData;
|
||||
}
|
||||
#include <stdio.h>
|
||||
|
||||
void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
|
||||
for (i=0;i<m_overlappingPairArray.size();)
|
||||
{
|
||||
|
||||
btBroadphasePair* pair = &m_overlappingPairArray[i];
|
||||
if (callback->processOverlap(*pair))
|
||||
{
|
||||
removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher);
|
||||
|
||||
gOverlappingPairs--;
|
||||
} else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
||||
|
||||
|
||||
void* btOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher )
|
||||
{
|
||||
#ifndef USE_LAZY_REMOVAL
|
||||
|
||||
btBroadphasePair findPair(*proxy0,*proxy1);
|
||||
|
||||
int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
|
||||
if (findIndex < m_overlappingPairArray.size())
|
||||
{
|
||||
gOverlappingPairs--;
|
||||
btBroadphasePair& pair = m_overlappingPairArray[findIndex];
|
||||
void* userData = pair.m_userInfo;
|
||||
cleanOverlappingPair(pair,dispatcher);
|
||||
|
||||
m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
|
||||
m_overlappingPairArray.pop_back();
|
||||
return userData;
|
||||
}
|
||||
#endif //USE_LAZY_REMOVAL
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
btBroadphasePair* btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
|
||||
{
|
||||
//don't add overlap with own
|
||||
assert(proxy0 != proxy1);
|
||||
|
||||
if (!needsBroadphaseCollision(proxy0,proxy1))
|
||||
return 0;
|
||||
|
||||
void* mem = &m_overlappingPairArray.expand();
|
||||
btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
|
||||
gOverlappingPairs++;
|
||||
return pair;
|
||||
|
||||
}
|
||||
|
||||
///this findPair becomes really slow. Either sort the list to speedup the query, or
|
||||
///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
|
||||
///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
|
||||
///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
|
||||
btBroadphasePair* btOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
|
||||
{
|
||||
if (!needsBroadphaseCollision(proxy0,proxy1))
|
||||
return 0;
|
||||
|
||||
btBroadphasePair tmpPair(*proxy0,*proxy1);
|
||||
int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
|
||||
|
||||
if (findIndex < m_overlappingPairArray.size())
|
||||
{
|
||||
//assert(it != m_overlappingPairSet.end());
|
||||
btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
|
||||
return pair;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
for (i=0;i<m_overlappingPairArray.size();)
|
||||
{
|
||||
|
||||
btBroadphasePair* pair = &m_overlappingPairArray[i];
|
||||
if (callback->processOverlap(*pair))
|
||||
{
|
||||
cleanOverlappingPair(*pair,dispatcher);
|
||||
|
||||
m_overlappingPairArray.swap(i,m_overlappingPairArray.capacity()-1);
|
||||
m_overlappingPairArray.pop_back();
|
||||
gOverlappingPairs--;
|
||||
} else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif //USE_HASH_PAIRCACHE
|
|
@ -0,0 +1,323 @@
|
|||
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef OVERLAPPING_PAIR_CACHE_H
|
||||
#define OVERLAPPING_PAIR_CACHE_H
|
||||
|
||||
|
||||
#include "btBroadphaseInterface.h"
|
||||
#include "btBroadphaseProxy.h"
|
||||
#include "LinearMath/btPoint3.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
class btDispatcher;
|
||||
|
||||
///disable the USE_HASH_PAIRCACHE define to use a pair manager that sorts the pairs to find duplicates/non-overlap
|
||||
#define USE_HASH_PAIRCACHE 1
|
||||
|
||||
|
||||
struct btOverlapCallback
|
||||
{
|
||||
virtual ~btOverlapCallback()
|
||||
{}
|
||||
//return true for deletion of the pair
|
||||
virtual bool processOverlap(btBroadphasePair& pair) = 0;
|
||||
};
|
||||
|
||||
struct btOverlapFilterCallback
|
||||
{
|
||||
virtual ~btOverlapFilterCallback()
|
||||
{}
|
||||
// return true when pairs need collision
|
||||
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
|
||||
};
|
||||
|
||||
typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
|
||||
|
||||
#ifdef USE_HASH_PAIRCACHE
|
||||
|
||||
|
||||
/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
|
||||
|
||||
extern int gRemovePairs;
|
||||
extern int gAddedPairs;
|
||||
extern int gFindPairs;
|
||||
|
||||
const int BT_NULL_PAIR=0xffffffff;
|
||||
|
||||
class btOverlappingPairCache
|
||||
{
|
||||
btBroadphasePairArray m_overlappingPairArray;
|
||||
btOverlapFilterCallback* m_overlapFilterCallback;
|
||||
bool m_blockedForChanges;
|
||||
|
||||
|
||||
public:
|
||||
btOverlappingPairCache();
|
||||
virtual ~btOverlappingPairCache();
|
||||
|
||||
|
||||
void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
|
||||
|
||||
void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
|
||||
|
||||
SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
|
||||
{
|
||||
if (m_overlapFilterCallback)
|
||||
return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
|
||||
|
||||
bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
|
||||
collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
|
||||
|
||||
return collides;
|
||||
}
|
||||
|
||||
// Add a pair and return the new pair. If the pair already exists,
|
||||
// no new pair is created and the old one is returned.
|
||||
SIMD_FORCE_INLINE btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
|
||||
{
|
||||
gAddedPairs++;
|
||||
|
||||
if (!needsBroadphaseCollision(proxy0,proxy1))
|
||||
return 0;
|
||||
|
||||
return internalAddPair(proxy0,proxy1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
|
||||
|
||||
|
||||
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
|
||||
|
||||
btBroadphasePair* getOverlappingPairArrayPtr()
|
||||
{
|
||||
return &m_overlappingPairArray[0];
|
||||
}
|
||||
|
||||
const btBroadphasePair* getOverlappingPairArrayPtr() const
|
||||
{
|
||||
return &m_overlappingPairArray[0];
|
||||
}
|
||||
|
||||
btBroadphasePairArray& getOverlappingPairArray()
|
||||
{
|
||||
return m_overlappingPairArray;
|
||||
}
|
||||
|
||||
const btBroadphasePairArray& getOverlappingPairArray() const
|
||||
{
|
||||
return m_overlappingPairArray;
|
||||
}
|
||||
|
||||
void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
|
||||
|
||||
|
||||
|
||||
btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
|
||||
|
||||
int GetCount() const { return m_overlappingPairArray.size(); }
|
||||
// btBroadphasePair* GetPairs() { return m_pairs; }
|
||||
|
||||
btOverlapFilterCallback* getOverlapFilterCallback()
|
||||
{
|
||||
return m_overlapFilterCallback;
|
||||
}
|
||||
|
||||
void setOverlapFilterCallback(btOverlapFilterCallback* callback)
|
||||
{
|
||||
m_overlapFilterCallback = callback;
|
||||
}
|
||||
|
||||
int getNumOverlappingPairs() const
|
||||
{
|
||||
return m_overlappingPairArray.size();
|
||||
}
|
||||
private:
|
||||
|
||||
btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
|
||||
|
||||
void growTables();
|
||||
|
||||
SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2)
|
||||
{
|
||||
return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2;
|
||||
}
|
||||
|
||||
/*
|
||||
// Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
// This assumes proxyId1 and proxyId2 are 16-bit.
|
||||
SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2)
|
||||
{
|
||||
int key = (proxyId2 << 16) | proxyId1;
|
||||
key = ~key + (key << 15);
|
||||
key = key ^ (key >> 12);
|
||||
key = key + (key << 2);
|
||||
key = key ^ (key >> 4);
|
||||
key = key * 2057;
|
||||
key = key ^ (key >> 16);
|
||||
return key;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
|
||||
{
|
||||
int key = ((unsigned int)proxyId1) | (((unsigned int)proxyId1) <<16);
|
||||
// Thomas Wang's hash
|
||||
|
||||
key += ~(key << 15);
|
||||
key ^= (key >> 10);
|
||||
key += (key << 3);
|
||||
key ^= (key >> 6);
|
||||
key += ~(key << 11);
|
||||
key ^= (key >> 16);
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash)
|
||||
{
|
||||
int proxyId1 = proxy0->getUid();
|
||||
int proxyId2 = proxy1->getUid();
|
||||
if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);
|
||||
|
||||
int index = m_hashTable[hash];
|
||||
|
||||
while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
|
||||
{
|
||||
index = m_next[index];
|
||||
}
|
||||
|
||||
if ( index == BT_NULL_PAIR )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
btAssert(index < m_overlappingPairArray.size());
|
||||
|
||||
return &m_overlappingPairArray[index];
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
btAlignedObjectArray<int> m_hashTable;
|
||||
btAlignedObjectArray<int> m_next;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#else//USE_HASH_PAIRCACHE
|
||||
|
||||
#define USE_LAZY_REMOVAL 1
|
||||
|
||||
///btOverlappingPairCache maintains the objects with overlapping AABB
|
||||
///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
|
||||
class btOverlappingPairCache
|
||||
{
|
||||
protected:
|
||||
//avoid brute-force finding all the time
|
||||
btBroadphasePairArray m_overlappingPairArray;
|
||||
|
||||
//during the dispatch, check that user doesn't destroy/create proxy
|
||||
bool m_blockedForChanges;
|
||||
|
||||
//if set, use the callback instead of the built in filter in needBroadphaseCollision
|
||||
btOverlapFilterCallback* m_overlapFilterCallback;
|
||||
|
||||
public:
|
||||
|
||||
btOverlappingPairCache();
|
||||
virtual ~btOverlappingPairCache();
|
||||
|
||||
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
|
||||
|
||||
void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
|
||||
|
||||
void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
|
||||
|
||||
btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
|
||||
|
||||
btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
|
||||
|
||||
|
||||
void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
|
||||
|
||||
void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
|
||||
|
||||
|
||||
inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
|
||||
{
|
||||
if (m_overlapFilterCallback)
|
||||
return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
|
||||
|
||||
bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
|
||||
collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
|
||||
|
||||
return collides;
|
||||
}
|
||||
|
||||
btBroadphasePairArray& getOverlappingPairArray()
|
||||
{
|
||||
return m_overlappingPairArray;
|
||||
}
|
||||
|
||||
const btBroadphasePairArray& getOverlappingPairArray() const
|
||||
{
|
||||
return m_overlappingPairArray;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
btBroadphasePair* getOverlappingPairArrayPtr()
|
||||
{
|
||||
return &m_overlappingPairArray[0];
|
||||
}
|
||||
|
||||
const btBroadphasePair* getOverlappingPairArrayPtr() const
|
||||
{
|
||||
return &m_overlappingPairArray[0];
|
||||
}
|
||||
|
||||
int getNumOverlappingPairs() const
|
||||
{
|
||||
return m_overlappingPairArray.size();
|
||||
}
|
||||
|
||||
btOverlapFilterCallback* getOverlapFilterCallback()
|
||||
{
|
||||
return m_overlapFilterCallback;
|
||||
}
|
||||
|
||||
void setOverlapFilterCallback(btOverlapFilterCallback* callback)
|
||||
{
|
||||
m_overlapFilterCallback = callback;
|
||||
}
|
||||
|
||||
};
|
||||
#endif //USE_HASH_PAIRCACHE
|
||||
|
||||
#endif //OVERLAPPING_PAIR_CACHE_H
|
||||
|
||||
|
|
@ -0,0 +1,311 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btSimpleBroadphase.h"
|
||||
#include <BulletCollision/BroadphaseCollision/btDispatcher.h>
|
||||
#include <BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h>
|
||||
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "LinearMath/btMatrix3x3.h"
|
||||
#include <new>
|
||||
|
||||
extern int gOverlappingPairs;
|
||||
|
||||
void btSimpleBroadphase::validate()
|
||||
{
|
||||
for (int i=0;i<m_numHandles;i++)
|
||||
{
|
||||
for (int j=i+1;j<m_numHandles;j++)
|
||||
{
|
||||
btAssert(&m_pHandles[i] != &m_pHandles[j]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* overlappingPairCache)
|
||||
:m_pairCache(overlappingPairCache),
|
||||
m_ownsPairCache(false),
|
||||
m_invalidPair(0)
|
||||
{
|
||||
|
||||
if (!overlappingPairCache)
|
||||
{
|
||||
void* mem = btAlignedAlloc(sizeof(btOverlappingPairCache),16);
|
||||
m_pairCache = new (mem)btOverlappingPairCache();
|
||||
m_ownsPairCache = true;
|
||||
}
|
||||
|
||||
// allocate handles buffer and put all handles on free list
|
||||
void* ptr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy)*maxProxies,16);
|
||||
m_pHandles = new(ptr) btSimpleBroadphaseProxy[maxProxies];
|
||||
m_maxHandles = maxProxies;
|
||||
m_numHandles = 0;
|
||||
m_firstFreeHandle = 0;
|
||||
m_firstAllocatedHandle = -1;
|
||||
|
||||
{
|
||||
for (int i = m_firstFreeHandle; i < maxProxies; i++)
|
||||
{
|
||||
m_pHandles[i].SetNextFree(i + 1);
|
||||
m_pHandles[i].m_uniqueId = i+2;//any UID will do, we just avoid too trivial values (0,1) for debugging purposes
|
||||
m_pHandles[i].SetNextAllocated(-1);
|
||||
}
|
||||
m_pHandles[maxProxies - 1].SetNextFree(0);
|
||||
m_pHandles[maxProxies - 1].SetNextAllocated(-1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
btSimpleBroadphase::~btSimpleBroadphase()
|
||||
{
|
||||
btAlignedFree(m_pHandles);
|
||||
|
||||
if (m_ownsPairCache)
|
||||
{
|
||||
btAlignedFree(m_pairCache);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher)
|
||||
{
|
||||
if (m_numHandles >= m_maxHandles)
|
||||
{
|
||||
btAssert(0);
|
||||
return 0; //should never happen, but don't let the game crash ;-)
|
||||
}
|
||||
assert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]);
|
||||
|
||||
int newHandleIndex = allocHandle();
|
||||
btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask);
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
class RemovingOverlapCallback : public btOverlapCallback
|
||||
{
|
||||
protected:
|
||||
virtual bool processOverlap(btBroadphasePair& pair)
|
||||
{
|
||||
(void)pair;
|
||||
btAssert(0);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class RemovePairContainingProxy
|
||||
{
|
||||
|
||||
btBroadphaseProxy* m_targetProxy;
|
||||
public:
|
||||
virtual ~RemovePairContainingProxy()
|
||||
{
|
||||
}
|
||||
protected:
|
||||
virtual bool processOverlap(btBroadphasePair& pair)
|
||||
{
|
||||
btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0);
|
||||
btSimpleBroadphaseProxy* proxy1 = static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1);
|
||||
|
||||
return ((m_targetProxy == proxy0 || m_targetProxy == proxy1));
|
||||
};
|
||||
};
|
||||
|
||||
void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
|
||||
freeHandle(proxy0);
|
||||
|
||||
m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher);
|
||||
|
||||
//validate();
|
||||
|
||||
}
|
||||
|
||||
void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
|
||||
{
|
||||
btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
|
||||
sbp->m_min = aabbMin;
|
||||
sbp->m_max = aabbMax;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1)
|
||||
{
|
||||
return proxy0->m_min[0] <= proxy1->m_max[0] && proxy1->m_min[0] <= proxy0->m_max[0] &&
|
||||
proxy0->m_min[1] <= proxy1->m_max[1] && proxy1->m_min[1] <= proxy0->m_max[1] &&
|
||||
proxy0->m_min[2] <= proxy1->m_max[2] && proxy1->m_min[2] <= proxy0->m_max[2];
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//then remove non-overlapping ones
|
||||
class CheckOverlapCallback : public btOverlapCallback
|
||||
{
|
||||
public:
|
||||
virtual bool processOverlap(btBroadphasePair& pair)
|
||||
{
|
||||
return (!btSimpleBroadphase::aabbOverlap(static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0),static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1)));
|
||||
}
|
||||
};
|
||||
|
||||
void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
|
||||
{
|
||||
//first check for new overlapping pairs
|
||||
int i,j;
|
||||
|
||||
if (m_firstAllocatedHandle >= 0)
|
||||
{
|
||||
|
||||
btSimpleBroadphaseProxy* proxy0 = &m_pHandles[m_firstAllocatedHandle];
|
||||
|
||||
for (i=0;i<m_numHandles;i++)
|
||||
{
|
||||
btSimpleBroadphaseProxy* proxy1 = &m_pHandles[m_firstAllocatedHandle];
|
||||
|
||||
for (j=0;j<m_numHandles;j++)
|
||||
{
|
||||
|
||||
if (proxy0 != proxy1)
|
||||
{
|
||||
btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
|
||||
btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
|
||||
|
||||
if (aabbOverlap(p0,p1))
|
||||
{
|
||||
if ( !m_pairCache->findPair(proxy0,proxy1))
|
||||
{
|
||||
m_pairCache->addOverlappingPair(proxy0,proxy1);
|
||||
}
|
||||
} else
|
||||
{
|
||||
#ifdef USE_HASH_PAIRCACHE
|
||||
if ( m_pairCache->findPair(proxy0,proxy1))
|
||||
{
|
||||
m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher);
|
||||
}
|
||||
#endif //USE_HASH_PAIRCACHE
|
||||
|
||||
}
|
||||
}
|
||||
proxy1 = &m_pHandles[proxy1->GetNextAllocated()];
|
||||
|
||||
}
|
||||
proxy0 = &m_pHandles[proxy0->GetNextAllocated()];
|
||||
|
||||
}
|
||||
|
||||
#ifndef USE_HASH_PAIRCACHE
|
||||
|
||||
if (m_ownsPairCache)
|
||||
{
|
||||
|
||||
btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
|
||||
|
||||
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
|
||||
overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
|
||||
|
||||
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
|
||||
m_invalidPair = 0;
|
||||
|
||||
|
||||
btBroadphasePair previousPair;
|
||||
previousPair.m_pProxy0 = 0;
|
||||
previousPair.m_pProxy1 = 0;
|
||||
previousPair.m_algorithm = 0;
|
||||
|
||||
|
||||
for (i=0;i<overlappingPairArray.size();i++)
|
||||
{
|
||||
|
||||
btBroadphasePair& pair = overlappingPairArray[i];
|
||||
|
||||
bool isDuplicate = (pair == previousPair);
|
||||
|
||||
previousPair = pair;
|
||||
|
||||
bool needsRemoval = false;
|
||||
|
||||
if (!isDuplicate)
|
||||
{
|
||||
bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
|
||||
|
||||
if (hasOverlap)
|
||||
{
|
||||
needsRemoval = false;//callback->processOverlap(pair);
|
||||
} else
|
||||
{
|
||||
needsRemoval = true;
|
||||
}
|
||||
} else
|
||||
{
|
||||
//remove duplicate
|
||||
needsRemoval = true;
|
||||
//should have no algorithm
|
||||
btAssert(!pair.m_algorithm);
|
||||
}
|
||||
|
||||
if (needsRemoval)
|
||||
{
|
||||
m_pairCache->cleanOverlappingPair(pair,dispatcher);
|
||||
|
||||
// m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
|
||||
// m_overlappingPairArray.pop_back();
|
||||
pair.m_pProxy0 = 0;
|
||||
pair.m_pProxy1 = 0;
|
||||
m_invalidPair++;
|
||||
gOverlappingPairs--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///if you don't like to skip the invalid pairs in the array, execute following code:
|
||||
#define CLEAN_INVALID_PAIRS 1
|
||||
#ifdef CLEAN_INVALID_PAIRS
|
||||
|
||||
//perform a sort, to sort 'invalid' pairs to the end
|
||||
overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
|
||||
|
||||
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
|
||||
m_invalidPair = 0;
|
||||
#endif//CLEAN_INVALID_PAIRS
|
||||
|
||||
}
|
||||
#endif //USE_HASH_PAIRCACHE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
|
||||
{
|
||||
btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
|
||||
btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
|
||||
return aabbOverlap(p0,p1);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SIMPLE_BROADPHASE_H
|
||||
#define SIMPLE_BROADPHASE_H
|
||||
|
||||
|
||||
#include "btOverlappingPairCache.h"
|
||||
|
||||
|
||||
struct btSimpleBroadphaseProxy : public btBroadphaseProxy
|
||||
{
|
||||
btVector3 m_min;
|
||||
btVector3 m_max;
|
||||
int m_nextFree;
|
||||
int m_nextAllocated;
|
||||
// int m_handleId;
|
||||
|
||||
|
||||
btSimpleBroadphaseProxy() {};
|
||||
|
||||
btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask)
|
||||
:btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask),
|
||||
m_min(minpt),m_max(maxpt)
|
||||
{
|
||||
(void)shapeType;
|
||||
}
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;}
|
||||
SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;}
|
||||
|
||||
SIMD_FORCE_INLINE void SetNextAllocated(int next) {m_nextAllocated = next;}
|
||||
SIMD_FORCE_INLINE int GetNextAllocated() const {return m_nextAllocated;}
|
||||
|
||||
|
||||
};
|
||||
|
||||
///SimpleBroadphase is a brute force aabb culling broadphase based on O(n^2) aabb checks
|
||||
class btSimpleBroadphase : public btBroadphaseInterface
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
int m_numHandles; // number of active handles
|
||||
int m_maxHandles; // max number of handles
|
||||
btSimpleBroadphaseProxy* m_pHandles; // handles pool
|
||||
int m_firstFreeHandle; // free handles list
|
||||
int m_firstAllocatedHandle;
|
||||
|
||||
int allocHandle()
|
||||
{
|
||||
|
||||
int freeHandle = m_firstFreeHandle;
|
||||
m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree();
|
||||
|
||||
m_pHandles[freeHandle].SetNextAllocated(m_firstAllocatedHandle);
|
||||
m_firstAllocatedHandle = freeHandle;
|
||||
|
||||
m_numHandles++;
|
||||
|
||||
return freeHandle;
|
||||
}
|
||||
|
||||
void freeHandle(btSimpleBroadphaseProxy* proxy)
|
||||
{
|
||||
int handle = int(proxy-m_pHandles);
|
||||
btAssert(handle > 0 && handle < m_maxHandles);
|
||||
|
||||
proxy->SetNextFree(m_firstFreeHandle);
|
||||
m_firstFreeHandle = handle;
|
||||
|
||||
m_firstAllocatedHandle = proxy->GetNextAllocated();
|
||||
proxy->SetNextAllocated(-1);
|
||||
|
||||
m_numHandles--;
|
||||
}
|
||||
|
||||
|
||||
btOverlappingPairCache* m_pairCache;
|
||||
bool m_ownsPairCache;
|
||||
|
||||
int m_invalidPair;
|
||||
|
||||
|
||||
|
||||
inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
|
||||
{
|
||||
btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxy);
|
||||
return proxy0;
|
||||
}
|
||||
|
||||
|
||||
void validate();
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0);
|
||||
virtual ~btSimpleBroadphase();
|
||||
|
||||
|
||||
static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1);
|
||||
|
||||
|
||||
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher);
|
||||
|
||||
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
|
||||
|
||||
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
|
||||
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
|
||||
|
||||
btOverlappingPairCache* getOverlappingPairCache()
|
||||
{
|
||||
return m_pairCache;
|
||||
}
|
||||
const btOverlappingPairCache* getOverlappingPairCache() const
|
||||
{
|
||||
return m_pairCache;
|
||||
}
|
||||
|
||||
bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //SIMPLE_BROADPHASE_H
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "LinearMath/btScalar.h"
|
||||
#include "SphereTriangleDetector.h"
|
||||
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btSphereShape.h"
|
||||
|
||||
|
||||
SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle)
|
||||
:m_sphere(sphere),
|
||||
m_triangle(triangle)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw)
|
||||
{
|
||||
|
||||
(void)debugDraw;
|
||||
const btTransform& transformA = input.m_transformA;
|
||||
const btTransform& transformB = input.m_transformB;
|
||||
|
||||
btVector3 point,normal;
|
||||
btScalar timeOfImpact = btScalar(1.);
|
||||
btScalar depth = btScalar(0.);
|
||||
// output.m_distance = btScalar(1e30);
|
||||
//move sphere into triangle space
|
||||
btTransform sphereInTr = transformB.inverseTimes(transformA);
|
||||
|
||||
if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact))
|
||||
{
|
||||
output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define MAX_OVERLAP btScalar(0.)
|
||||
|
||||
|
||||
|
||||
// See also geometrictools.com
|
||||
// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv
|
||||
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) {
|
||||
btVector3 diff = p - from;
|
||||
btVector3 v = to - from;
|
||||
btScalar t = v.dot(diff);
|
||||
|
||||
if (t > 0) {
|
||||
btScalar dotVV = v.dot(v);
|
||||
if (t < dotVV) {
|
||||
t /= dotVV;
|
||||
diff -= t*v;
|
||||
} else {
|
||||
t = 1;
|
||||
diff -= v;
|
||||
}
|
||||
} else
|
||||
t = 0;
|
||||
|
||||
nearest = from + t*v;
|
||||
return diff.dot(diff);
|
||||
}
|
||||
|
||||
bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal) {
|
||||
btVector3 lp(p);
|
||||
btVector3 lnormal(normal);
|
||||
|
||||
return pointInTriangle(vertices, lnormal, &lp);
|
||||
}
|
||||
|
||||
///combined discrete/continuous sphere-triangle
|
||||
bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact)
|
||||
{
|
||||
|
||||
const btVector3* vertices = &m_triangle->getVertexPtr(0);
|
||||
const btVector3& c = sphereCenter;
|
||||
btScalar r = m_sphere->getRadius();
|
||||
|
||||
btVector3 delta (0,0,0);
|
||||
|
||||
btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
|
||||
normal.normalize();
|
||||
btVector3 p1ToCentre = c - vertices[0];
|
||||
btScalar distanceFromPlane = p1ToCentre.dot(normal);
|
||||
|
||||
if (distanceFromPlane < btScalar(0.))
|
||||
{
|
||||
//triangle facing the other way
|
||||
|
||||
distanceFromPlane *= btScalar(-1.);
|
||||
normal *= btScalar(-1.);
|
||||
}
|
||||
|
||||
///todo: move this gContactBreakingThreshold into a proper structure
|
||||
extern btScalar gContactBreakingThreshold;
|
||||
|
||||
btScalar contactMargin = gContactBreakingThreshold;
|
||||
bool isInsideContactPlane = distanceFromPlane < r + contactMargin;
|
||||
bool isInsideShellPlane = distanceFromPlane < r;
|
||||
|
||||
btScalar deltaDotNormal = delta.dot(normal);
|
||||
if (!isInsideShellPlane && deltaDotNormal >= btScalar(0.0))
|
||||
return false;
|
||||
|
||||
// Check for contact / intersection
|
||||
bool hasContact = false;
|
||||
btVector3 contactPoint;
|
||||
if (isInsideContactPlane) {
|
||||
if (facecontains(c,vertices,normal)) {
|
||||
// Inside the contact wedge - touches a point on the shell plane
|
||||
hasContact = true;
|
||||
contactPoint = c - normal*distanceFromPlane;
|
||||
} else {
|
||||
// Could be inside one of the contact capsules
|
||||
btScalar contactCapsuleRadiusSqr = (r + contactMargin) * (r + contactMargin);
|
||||
btVector3 nearestOnEdge;
|
||||
for (int i = 0; i < m_triangle->getNumEdges(); i++) {
|
||||
|
||||
btPoint3 pa;
|
||||
btPoint3 pb;
|
||||
|
||||
m_triangle->getEdge(i,pa,pb);
|
||||
|
||||
btScalar distanceSqr = SegmentSqrDistance(pa,pb,c, nearestOnEdge);
|
||||
if (distanceSqr < contactCapsuleRadiusSqr) {
|
||||
// Yep, we're inside a capsule
|
||||
hasContact = true;
|
||||
contactPoint = nearestOnEdge;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasContact) {
|
||||
btVector3 contactToCentre = c - contactPoint;
|
||||
btScalar distanceSqr = contactToCentre.length2();
|
||||
if (distanceSqr < (r - MAX_OVERLAP)*(r - MAX_OVERLAP)) {
|
||||
btScalar distance = btSqrt(distanceSqr);
|
||||
resultNormal = contactToCentre;
|
||||
resultNormal.normalize();
|
||||
point = contactPoint;
|
||||
depth = -(r-distance);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (delta.dot(contactToCentre) >= btScalar(0.0))
|
||||
return false;
|
||||
|
||||
// Moving towards the contact point -> collision
|
||||
point = contactPoint;
|
||||
timeOfImpact = btScalar(0.0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p )
|
||||
{
|
||||
const btVector3* p1 = &vertices[0];
|
||||
const btVector3* p2 = &vertices[1];
|
||||
const btVector3* p3 = &vertices[2];
|
||||
|
||||
btVector3 edge1( *p2 - *p1 );
|
||||
btVector3 edge2( *p3 - *p2 );
|
||||
btVector3 edge3( *p1 - *p3 );
|
||||
|
||||
btVector3 p1_to_p( *p - *p1 );
|
||||
btVector3 p2_to_p( *p - *p2 );
|
||||
btVector3 p3_to_p( *p - *p3 );
|
||||
|
||||
btVector3 edge1_normal( edge1.cross(normal));
|
||||
btVector3 edge2_normal( edge2.cross(normal));
|
||||
btVector3 edge3_normal( edge3.cross(normal));
|
||||
|
||||
btScalar r1, r2, r3;
|
||||
r1 = edge1_normal.dot( p1_to_p );
|
||||
r2 = edge2_normal.dot( p2_to_p );
|
||||
r3 = edge3_normal.dot( p3_to_p );
|
||||
if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) ||
|
||||
( r1 <= 0 && r2 <= 0 && r3 <= 0 ) )
|
||||
return true;
|
||||
return false;
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SPHERE_TRIANGLE_DETECTOR_H
|
||||
#define SPHERE_TRIANGLE_DETECTOR_H
|
||||
|
||||
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
|
||||
#include "LinearMath/btPoint3.h"
|
||||
|
||||
|
||||
class btSphereShape;
|
||||
class btTriangleShape;
|
||||
|
||||
|
||||
|
||||
/// sphere-triangle to match the btDiscreteCollisionDetectorInterface
|
||||
struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface
|
||||
{
|
||||
virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw);
|
||||
|
||||
SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle);
|
||||
|
||||
virtual ~SphereTriangleDetector() {};
|
||||
|
||||
private:
|
||||
|
||||
bool collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact);
|
||||
bool pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p );
|
||||
bool facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal);
|
||||
|
||||
btSphereShape* m_sphere;
|
||||
btTriangleShape* m_triangle;
|
||||
|
||||
|
||||
};
|
||||
#endif //SPHERE_TRIANGLE_DETECTOR_H
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef BT_COLLISION_CONFIGURATION
|
||||
#define BT_COLLISION_CONFIGURATION
|
||||
struct btCollisionAlgorithmCreateFunc;
|
||||
|
||||
///btCollisionConfiguration allows to configure Bullet collision detection
|
||||
///stack allocator size, default collision algorithms and persistent manifold pool size
|
||||
///todo: describe the meaning
|
||||
class btCollisionConfiguration
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual ~btCollisionConfiguration()
|
||||
{
|
||||
}
|
||||
|
||||
///pool size for the persistent contact manifold
|
||||
virtual int getPersistentManifoldPoolSize() = 0;
|
||||
|
||||
virtual int getStackAllocatorSize() = 0;
|
||||
|
||||
virtual int getCollisionAlgorithmPoolSize() = 0;
|
||||
|
||||
virtual int getCollisionAlgorithmMaxElementSize() = 0;
|
||||
|
||||
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0;
|
||||
|
||||
};
|
||||
|
||||
#endif //BT_COLLISION_CONFIGURATION
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef COLLISION_CREATE_FUNC
|
||||
#define COLLISION_CREATE_FUNC
|
||||
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray;
|
||||
class btCollisionAlgorithm;
|
||||
class btCollisionObject;
|
||||
|
||||
struct btCollisionAlgorithmConstructionInfo;
|
||||
|
||||
///Used by the btCollisionDispatcher to register and create instances for btCollisionAlgorithm
|
||||
struct btCollisionAlgorithmCreateFunc
|
||||
{
|
||||
bool m_swapped;
|
||||
|
||||
btCollisionAlgorithmCreateFunc()
|
||||
:m_swapped(false)
|
||||
{
|
||||
}
|
||||
virtual ~btCollisionAlgorithmCreateFunc(){};
|
||||
|
||||
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& , btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
|
||||
(void)body0;
|
||||
(void)body1;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
#endif //COLLISION_CREATE_FUNC
|
||||
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "btCollisionDispatcher.h"
|
||||
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||
|
||||
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
|
||||
#include "LinearMath/btPoolAllocator.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
|
||||
|
||||
int gNumManifold = 0;
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration):
|
||||
m_count(0),
|
||||
m_useIslands(true),
|
||||
m_collisionConfiguration(collisionConfiguration)
|
||||
{
|
||||
int i;
|
||||
|
||||
setNearCallback(defaultNearCallback);
|
||||
|
||||
m_collisionAlgorithmPoolAllocator = new btPoolAllocator(m_collisionConfiguration->getCollisionAlgorithmMaxElementSize(),m_collisionConfiguration->getCollisionAlgorithmPoolSize());
|
||||
|
||||
m_persistentManifoldPoolAllocator = new btPoolAllocator(sizeof(btPersistentManifold),m_collisionConfiguration->getPersistentManifoldPoolSize());
|
||||
|
||||
for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
|
||||
{
|
||||
for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
|
||||
{
|
||||
m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
|
||||
assert(m_doubleDispatch[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
|
||||
{
|
||||
m_doubleDispatch[proxyType0][proxyType1] = createFunc;
|
||||
}
|
||||
|
||||
btCollisionDispatcher::~btCollisionDispatcher()
|
||||
{
|
||||
delete m_collisionAlgorithmPoolAllocator;
|
||||
delete m_persistentManifoldPoolAllocator;
|
||||
}
|
||||
|
||||
btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1)
|
||||
{
|
||||
gNumManifold++;
|
||||
|
||||
//btAssert(gNumManifold < 65535);
|
||||
|
||||
|
||||
btCollisionObject* body0 = (btCollisionObject*)b0;
|
||||
btCollisionObject* body1 = (btCollisionObject*)b1;
|
||||
|
||||
void* mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
|
||||
btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0);
|
||||
manifold->m_index1a = m_manifoldsPtr.size();
|
||||
m_manifoldsPtr.push_back(manifold);
|
||||
|
||||
return manifold;
|
||||
}
|
||||
|
||||
void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
|
||||
{
|
||||
manifold->clearManifold();
|
||||
}
|
||||
|
||||
|
||||
void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
|
||||
{
|
||||
|
||||
gNumManifold--;
|
||||
|
||||
//printf("releaseManifold: gNumManifold %d\n",gNumManifold);
|
||||
clearManifold(manifold);
|
||||
|
||||
int findIndex = manifold->m_index1a;
|
||||
btAssert(findIndex < m_manifoldsPtr.size());
|
||||
m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
|
||||
m_manifoldsPtr[findIndex]->m_index1a = findIndex;
|
||||
m_manifoldsPtr.pop_back();
|
||||
|
||||
manifold->~btPersistentManifold();
|
||||
m_persistentManifoldPoolAllocator->free(manifold);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
|
||||
{
|
||||
|
||||
btCollisionAlgorithmConstructionInfo ci;
|
||||
|
||||
ci.m_dispatcher1 = this;
|
||||
ci.m_manifold = sharedManifold;
|
||||
btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1);
|
||||
|
||||
return algo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
//here you can do filtering
|
||||
bool hasResponse =
|
||||
(body0->hasContactResponse() && body1->hasContactResponse());
|
||||
//no response between two static/kinematic bodies:
|
||||
hasResponse = hasResponse &&
|
||||
((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject()));
|
||||
return hasResponse;
|
||||
}
|
||||
|
||||
bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
assert(body0);
|
||||
assert(body1);
|
||||
|
||||
bool needsCollision = true;
|
||||
|
||||
//broadphase filtering already deals with this
|
||||
if ((body0->isStaticObject() || body0->isKinematicObject()) &&
|
||||
(body1->isStaticObject() || body1->isKinematicObject()))
|
||||
{
|
||||
printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
|
||||
}
|
||||
|
||||
if ((!body0->isActive()) && (!body1->isActive()))
|
||||
needsCollision = false;
|
||||
else if (!body0->checkCollideWith(body1))
|
||||
needsCollision = false;
|
||||
|
||||
return needsCollision ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
|
||||
///this is useful for the collision dispatcher.
|
||||
class btCollisionPairCallback : public btOverlapCallback
|
||||
{
|
||||
btDispatcherInfo& m_dispatchInfo;
|
||||
btCollisionDispatcher* m_dispatcher;
|
||||
|
||||
public:
|
||||
|
||||
btCollisionPairCallback(btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
|
||||
:m_dispatchInfo(dispatchInfo),
|
||||
m_dispatcher(dispatcher)
|
||||
{
|
||||
}
|
||||
|
||||
btCollisionPairCallback& operator=(btCollisionPairCallback& other)
|
||||
{
|
||||
m_dispatchInfo = other.m_dispatchInfo;
|
||||
m_dispatcher = other.m_dispatcher;
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ~btCollisionPairCallback() {}
|
||||
|
||||
|
||||
virtual bool processOverlap(btBroadphasePair& pair)
|
||||
{
|
||||
(*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo);
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)
|
||||
{
|
||||
//m_blockedForChanges = true;
|
||||
|
||||
btCollisionPairCallback collisionCallback(dispatchInfo,this);
|
||||
|
||||
pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
|
||||
|
||||
//m_blockedForChanges = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//by default, Bullet will use this near callback
|
||||
void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo)
|
||||
{
|
||||
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
|
||||
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
|
||||
|
||||
if (dispatcher.needsCollision(colObj0,colObj1))
|
||||
{
|
||||
//dispatcher will keep algorithms persistent in the collision pair
|
||||
if (!collisionPair.m_algorithm)
|
||||
{
|
||||
collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1);
|
||||
}
|
||||
|
||||
if (collisionPair.m_algorithm)
|
||||
{
|
||||
btManifoldResult contactPointResult(colObj0,colObj1);
|
||||
|
||||
if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
|
||||
{
|
||||
//discrete collision detection query
|
||||
collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult);
|
||||
} else
|
||||
{
|
||||
//continuous collision detection query, time of impact (toi)
|
||||
btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
|
||||
if (dispatchInfo.m_timeOfImpact > toi)
|
||||
dispatchInfo.m_timeOfImpact = toi;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
|
||||
{
|
||||
return m_collisionAlgorithmPoolAllocator->allocate(size);
|
||||
}
|
||||
|
||||
void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
|
||||
{
|
||||
m_collisionAlgorithmPoolAllocator->free(ptr);
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef COLLISION__DISPATCHER_H
|
||||
#define COLLISION__DISPATCHER_H
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
||||
|
||||
#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
|
||||
class btIDebugDraw;
|
||||
class btOverlappingPairCache;
|
||||
class btPoolAllocator;
|
||||
class btCollisionConfiguration;
|
||||
|
||||
#include "btCollisionCreateFunc.h"
|
||||
|
||||
#define USE_DISPATCH_REGISTRY_ARRAY 1
|
||||
|
||||
class btCollisionDispatcher;
|
||||
///user can override this nearcallback for collision filtering and more finegrained control over collision detection
|
||||
typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo);
|
||||
|
||||
|
||||
///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
|
||||
///Time of Impact, Closest Points and Penetration Depth.
|
||||
class btCollisionDispatcher : public btDispatcher
|
||||
{
|
||||
int m_count;
|
||||
|
||||
btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
|
||||
|
||||
bool m_useIslands;
|
||||
|
||||
btManifoldResult m_defaultManifoldResult;
|
||||
|
||||
btNearCallback m_nearCallback;
|
||||
|
||||
btPoolAllocator* m_collisionAlgorithmPoolAllocator;
|
||||
|
||||
btPoolAllocator* m_persistentManifoldPoolAllocator;
|
||||
|
||||
btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
|
||||
|
||||
|
||||
btCollisionConfiguration* m_collisionConfiguration;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
///registerCollisionCreateFunc allows registration of custom/alternative collision create functions
|
||||
void registerCollisionCreateFunc(int proxyType0,int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
|
||||
|
||||
int getNumManifolds() const
|
||||
{
|
||||
return int( m_manifoldsPtr.size());
|
||||
}
|
||||
|
||||
btPersistentManifold** getInternalManifoldPointer()
|
||||
{
|
||||
return &m_manifoldsPtr[0];
|
||||
}
|
||||
|
||||
btPersistentManifold* getManifoldByIndexInternal(int index)
|
||||
{
|
||||
return m_manifoldsPtr[index];
|
||||
}
|
||||
|
||||
const btPersistentManifold* getManifoldByIndexInternal(int index) const
|
||||
{
|
||||
return m_manifoldsPtr[index];
|
||||
}
|
||||
|
||||
btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration);
|
||||
|
||||
virtual ~btCollisionDispatcher();
|
||||
|
||||
virtual btPersistentManifold* getNewManifold(void* b0,void* b1);
|
||||
|
||||
virtual void releaseManifold(btPersistentManifold* manifold);
|
||||
|
||||
|
||||
virtual void clearManifold(btPersistentManifold* manifold);
|
||||
|
||||
|
||||
btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0);
|
||||
|
||||
virtual bool needsCollision(btCollisionObject* body0,btCollisionObject* body1);
|
||||
|
||||
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1);
|
||||
|
||||
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher);
|
||||
|
||||
void setNearCallback(btNearCallback nearCallback)
|
||||
{
|
||||
m_nearCallback = nearCallback;
|
||||
}
|
||||
|
||||
btNearCallback getNearCallback() const
|
||||
{
|
||||
return m_nearCallback;
|
||||
}
|
||||
|
||||
//by default, Bullet will use this near callback
|
||||
static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo);
|
||||
|
||||
virtual void* allocateCollisionAlgorithm(int size);
|
||||
|
||||
virtual void freeCollisionAlgorithm(void* ptr);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //COLLISION__DISPATCHER_H
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "btCollisionObject.h"
|
||||
|
||||
btCollisionObject::btCollisionObject()
|
||||
: m_broadphaseHandle(0),
|
||||
m_collisionShape(0),
|
||||
m_collisionFlags(0),
|
||||
m_islandTag1(-1),
|
||||
m_companionId(-1),
|
||||
m_activationState1(1),
|
||||
m_deactivationTime(btScalar(0.)),
|
||||
m_userObjectPointer(0),
|
||||
m_internalOwner(0),
|
||||
m_hitFraction(btScalar(1.)),
|
||||
m_ccdSweptSphereRadius(btScalar(0.)),
|
||||
m_ccdSquareMotionThreshold(btScalar(0.)),
|
||||
m_checkCollideWith(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
btCollisionObject::~btCollisionObject()
|
||||
{
|
||||
}
|
||||
|
||||
void btCollisionObject::setActivationState(int newState)
|
||||
{
|
||||
if ( (m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION))
|
||||
m_activationState1 = newState;
|
||||
}
|
||||
|
||||
void btCollisionObject::forceActivationState(int newState)
|
||||
{
|
||||
m_activationState1 = newState;
|
||||
}
|
||||
|
||||
void btCollisionObject::activate(bool forceActivation)
|
||||
{
|
||||
if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT|CF_KINEMATIC_OBJECT)))
|
||||
{
|
||||
setActivationState(ACTIVE_TAG);
|
||||
m_deactivationTime = btScalar(0.);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,349 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef COLLISION_OBJECT_H
|
||||
#define COLLISION_OBJECT_H
|
||||
|
||||
#include "LinearMath/btTransform.h"
|
||||
|
||||
//island management, m_activationState1
|
||||
#define ACTIVE_TAG 1
|
||||
#define ISLAND_SLEEPING 2
|
||||
#define WANTS_DEACTIVATION 3
|
||||
#define DISABLE_DEACTIVATION 4
|
||||
#define DISABLE_SIMULATION 5
|
||||
|
||||
struct btBroadphaseProxy;
|
||||
class btCollisionShape;
|
||||
#include "LinearMath/btMotionState.h"
|
||||
#include "LinearMath/btAlignedAllocator.h"
|
||||
|
||||
|
||||
|
||||
/// btCollisionObject can be used to manage collision detection objects.
|
||||
/// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy.
|
||||
/// They can be added to the btCollisionWorld.
|
||||
ATTRIBUTE_ALIGNED16(class) btCollisionObject
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
btTransform m_worldTransform;
|
||||
|
||||
///m_interpolationWorldTransform is used for CCD and interpolation
|
||||
///it can be either previous or future (predicted) transform
|
||||
btTransform m_interpolationWorldTransform;
|
||||
//those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities)
|
||||
//without destroying the continuous interpolated motion (which uses this interpolation velocities)
|
||||
btVector3 m_interpolationLinearVelocity;
|
||||
btVector3 m_interpolationAngularVelocity;
|
||||
btBroadphaseProxy* m_broadphaseHandle;
|
||||
btCollisionShape* m_collisionShape;
|
||||
|
||||
int m_collisionFlags;
|
||||
|
||||
int m_islandTag1;
|
||||
int m_companionId;
|
||||
|
||||
int m_activationState1;
|
||||
btScalar m_deactivationTime;
|
||||
|
||||
btScalar m_friction;
|
||||
btScalar m_restitution;
|
||||
|
||||
///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer
|
||||
void* m_userObjectPointer;
|
||||
|
||||
///m_internalOwner is reserved to point to Bullet's btRigidBody. Don't use this, use m_userObjectPointer instead.
|
||||
void* m_internalOwner;
|
||||
|
||||
///time of impact calculation
|
||||
btScalar m_hitFraction;
|
||||
|
||||
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
|
||||
btScalar m_ccdSweptSphereRadius;
|
||||
|
||||
/// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold
|
||||
btScalar m_ccdSquareMotionThreshold;
|
||||
|
||||
/// If some object should have elaborate collision filtering by sub-classes
|
||||
bool m_checkCollideWith;
|
||||
|
||||
char m_pad[7];
|
||||
|
||||
virtual bool checkCollideWithOverride(btCollisionObject* co)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
enum CollisionFlags
|
||||
{
|
||||
CF_STATIC_OBJECT= 1,
|
||||
CF_KINEMATIC_OBJECT= 2,
|
||||
CF_NO_CONTACT_RESPONSE = 4,
|
||||
CF_CUSTOM_MATERIAL_CALLBACK = 8//this allows per-triangle material (friction/restitution)
|
||||
};
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE bool mergesSimulationIslands() const
|
||||
{
|
||||
///static objects, kinematic and object without contact response don't merge islands
|
||||
return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0);
|
||||
}
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE bool isStaticObject() const {
|
||||
return (m_collisionFlags & CF_STATIC_OBJECT) != 0;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE bool isKinematicObject() const
|
||||
{
|
||||
return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const
|
||||
{
|
||||
return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE bool hasContactResponse() const {
|
||||
return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0;
|
||||
}
|
||||
|
||||
|
||||
btCollisionObject();
|
||||
|
||||
virtual ~btCollisionObject();
|
||||
|
||||
void setCollisionShape(btCollisionShape* collisionShape)
|
||||
{
|
||||
m_collisionShape = collisionShape;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
|
||||
{
|
||||
return m_collisionShape;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
|
||||
{
|
||||
return m_collisionShape;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int getActivationState() const { return m_activationState1;}
|
||||
|
||||
void setActivationState(int newState);
|
||||
|
||||
void setDeactivationTime(btScalar time)
|
||||
{
|
||||
m_deactivationTime = time;
|
||||
}
|
||||
btScalar getDeactivationTime() const
|
||||
{
|
||||
return m_deactivationTime;
|
||||
}
|
||||
|
||||
void forceActivationState(int newState);
|
||||
|
||||
void activate(bool forceActivation = false);
|
||||
|
||||
inline bool isActive() const
|
||||
{
|
||||
return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION));
|
||||
}
|
||||
|
||||
void setRestitution(btScalar rest)
|
||||
{
|
||||
m_restitution = rest;
|
||||
}
|
||||
btScalar getRestitution() const
|
||||
{
|
||||
return m_restitution;
|
||||
}
|
||||
void setFriction(btScalar frict)
|
||||
{
|
||||
m_friction = frict;
|
||||
}
|
||||
btScalar getFriction() const
|
||||
{
|
||||
return m_friction;
|
||||
}
|
||||
|
||||
///reserved for Bullet internal usage
|
||||
void* getInternalOwner()
|
||||
{
|
||||
return m_internalOwner;
|
||||
}
|
||||
|
||||
const void* getInternalOwner() const
|
||||
{
|
||||
return m_internalOwner;
|
||||
}
|
||||
|
||||
btTransform& getWorldTransform()
|
||||
{
|
||||
return m_worldTransform;
|
||||
}
|
||||
|
||||
const btTransform& getWorldTransform() const
|
||||
{
|
||||
return m_worldTransform;
|
||||
}
|
||||
|
||||
void setWorldTransform(const btTransform& worldTrans)
|
||||
{
|
||||
m_worldTransform = worldTrans;
|
||||
}
|
||||
|
||||
|
||||
btBroadphaseProxy* getBroadphaseHandle()
|
||||
{
|
||||
return m_broadphaseHandle;
|
||||
}
|
||||
|
||||
const btBroadphaseProxy* getBroadphaseHandle() const
|
||||
{
|
||||
return m_broadphaseHandle;
|
||||
}
|
||||
|
||||
void setBroadphaseHandle(btBroadphaseProxy* handle)
|
||||
{
|
||||
m_broadphaseHandle = handle;
|
||||
}
|
||||
|
||||
|
||||
const btTransform& getInterpolationWorldTransform() const
|
||||
{
|
||||
return m_interpolationWorldTransform;
|
||||
}
|
||||
|
||||
btTransform& getInterpolationWorldTransform()
|
||||
{
|
||||
return m_interpolationWorldTransform;
|
||||
}
|
||||
|
||||
void setInterpolationWorldTransform(const btTransform& trans)
|
||||
{
|
||||
m_interpolationWorldTransform = trans;
|
||||
}
|
||||
|
||||
|
||||
const btVector3& getInterpolationLinearVelocity() const
|
||||
{
|
||||
return m_interpolationLinearVelocity;
|
||||
}
|
||||
|
||||
const btVector3& getInterpolationAngularVelocity() const
|
||||
{
|
||||
return m_interpolationAngularVelocity;
|
||||
}
|
||||
|
||||
const int getIslandTag() const
|
||||
{
|
||||
return m_islandTag1;
|
||||
}
|
||||
|
||||
void setIslandTag(int tag)
|
||||
{
|
||||
m_islandTag1 = tag;
|
||||
}
|
||||
|
||||
const int getCompanionId() const
|
||||
{
|
||||
return m_companionId;
|
||||
}
|
||||
|
||||
void setCompanionId(int id)
|
||||
{
|
||||
m_companionId = id;
|
||||
}
|
||||
|
||||
const btScalar getHitFraction() const
|
||||
{
|
||||
return m_hitFraction;
|
||||
}
|
||||
|
||||
void setHitFraction(btScalar hitFraction)
|
||||
{
|
||||
m_hitFraction = hitFraction;
|
||||
}
|
||||
|
||||
|
||||
const int getCollisionFlags() const
|
||||
{
|
||||
return m_collisionFlags;
|
||||
}
|
||||
|
||||
void setCollisionFlags(int flags)
|
||||
{
|
||||
m_collisionFlags = flags;
|
||||
}
|
||||
|
||||
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
|
||||
btScalar getCcdSweptSphereRadius() const
|
||||
{
|
||||
return m_ccdSweptSphereRadius;
|
||||
}
|
||||
|
||||
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
|
||||
void setCcdSweptSphereRadius(btScalar radius)
|
||||
{
|
||||
m_ccdSweptSphereRadius = radius;
|
||||
}
|
||||
|
||||
btScalar getCcdSquareMotionThreshold() const
|
||||
{
|
||||
return m_ccdSquareMotionThreshold;
|
||||
}
|
||||
|
||||
|
||||
/// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold
|
||||
void setCcdSquareMotionThreshold(btScalar ccdSquareMotionThreshold)
|
||||
{
|
||||
m_ccdSquareMotionThreshold = ccdSquareMotionThreshold;
|
||||
}
|
||||
|
||||
///users can point to their objects, userPointer is not used by Bullet
|
||||
void* getUserPointer() const
|
||||
{
|
||||
return m_userObjectPointer;
|
||||
}
|
||||
|
||||
///users can point to their objects, userPointer is not used by Bullet
|
||||
void setUserPointer(void* userPointer)
|
||||
{
|
||||
m_userObjectPointer = userPointer;
|
||||
}
|
||||
|
||||
inline bool checkCollideWith(btCollisionObject* co)
|
||||
{
|
||||
if (m_checkCollideWith)
|
||||
return checkCollideWithOverride(co);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
;
|
||||
|
||||
#endif //COLLISION_OBJECT_H
|
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btCollisionWorld.h"
|
||||
#include "btCollisionDispatcher.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||
|
||||
#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
|
||||
#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" //for raycasting
|
||||
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
|
||||
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
|
||||
#include "LinearMath/btAabbUtil2.h"
|
||||
#include "LinearMath/btQuickprof.h"
|
||||
#include "LinearMath/btStackAlloc.h"
|
||||
|
||||
//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
|
||||
|
||||
|
||||
|
||||
btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, int stackSize)
|
||||
:m_dispatcher1(dispatcher),
|
||||
m_broadphasePairCache(pairCache),
|
||||
m_ownsDispatcher(false),
|
||||
m_ownsBroadphasePairCache(false)
|
||||
{
|
||||
m_stackAlloc = new btStackAlloc(stackSize);
|
||||
m_dispatchInfo.m_stackAllocator = m_stackAlloc;
|
||||
}
|
||||
|
||||
|
||||
btCollisionWorld::~btCollisionWorld()
|
||||
{
|
||||
m_stackAlloc->destroy();
|
||||
delete m_stackAlloc;
|
||||
|
||||
//clean up remaining objects
|
||||
int i;
|
||||
for (i=0;i<m_collisionObjects.size();i++)
|
||||
{
|
||||
btCollisionObject* collisionObject= m_collisionObjects[i];
|
||||
|
||||
btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
|
||||
if (bp)
|
||||
{
|
||||
//
|
||||
// only clear the cached algorithms
|
||||
//
|
||||
getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
|
||||
getBroadphase()->destroyProxy(bp,m_dispatcher1);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ownsDispatcher)
|
||||
delete m_dispatcher1;
|
||||
if (m_ownsBroadphasePairCache)
|
||||
delete m_broadphasePairCache;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask)
|
||||
{
|
||||
|
||||
//check that the object isn't already added
|
||||
btAssert( m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size());
|
||||
|
||||
m_collisionObjects.push_back(collisionObject);
|
||||
|
||||
//calculate new AABB
|
||||
btTransform trans = collisionObject->getWorldTransform();
|
||||
|
||||
btVector3 minAabb;
|
||||
btVector3 maxAabb;
|
||||
collisionObject->getCollisionShape()->getAabb(trans,minAabb,maxAabb);
|
||||
|
||||
int type = collisionObject->getCollisionShape()->getShapeType();
|
||||
collisionObject->setBroadphaseHandle( getBroadphase()->createProxy(
|
||||
minAabb,
|
||||
maxAabb,
|
||||
type,
|
||||
collisionObject,
|
||||
collisionFilterGroup,
|
||||
collisionFilterMask,
|
||||
m_dispatcher1
|
||||
)) ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void btCollisionWorld::performDiscreteCollisionDetection()
|
||||
{
|
||||
btDispatcherInfo& dispatchInfo = getDispatchInfo();
|
||||
|
||||
BEGIN_PROFILE("perform Broadphase Collision Detection");
|
||||
|
||||
|
||||
//update aabb (of all moved objects)
|
||||
|
||||
btVector3 aabbMin,aabbMax;
|
||||
for (int i=0;i<m_collisionObjects.size();i++)
|
||||
{
|
||||
m_collisionObjects[i]->getCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax);
|
||||
m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax,m_dispatcher1);
|
||||
}
|
||||
|
||||
m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
|
||||
|
||||
END_PROFILE("perform Broadphase Collision Detection");
|
||||
|
||||
BEGIN_PROFILE("performDiscreteCollisionDetection");
|
||||
|
||||
btDispatcher* dispatcher = getDispatcher();
|
||||
if (dispatcher)
|
||||
dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
|
||||
|
||||
END_PROFILE("performDiscreteCollisionDetection");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
|
||||
{
|
||||
|
||||
|
||||
//bool removeFromBroadphase = false;
|
||||
|
||||
{
|
||||
|
||||
btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
|
||||
if (bp)
|
||||
{
|
||||
//
|
||||
// only clear the cached algorithms
|
||||
//
|
||||
getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
|
||||
getBroadphase()->destroyProxy(bp,m_dispatcher1);
|
||||
collisionObject->setBroadphaseHandle(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//swapremove
|
||||
m_collisionObjects.remove(collisionObject);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
|
||||
btCollisionObject* collisionObject,
|
||||
const btCollisionShape* collisionShape,
|
||||
const btTransform& colObjWorldTransform,
|
||||
RayResultCallback& resultCallback,short int collisionFilterMask)
|
||||
{
|
||||
|
||||
btSphereShape pointShape(btScalar(0.0));
|
||||
pointShape.setMargin(0.f);
|
||||
|
||||
objectQuerySingle(&pointShape,rayFromTrans,rayToTrans,
|
||||
collisionObject,
|
||||
collisionShape,
|
||||
colObjWorldTransform,
|
||||
resultCallback,collisionFilterMask);
|
||||
}
|
||||
|
||||
void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& rayFromTrans,const btTransform& rayToTrans,
|
||||
btCollisionObject* collisionObject,
|
||||
const btCollisionShape* collisionShape,
|
||||
const btTransform& colObjWorldTransform,
|
||||
RayResultCallback& resultCallback,short int collisionFilterMask)
|
||||
{
|
||||
|
||||
|
||||
if (collisionShape->isConvex())
|
||||
{
|
||||
btConvexCast::CastResult castResult;
|
||||
castResult.m_fraction = btScalar(1.);//??
|
||||
|
||||
btConvexShape* convexShape = (btConvexShape*) collisionShape;
|
||||
btVoronoiSimplexSolver simplexSolver;
|
||||
#define USE_SUBSIMPLEX_CONVEX_CAST 1
|
||||
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
|
||||
btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver);
|
||||
#else
|
||||
//btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver);
|
||||
//btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
|
||||
#endif //#USE_SUBSIMPLEX_CONVEX_CAST
|
||||
|
||||
if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
|
||||
{
|
||||
//add hit
|
||||
if (castResult.m_normal.length2() > btScalar(0.0001))
|
||||
{
|
||||
|
||||
if (castResult.m_fraction < resultCallback.m_closestHitFraction)
|
||||
{
|
||||
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
|
||||
//rotate normal into worldspace
|
||||
castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
|
||||
#endif //USE_SUBSIMPLEX_CONVEX_CAST
|
||||
|
||||
castResult.m_normal.normalize();
|
||||
btCollisionWorld::LocalRayResult localRayResult
|
||||
(
|
||||
collisionObject,
|
||||
0,
|
||||
castResult.m_normal,
|
||||
castResult.m_fraction
|
||||
);
|
||||
|
||||
bool normalInWorldSpace = true;
|
||||
resultCallback.AddSingleResult(localRayResult, normalInWorldSpace);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (collisionShape->isConcave())
|
||||
{
|
||||
|
||||
btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape;
|
||||
|
||||
btTransform worldTocollisionObject = colObjWorldTransform.inverse();
|
||||
|
||||
btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
|
||||
btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
|
||||
|
||||
//ConvexCast::CastResult
|
||||
|
||||
struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
|
||||
{
|
||||
btCollisionWorld::RayResultCallback* m_resultCallback;
|
||||
btCollisionObject* m_collisionObject;
|
||||
btTriangleMeshShape* m_triangleMesh;
|
||||
|
||||
BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
|
||||
btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh):
|
||||
btTriangleRaycastCallback(from,to),
|
||||
m_resultCallback(resultCallback),
|
||||
m_collisionObject(collisionObject),
|
||||
m_triangleMesh(triangleMesh)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
|
||||
{
|
||||
btCollisionWorld::LocalShapeInfo shapeInfo;
|
||||
shapeInfo.m_shapePart = partId;
|
||||
shapeInfo.m_triangleIndex = triangleIndex;
|
||||
|
||||
btCollisionWorld::LocalRayResult rayResult
|
||||
(m_collisionObject,
|
||||
&shapeInfo,
|
||||
hitNormalLocal,
|
||||
hitFraction);
|
||||
|
||||
bool normalInWorldSpace = false;
|
||||
return m_resultCallback->AddSingleResult(rayResult,normalInWorldSpace);
|
||||
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh);
|
||||
rcb.m_hitFraction = resultCallback.m_closestHitFraction;
|
||||
|
||||
btVector3 rayAabbMinLocal = rayFromLocal;
|
||||
rayAabbMinLocal.setMin(rayToLocal);
|
||||
btVector3 rayAabbMaxLocal = rayFromLocal;
|
||||
rayAabbMaxLocal.setMax(rayToLocal);
|
||||
|
||||
triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
|
||||
|
||||
} else
|
||||
{
|
||||
//todo: use AABB tree or other BVH acceleration structure!
|
||||
if (collisionShape->isCompound())
|
||||
{
|
||||
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
|
||||
int i=0;
|
||||
for (i=0;i<compoundShape->getNumChildShapes();i++)
|
||||
{
|
||||
btTransform childTrans = compoundShape->getChildTransform(i);
|
||||
const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
|
||||
btTransform childWorldTrans = colObjWorldTransform * childTrans;
|
||||
objectQuerySingle(castShape, rayFromTrans,rayToTrans,
|
||||
collisionObject,
|
||||
childCollisionShape,
|
||||
childWorldTrans,
|
||||
resultCallback, collisionFilterMask);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask)
|
||||
{
|
||||
|
||||
|
||||
btTransform rayFromTrans,rayToTrans;
|
||||
rayFromTrans.setIdentity();
|
||||
rayFromTrans.setOrigin(rayFromWorld);
|
||||
rayToTrans.setIdentity();
|
||||
|
||||
rayToTrans.setOrigin(rayToWorld);
|
||||
|
||||
/// go over all objects, and if the ray intersects their aabb, do a ray-shape query using convexCaster (CCD)
|
||||
|
||||
int i;
|
||||
for (i=0;i<m_collisionObjects.size();i++)
|
||||
{
|
||||
btCollisionObject* collisionObject= m_collisionObjects[i];
|
||||
//only perform raycast if filterMask matches
|
||||
if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) {
|
||||
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
|
||||
btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
|
||||
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
|
||||
|
||||
btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
|
||||
btVector3 hitNormal;
|
||||
if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
|
||||
{
|
||||
rayTestSingle(rayFromTrans,rayToTrans,
|
||||
collisionObject,
|
||||
collisionObject->getCollisionShape(),
|
||||
collisionObject->getWorldTransform(),
|
||||
resultCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @mainpage Bullet Documentation
|
||||
*
|
||||
* @section intro_sec Introduction
|
||||
* Bullet Collision Detection & Physics SDK
|
||||
*
|
||||
* Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ).
|
||||
*
|
||||
* There is the Physics Forum for Feedback and bteral Collision Detection and Physics discussions.
|
||||
* Please visit http://www.continuousphysics.com/Bullet/phpBB2/index.php
|
||||
*
|
||||
* @section install_sec Installation
|
||||
*
|
||||
* @subsection step1 Step 1: Download
|
||||
* You can download the Bullet Physics Library from our website: http://www.continuousphysics.com/Bullet/
|
||||
* @subsection step2 Step 2: Building
|
||||
* Bullet comes with autogenerated Project Files for Microsoft Visual Studio 6, 7, 7.1 and 8.
|
||||
* The main Workspace/Solution is located in Bullet/msvc/8/wksbullet.sln (replace 8 with your version).
|
||||
*
|
||||
* Under other platforms, like Linux or Mac OS-X, Bullet can be build using either using cmake, http://www.cmake.org, or jam, http://www.perforce.com/jam/jam.html . cmake can autogenerate Xcode, KDevelop, MSVC and other build systems. just run cmake . in the root of Bullet.
|
||||
* Jam is a build system that can build the library, demos and also autogenerate the MSVC Project Files.
|
||||
* So if you are not using MSVC, you can run configure and jam .
|
||||
* If you don't have jam installed, you can make jam from the included jam-2.5 sources, or download jam from ftp://ftp.perforce.com/pub/jam/
|
||||
*
|
||||
* @subsection step3 Step 3: Testing demos
|
||||
* Try to run and experiment with CcdPhysicsDemo executable as a starting point.
|
||||
* Bullet can be used in several ways, as Full Rigid Body simulation, as Collision Detector Library or Low Level / Snippets like the GJK Closest Point calculation.
|
||||
* The Dependencies can be seen in this documentation under Directories
|
||||
*
|
||||
* @subsection step4 Step 4: Integrating in your application, Full Rigid Body Simulation
|
||||
* Check out CcdPhysicsDemo how to create a btDynamicsWorld, btRigidBody and btCollisionShape, Stepping the simulation and synchronizing your graphics object transform.
|
||||
* PLEASE NOTE THE CcdPhysicsEnvironment and CcdPhysicsController is obsolete and will be removed. It has been replaced by classes derived frmo btDynamicsWorld and btRididBody
|
||||
* @subsection step5 Step 5 : Integrate the Collision Detection Library (without Dynamics and other Extras)
|
||||
* Bullet Collision Detection can also be used without the Dynamics/Extras.
|
||||
* Check out btCollisionWorld and btCollisionObject, and the CollisionInterfaceDemo. Also in Extras/test_BulletOde.cpp there is a sample Collision Detection integration with Open Dynamics Engine, ODE, http://www.ode.org
|
||||
* @subsection step6 Step 6 : Use Snippets like the GJK Closest Point calculation.
|
||||
* Bullet has been designed in a modular way keeping dependencies to a minimum. The ConvexHullDistance demo demonstrates direct use of btGjkPairDetector.
|
||||
*
|
||||
* @section copyright Copyright
|
||||
* Copyright (C) 2005-2007 Erwin Coumans, some contributions Copyright Gino van den Bergen, Christer Ericson, Simon Hobbs, Ricardo Padrela, F Richter(res), Stephane Redon
|
||||
* Special thanks to all visitors of the Bullet Physics forum, and in particular above contributors, Dave Eberle, Dirk Gregorius, Erin Catto, Dave Eberle, Adam Moravanszky,
|
||||
* Pierre Terdiman, Kenny Erleben, Russell Smith, Oliver Strunk, Jan Paul van Waveren, Marten Svanfeldt.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef COLLISION_WORLD_H
|
||||
#define COLLISION_WORLD_H
|
||||
|
||||
class btStackAlloc;
|
||||
class btCollisionShape;
|
||||
class btConvexShape;
|
||||
class btBroadphaseInterface;
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "btCollisionObject.h"
|
||||
#include "btCollisionDispatcher.h" //for definition of btCollisionObjectArray
|
||||
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
|
||||
///CollisionWorld is interface and container for the collision detection
|
||||
class btCollisionWorld
|
||||
{
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
btAlignedObjectArray<btCollisionObject*> m_collisionObjects;
|
||||
|
||||
btDispatcher* m_dispatcher1;
|
||||
|
||||
btDispatcherInfo m_dispatchInfo;
|
||||
|
||||
btStackAlloc* m_stackAlloc;
|
||||
|
||||
btBroadphaseInterface* m_broadphasePairCache;
|
||||
|
||||
bool m_ownsDispatcher;
|
||||
bool m_ownsBroadphasePairCache;
|
||||
|
||||
public:
|
||||
|
||||
//this constructor doesn't own the dispatcher and paircache/broadphase
|
||||
btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, int stackSize = 2*1024*1024);
|
||||
|
||||
virtual ~btCollisionWorld();
|
||||
|
||||
|
||||
btBroadphaseInterface* getBroadphase()
|
||||
{
|
||||
return m_broadphasePairCache;
|
||||
}
|
||||
|
||||
btOverlappingPairCache* getPairCache()
|
||||
{
|
||||
return m_broadphasePairCache->getOverlappingPairCache();
|
||||
}
|
||||
|
||||
|
||||
btDispatcher* getDispatcher()
|
||||
{
|
||||
return m_dispatcher1;
|
||||
}
|
||||
|
||||
///LocalShapeInfo gives extra information for complex shapes
|
||||
///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart
|
||||
struct LocalShapeInfo
|
||||
{
|
||||
int m_shapePart;
|
||||
int m_triangleIndex;
|
||||
|
||||
//const btCollisionShape* m_shapeTemp;
|
||||
//const btTransform* m_shapeLocalTransform;
|
||||
};
|
||||
|
||||
struct LocalRayResult
|
||||
{
|
||||
LocalRayResult(btCollisionObject* collisionObject,
|
||||
LocalShapeInfo* localShapeInfo,
|
||||
const btVector3& hitNormalLocal,
|
||||
btScalar hitFraction)
|
||||
:m_collisionObject(collisionObject),
|
||||
m_localShapeInfo(localShapeInfo),
|
||||
m_hitNormalLocal(hitNormalLocal),
|
||||
m_hitFraction(hitFraction)
|
||||
{
|
||||
}
|
||||
|
||||
btCollisionObject* m_collisionObject;
|
||||
LocalShapeInfo* m_localShapeInfo;
|
||||
btVector3 m_hitNormalLocal;
|
||||
btScalar m_hitFraction;
|
||||
|
||||
};
|
||||
|
||||
///RayResultCallback is used to report new raycast results
|
||||
struct RayResultCallback
|
||||
{
|
||||
virtual ~RayResultCallback()
|
||||
{
|
||||
}
|
||||
btScalar m_closestHitFraction;
|
||||
bool HasHit()
|
||||
{
|
||||
return (m_closestHitFraction < btScalar(1.));
|
||||
}
|
||||
|
||||
RayResultCallback()
|
||||
:m_closestHitFraction(btScalar(1.))
|
||||
{
|
||||
}
|
||||
virtual btScalar AddSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0;
|
||||
};
|
||||
|
||||
struct ClosestRayResultCallback : public RayResultCallback
|
||||
{
|
||||
ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld)
|
||||
:m_rayFromWorld(rayFromWorld),
|
||||
m_rayToWorld(rayToWorld),
|
||||
m_collisionObject(0)
|
||||
{
|
||||
}
|
||||
|
||||
btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction
|
||||
btVector3 m_rayToWorld;
|
||||
|
||||
btVector3 m_hitNormalWorld;
|
||||
btVector3 m_hitPointWorld;
|
||||
btCollisionObject* m_collisionObject;
|
||||
|
||||
virtual btScalar AddSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
|
||||
{
|
||||
|
||||
//caller already does the filter on the m_closestHitFraction
|
||||
assert(rayResult.m_hitFraction <= m_closestHitFraction);
|
||||
|
||||
m_closestHitFraction = rayResult.m_hitFraction;
|
||||
m_collisionObject = rayResult.m_collisionObject;
|
||||
if (normalInWorldSpace)
|
||||
{
|
||||
m_hitNormalWorld = rayResult.m_hitNormalLocal;
|
||||
} else
|
||||
{
|
||||
///need to transform normal into worldspace
|
||||
m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
|
||||
}
|
||||
m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction);
|
||||
return rayResult.m_hitFraction;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
int getNumCollisionObjects() const
|
||||
{
|
||||
return int(m_collisionObjects.size());
|
||||
}
|
||||
|
||||
/// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback
|
||||
/// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
|
||||
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1);
|
||||
|
||||
/// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
|
||||
/// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
|
||||
/// This allows more customization.
|
||||
static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
|
||||
btCollisionObject* collisionObject,
|
||||
const btCollisionShape* collisionShape,
|
||||
const btTransform& colObjWorldTransform,
|
||||
RayResultCallback& resultCallback, short int collisionFilterMask=-1);
|
||||
|
||||
/// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest.
|
||||
static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans,
|
||||
btCollisionObject* collisionObject,
|
||||
const btCollisionShape* collisionShape,
|
||||
const btTransform& colObjWorldTransform,
|
||||
RayResultCallback& resultCallback, short int collisionFilterMask=-1);
|
||||
|
||||
void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1);
|
||||
|
||||
btCollisionObjectArray& getCollisionObjectArray()
|
||||
{
|
||||
return m_collisionObjects;
|
||||
}
|
||||
|
||||
const btCollisionObjectArray& getCollisionObjectArray() const
|
||||
{
|
||||
return m_collisionObjects;
|
||||
}
|
||||
|
||||
|
||||
void removeCollisionObject(btCollisionObject* collisionObject);
|
||||
|
||||
virtual void performDiscreteCollisionDetection();
|
||||
|
||||
btDispatcherInfo& getDispatchInfo()
|
||||
{
|
||||
return m_dispatchInfo;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //COLLISION_WORLD_H
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
|
||||
|
||||
|
||||
btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
|
||||
:btCollisionAlgorithm(ci),
|
||||
m_isSwapped(isSwapped)
|
||||
{
|
||||
btCollisionObject* colObj = m_isSwapped? body1 : body0;
|
||||
btCollisionObject* otherObj = m_isSwapped? body0 : body1;
|
||||
assert (colObj->getCollisionShape()->isCompound());
|
||||
|
||||
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
|
||||
int numChildren = compoundShape->getNumChildShapes();
|
||||
int i;
|
||||
|
||||
m_childCollisionAlgorithms.resize(numChildren);
|
||||
for (i=0;i<numChildren;i++)
|
||||
{
|
||||
btCollisionShape* childShape = compoundShape->getChildShape(i);
|
||||
btCollisionShape* orgShape = colObj->getCollisionShape();
|
||||
colObj->setCollisionShape( childShape );
|
||||
m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj);
|
||||
colObj->setCollisionShape( orgShape );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
|
||||
{
|
||||
int numChildren = m_childCollisionAlgorithms.size();
|
||||
int i;
|
||||
for (i=0;i<numChildren;i++)
|
||||
{
|
||||
m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
|
||||
m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
btCollisionObject* colObj = m_isSwapped? body1 : body0;
|
||||
btCollisionObject* otherObj = m_isSwapped? body0 : body1;
|
||||
|
||||
assert (colObj->getCollisionShape()->isCompound());
|
||||
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
|
||||
|
||||
//We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
|
||||
//If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals
|
||||
//given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means:
|
||||
//determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1
|
||||
//then use each overlapping node AABB against Tree0
|
||||
//and vise versa.
|
||||
|
||||
int numChildren = m_childCollisionAlgorithms.size();
|
||||
int i;
|
||||
for (i=0;i<numChildren;i++)
|
||||
{
|
||||
//temporarily exchange parent btCollisionShape with childShape, and recurse
|
||||
btCollisionShape* childShape = compoundShape->getChildShape(i);
|
||||
|
||||
//backup
|
||||
btTransform orgTrans = colObj->getWorldTransform();
|
||||
btCollisionShape* orgShape = colObj->getCollisionShape();
|
||||
|
||||
const btTransform& childTrans = compoundShape->getChildTransform(i);
|
||||
//btTransform newChildWorldTrans = orgTrans*childTrans ;
|
||||
colObj->setWorldTransform( orgTrans*childTrans );
|
||||
//the contactpoint is still projected back using the original inverted worldtrans
|
||||
colObj->setCollisionShape( childShape );
|
||||
m_childCollisionAlgorithms[i]->processCollision(colObj,otherObj,dispatchInfo,resultOut);
|
||||
//revert back
|
||||
colObj->setCollisionShape( orgShape);
|
||||
colObj->setWorldTransform( orgTrans );
|
||||
}
|
||||
}
|
||||
|
||||
btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
|
||||
btCollisionObject* colObj = m_isSwapped? body1 : body0;
|
||||
btCollisionObject* otherObj = m_isSwapped? body0 : body1;
|
||||
|
||||
assert (colObj->getCollisionShape()->isCompound());
|
||||
|
||||
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
|
||||
|
||||
//We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
|
||||
//If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals
|
||||
//given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means:
|
||||
//determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1
|
||||
//then use each overlapping node AABB against Tree0
|
||||
//and vise versa.
|
||||
|
||||
btScalar hitFraction = btScalar(1.);
|
||||
|
||||
int numChildren = m_childCollisionAlgorithms.size();
|
||||
int i;
|
||||
for (i=0;i<numChildren;i++)
|
||||
{
|
||||
//temporarily exchange parent btCollisionShape with childShape, and recurse
|
||||
btCollisionShape* childShape = compoundShape->getChildShape(i);
|
||||
|
||||
//backup
|
||||
btTransform orgTrans = colObj->getWorldTransform();
|
||||
btCollisionShape* orgShape = colObj->getCollisionShape();
|
||||
|
||||
const btTransform& childTrans = compoundShape->getChildTransform(i);
|
||||
//btTransform newChildWorldTrans = orgTrans*childTrans ;
|
||||
colObj->setWorldTransform( orgTrans*childTrans );
|
||||
|
||||
colObj->setCollisionShape( childShape );
|
||||
btScalar frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
|
||||
if (frac<hitFraction)
|
||||
{
|
||||
hitFraction = frac;
|
||||
}
|
||||
//revert back
|
||||
colObj->setCollisionShape( orgShape);
|
||||
colObj->setWorldTransform( orgTrans);
|
||||
}
|
||||
return hitFraction;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef COMPOUND_COLLISION_ALGORITHM_H
|
||||
#define COMPOUND_COLLISION_ALGORITHM_H
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
|
||||
|
||||
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
||||
class btDispatcher;
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
#include "btCollisionCreateFunc.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
class btDispatcher;
|
||||
|
||||
/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
|
||||
/// Place holder, not fully implemented yet
|
||||
class btCompoundCollisionAlgorithm : public btCollisionAlgorithm
|
||||
{
|
||||
btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithms;
|
||||
bool m_isSwapped;
|
||||
|
||||
public:
|
||||
|
||||
btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
|
||||
|
||||
virtual ~btCompoundCollisionAlgorithm();
|
||||
|
||||
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
struct CreateFunc :public btCollisionAlgorithmCreateFunc
|
||||
{
|
||||
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
|
||||
return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,false);
|
||||
}
|
||||
};
|
||||
|
||||
struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
|
||||
{
|
||||
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
|
||||
return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,true);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif //COMPOUND_COLLISION_ALGORITHM_H
|
|
@ -0,0 +1,314 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "btConvexConcaveCollisionAlgorithm.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
#include "BulletCollision/CollisionShapes/btConcaveShape.h"
|
||||
#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
|
||||
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btSphereShape.h"
|
||||
#include "LinearMath/btIDebugDraw.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
|
||||
|
||||
btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
|
||||
: btCollisionAlgorithm(ci),
|
||||
m_isSwapped(isSwapped),
|
||||
m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped)
|
||||
{
|
||||
}
|
||||
|
||||
btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped):
|
||||
m_dispatcher(dispatcher),
|
||||
m_dispatchInfoPtr(0)
|
||||
{
|
||||
m_convexBody = isSwapped? body1:body0;
|
||||
m_triBody = isSwapped? body0:body1;
|
||||
|
||||
//
|
||||
// create the manifold from the dispatcher 'manifold pool'
|
||||
//
|
||||
m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody);
|
||||
|
||||
clearCache();
|
||||
}
|
||||
|
||||
btConvexTriangleCallback::~btConvexTriangleCallback()
|
||||
{
|
||||
clearCache();
|
||||
m_dispatcher->releaseManifold( m_manifoldPtr );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void btConvexTriangleCallback::clearCache()
|
||||
{
|
||||
m_dispatcher->clearManifold(m_manifoldPtr);
|
||||
};
|
||||
|
||||
|
||||
|
||||
void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
|
||||
{
|
||||
|
||||
//just for debugging purposes
|
||||
//printf("triangle %d",m_triangleCount++);
|
||||
|
||||
|
||||
//aabb filter is already applied!
|
||||
|
||||
btCollisionAlgorithmConstructionInfo ci;
|
||||
ci.m_dispatcher1 = m_dispatcher;
|
||||
|
||||
btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody);
|
||||
|
||||
|
||||
|
||||
///debug drawing of the overlapping triangles
|
||||
if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && m_dispatchInfoPtr->m_debugDraw->getDebugMode() > 0)
|
||||
{
|
||||
btVector3 color(255,255,0);
|
||||
btTransform& tr = ob->getWorldTransform();
|
||||
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
|
||||
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
|
||||
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
|
||||
|
||||
//btVector3 center = triangle[0] + triangle[1]+triangle[2];
|
||||
//center *= btScalar(0.333333);
|
||||
//m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(center),color);
|
||||
//m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(center),color);
|
||||
//m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(center),color);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject);
|
||||
|
||||
if (m_convexBody->getCollisionShape()->isConvex())
|
||||
{
|
||||
btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
|
||||
tm.setMargin(m_collisionMarginTriangle);
|
||||
|
||||
|
||||
btCollisionShape* tmpShape = ob->getCollisionShape();
|
||||
ob->setCollisionShape( &tm );
|
||||
|
||||
|
||||
btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr);
|
||||
///this should use the btDispatcher, so the actual registered algorithm is used
|
||||
// btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody);
|
||||
|
||||
m_resultOut->setShapeIdentifiers(-1,-1,partId,triangleIndex);
|
||||
// cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex);
|
||||
// cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
|
||||
colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
|
||||
colAlgo->~btCollisionAlgorithm();
|
||||
ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
|
||||
ob->setCollisionShape( tmpShape );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
m_dispatchInfoPtr = &dispatchInfo;
|
||||
m_collisionMarginTriangle = collisionMarginTriangle;
|
||||
m_resultOut = resultOut;
|
||||
|
||||
//recalc aabbs
|
||||
btTransform convexInTriangleSpace;
|
||||
convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_convexBody->getWorldTransform();
|
||||
btCollisionShape* convexShape = static_cast<btCollisionShape*>(m_convexBody->getCollisionShape());
|
||||
//CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
|
||||
convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax);
|
||||
btScalar extraMargin = collisionMarginTriangle;
|
||||
btVector3 extra(extraMargin,extraMargin,extraMargin);
|
||||
|
||||
m_aabbMax += extra;
|
||||
m_aabbMin -= extra;
|
||||
|
||||
}
|
||||
|
||||
void btConvexConcaveCollisionAlgorithm::clearCache()
|
||||
{
|
||||
m_btConvexTriangleCallback.clearCache();
|
||||
|
||||
}
|
||||
|
||||
void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
|
||||
|
||||
btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
|
||||
btCollisionObject* triBody = m_isSwapped ? body0 : body1;
|
||||
|
||||
if (triBody->getCollisionShape()->isConcave())
|
||||
{
|
||||
|
||||
|
||||
btCollisionObject* triOb = triBody;
|
||||
btConcaveShape* concaveShape = static_cast<btConcaveShape*>( triOb->getCollisionShape());
|
||||
|
||||
if (convexBody->getCollisionShape()->isConvex())
|
||||
{
|
||||
btScalar collisionMarginTriangle = concaveShape->getMargin();
|
||||
|
||||
resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
|
||||
m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut);
|
||||
|
||||
//Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here.
|
||||
//m_dispatcher->clearManifold(m_btConvexTriangleCallback.m_manifoldPtr);
|
||||
|
||||
m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody);
|
||||
|
||||
concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax());
|
||||
|
||||
resultOut->refreshContactPoints();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
(void)resultOut;
|
||||
(void)dispatchInfo;
|
||||
btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
|
||||
btCollisionObject* triBody = m_isSwapped ? body0 : body1;
|
||||
|
||||
|
||||
//quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
|
||||
|
||||
//only perform CCD above a certain threshold, this prevents blocking on the long run
|
||||
//because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
|
||||
btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
|
||||
if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
|
||||
{
|
||||
return btScalar(1.);
|
||||
}
|
||||
|
||||
//const btVector3& from = convexbody->m_worldTransform.getOrigin();
|
||||
//btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
|
||||
//todo: only do if the motion exceeds the 'radius'
|
||||
|
||||
btTransform triInv = triBody->getWorldTransform().inverse();
|
||||
btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
|
||||
btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
|
||||
|
||||
struct LocalTriangleSphereCastCallback : public btTriangleCallback
|
||||
{
|
||||
btTransform m_ccdSphereFromTrans;
|
||||
btTransform m_ccdSphereToTrans;
|
||||
btTransform m_meshTransform;
|
||||
|
||||
btScalar m_ccdSphereRadius;
|
||||
btScalar m_hitFraction;
|
||||
|
||||
|
||||
LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
|
||||
:m_ccdSphereFromTrans(from),
|
||||
m_ccdSphereToTrans(to),
|
||||
m_ccdSphereRadius(ccdSphereRadius),
|
||||
m_hitFraction(hitFraction)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
|
||||
{
|
||||
(void)partId;
|
||||
(void)triangleIndex;
|
||||
//do a swept sphere for now
|
||||
btTransform ident;
|
||||
ident.setIdentity();
|
||||
btConvexCast::CastResult castResult;
|
||||
castResult.m_fraction = m_hitFraction;
|
||||
btSphereShape pointShape(m_ccdSphereRadius);
|
||||
btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
|
||||
btVoronoiSimplexSolver simplexSolver;
|
||||
btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
|
||||
//GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
|
||||
//ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
|
||||
//local space?
|
||||
|
||||
if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
|
||||
ident,ident,castResult))
|
||||
{
|
||||
if (m_hitFraction > castResult.m_fraction)
|
||||
m_hitFraction = castResult.m_fraction;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (triBody->getCollisionShape()->isConcave())
|
||||
{
|
||||
btVector3 rayAabbMin = convexFromLocal.getOrigin();
|
||||
rayAabbMin.setMin(convexToLocal.getOrigin());
|
||||
btVector3 rayAabbMax = convexFromLocal.getOrigin();
|
||||
rayAabbMax.setMax(convexToLocal.getOrigin());
|
||||
btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
|
||||
rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
|
||||
rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
|
||||
|
||||
btScalar curHitFraction = btScalar(1.); //is this available?
|
||||
LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
|
||||
convexbody->getCcdSweptSphereRadius(),curHitFraction);
|
||||
|
||||
raycastCallback.m_hitFraction = convexbody->getHitFraction();
|
||||
|
||||
btCollisionObject* concavebody = triBody;
|
||||
|
||||
btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
|
||||
|
||||
if (triangleMesh)
|
||||
{
|
||||
triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
|
||||
{
|
||||
convexbody->setHitFraction( raycastCallback.m_hitFraction);
|
||||
return raycastCallback.m_hitFraction;
|
||||
}
|
||||
}
|
||||
|
||||
return btScalar(1.);
|
||||
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H
|
||||
#define CONVEX_CONCAVE_COLLISION_ALGORITHM_H
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
|
||||
#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
||||
class btDispatcher;
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
#include "btCollisionCreateFunc.h"
|
||||
|
||||
///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called.
|
||||
class btConvexTriangleCallback : public btTriangleCallback
|
||||
{
|
||||
btCollisionObject* m_convexBody;
|
||||
btCollisionObject* m_triBody;
|
||||
|
||||
btVector3 m_aabbMin;
|
||||
btVector3 m_aabbMax ;
|
||||
|
||||
btManifoldResult* m_resultOut;
|
||||
|
||||
btDispatcher* m_dispatcher;
|
||||
const btDispatcherInfo* m_dispatchInfoPtr;
|
||||
btScalar m_collisionMarginTriangle;
|
||||
|
||||
public:
|
||||
int m_triangleCount;
|
||||
|
||||
btPersistentManifold* m_manifoldPtr;
|
||||
|
||||
btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
|
||||
|
||||
void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
virtual ~btConvexTriangleCallback();
|
||||
|
||||
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
|
||||
|
||||
void clearCache();
|
||||
|
||||
SIMD_FORCE_INLINE const btVector3& getAabbMin() const
|
||||
{
|
||||
return m_aabbMin;
|
||||
}
|
||||
SIMD_FORCE_INLINE const btVector3& getAabbMax() const
|
||||
{
|
||||
return m_aabbMax;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// btConvexConcaveCollisionAlgorithm supports collision between convex shapes and (concave) trianges meshes.
|
||||
class btConvexConcaveCollisionAlgorithm : public btCollisionAlgorithm
|
||||
{
|
||||
|
||||
bool m_isSwapped;
|
||||
|
||||
btConvexTriangleCallback m_btConvexTriangleCallback;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
|
||||
|
||||
virtual ~btConvexConcaveCollisionAlgorithm();
|
||||
|
||||
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
void clearCache();
|
||||
|
||||
struct CreateFunc :public btCollisionAlgorithmCreateFunc
|
||||
{
|
||||
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
|
||||
return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,false);
|
||||
}
|
||||
};
|
||||
|
||||
struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
|
||||
{
|
||||
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
|
||||
return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,true);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif //CONVEX_CONCAVE_COLLISION_ALGORITHM_H
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btConvexConvexAlgorithm.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||
#include "BulletCollision/CollisionShapes/btBoxShape.h"
|
||||
#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
|
||||
|
||||
#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
|
||||
|
||||
|
||||
|
||||
#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
|
||||
#include "BulletCollision/CollisionShapes/btSphereShape.h"
|
||||
|
||||
#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
|
||||
|
||||
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
btConvexConvexAlgorithm::CreateFunc::CreateFunc()
|
||||
{
|
||||
m_ownsSolvers = true;
|
||||
m_simplexSolver = new btVoronoiSimplexSolver();
|
||||
m_pdSolver = new btGjkEpaPenetrationDepthSolver;
|
||||
}
|
||||
|
||||
btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
|
||||
{
|
||||
m_ownsSolvers = false;
|
||||
m_simplexSolver = simplexSolver;
|
||||
m_pdSolver = pdSolver;
|
||||
}
|
||||
|
||||
btConvexConvexAlgorithm::CreateFunc::~CreateFunc()
|
||||
{
|
||||
if (m_ownsSolvers){
|
||||
delete m_simplexSolver;
|
||||
delete m_pdSolver;
|
||||
}
|
||||
}
|
||||
|
||||
btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
|
||||
: btCollisionAlgorithm(ci),
|
||||
m_gjkPairDetector(0,0,simplexSolver,pdSolver),
|
||||
m_ownManifold (false),
|
||||
m_manifoldPtr(mf),
|
||||
m_lowLevelOfDetail(false)
|
||||
{
|
||||
(void)body0;
|
||||
(void)body1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
btConvexConvexAlgorithm::~btConvexConvexAlgorithm()
|
||||
{
|
||||
if (m_ownManifold)
|
||||
{
|
||||
if (m_manifoldPtr)
|
||||
m_dispatcher->releaseManifold(m_manifoldPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
|
||||
{
|
||||
m_lowLevelOfDetail = useLowLevel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Convex-Convex collision algorithm
|
||||
//
|
||||
void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
|
||||
if (!m_manifoldPtr)
|
||||
{
|
||||
//swapped?
|
||||
m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
|
||||
m_ownManifold = true;
|
||||
}
|
||||
resultOut->setPersistentManifold(m_manifoldPtr);
|
||||
|
||||
#ifdef USE_BT_GJKEPA
|
||||
btConvexShape* shape0(static_cast<btConvexShape*>(body0->getCollisionShape()));
|
||||
btConvexShape* shape1(static_cast<btConvexShape*>(body1->getCollisionShape()));
|
||||
const btScalar radialmargin(0/*shape0->getMargin()+shape1->getMargin()*/);
|
||||
btGjkEpaSolver::sResults results;
|
||||
if(btGjkEpaSolver::Collide( shape0,body0->getWorldTransform(),
|
||||
shape1,body1->getWorldTransform(),
|
||||
radialmargin,results))
|
||||
{
|
||||
dispatchInfo.m_debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
|
||||
resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
|
||||
}
|
||||
#else
|
||||
|
||||
btConvexShape* min0 = static_cast<btConvexShape*>(body0->getCollisionShape());
|
||||
btConvexShape* min1 = static_cast<btConvexShape*>(body1->getCollisionShape());
|
||||
|
||||
btGjkPairDetector::ClosestPointInput input;
|
||||
|
||||
//TODO: if (dispatchInfo.m_useContinuous)
|
||||
m_gjkPairDetector.setMinkowskiA(min0);
|
||||
m_gjkPairDetector.setMinkowskiB(min1);
|
||||
input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold();
|
||||
input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
|
||||
input.m_stackAlloc = dispatchInfo.m_stackAllocator;
|
||||
|
||||
// input.m_maximumDistanceSquared = btScalar(1e30);
|
||||
|
||||
input.m_transformA = body0->getWorldTransform();
|
||||
input.m_transformB = body1->getWorldTransform();
|
||||
|
||||
m_gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
|
||||
#endif
|
||||
|
||||
if (m_ownManifold)
|
||||
{
|
||||
resultOut->refreshContactPoints();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool disableCcd = false;
|
||||
btScalar btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
(void)resultOut;
|
||||
(void)dispatchInfo;
|
||||
///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold
|
||||
|
||||
///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold
|
||||
///col0->m_worldTransform,
|
||||
btScalar resultFraction = btScalar(1.);
|
||||
|
||||
|
||||
btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
|
||||
btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
|
||||
|
||||
if (squareMot0 < col0->getCcdSquareMotionThreshold() &&
|
||||
squareMot1 < col1->getCcdSquareMotionThreshold())
|
||||
return resultFraction;
|
||||
|
||||
if (disableCcd)
|
||||
return btScalar(1.);
|
||||
|
||||
|
||||
//An adhoc way of testing the Continuous Collision Detection algorithms
|
||||
//One object is approximated as a sphere, to simplify things
|
||||
//Starting in penetration should report no time of impact
|
||||
//For proper CCD, better accuracy and handling of 'allowed' penetration should be added
|
||||
//also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
|
||||
|
||||
|
||||
/// Convex0 against sphere for Convex1
|
||||
{
|
||||
btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
|
||||
|
||||
btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
|
||||
btConvexCast::CastResult result;
|
||||
btVoronoiSimplexSolver voronoiSimplex;
|
||||
//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
|
||||
///Simplification, one object is simplified as a sphere
|
||||
btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex);
|
||||
//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
|
||||
if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
|
||||
col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
|
||||
{
|
||||
|
||||
//store result.m_fraction in both bodies
|
||||
|
||||
if (col0->getHitFraction()> result.m_fraction)
|
||||
col0->setHitFraction( result.m_fraction );
|
||||
|
||||
if (col1->getHitFraction() > result.m_fraction)
|
||||
col1->setHitFraction( result.m_fraction);
|
||||
|
||||
if (resultFraction > result.m_fraction)
|
||||
resultFraction = result.m_fraction;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// Sphere (for convex0) against Convex1
|
||||
{
|
||||
btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
|
||||
|
||||
btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
|
||||
btConvexCast::CastResult result;
|
||||
btVoronoiSimplexSolver voronoiSimplex;
|
||||
//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
|
||||
///Simplification, one object is simplified as a sphere
|
||||
btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex);
|
||||
//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
|
||||
if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
|
||||
col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
|
||||
{
|
||||
|
||||
//store result.m_fraction in both bodies
|
||||
|
||||
if (col0->getHitFraction() > result.m_fraction)
|
||||
col0->setHitFraction( result.m_fraction);
|
||||
|
||||
if (col1->getHitFraction() > result.m_fraction)
|
||||
col1->setHitFraction( result.m_fraction);
|
||||
|
||||
if (resultFraction > result.m_fraction)
|
||||
resultFraction = result.m_fraction;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return resultFraction;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef CONVEX_CONVEX_ALGORITHM_H
|
||||
#define CONVEX_CONVEX_ALGORITHM_H
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
|
||||
#include "btCollisionCreateFunc.h"
|
||||
#include "btCollisionDispatcher.h"
|
||||
|
||||
class btConvexPenetrationDepthSolver;
|
||||
|
||||
///ConvexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations.
|
||||
class btConvexConvexAlgorithm : public btCollisionAlgorithm
|
||||
{
|
||||
btGjkPairDetector m_gjkPairDetector;
|
||||
public:
|
||||
|
||||
bool m_ownManifold;
|
||||
btPersistentManifold* m_manifoldPtr;
|
||||
bool m_lowLevelOfDetail;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
|
||||
|
||||
virtual ~btConvexConvexAlgorithm();
|
||||
|
||||
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
void setLowLevelOfDetail(bool useLowLevel);
|
||||
|
||||
|
||||
const btPersistentManifold* getManifold()
|
||||
{
|
||||
return m_manifoldPtr;
|
||||
}
|
||||
|
||||
struct CreateFunc :public btCollisionAlgorithmCreateFunc
|
||||
{
|
||||
btConvexPenetrationDepthSolver* m_pdSolver;
|
||||
btSimplexSolverInterface* m_simplexSolver;
|
||||
bool m_ownsSolvers;
|
||||
|
||||
CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
|
||||
CreateFunc();
|
||||
virtual ~CreateFunc();
|
||||
|
||||
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm));
|
||||
return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //CONVEX_CONVEX_ALGORITHM_H
|
|
@ -0,0 +1,165 @@
|
|||
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btDefaultCollisionConfiguration.h"
|
||||
|
||||
#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
|
||||
#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
|
||||
#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
|
||||
#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
|
||||
#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
|
||||
#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
|
||||
|
||||
#define DEFAULT_MAX_OVERLAPPING_PAIRS 65535
|
||||
#define DEFAULT_STACK_ALLOCATOR_SIZE (5*1024*1024)
|
||||
|
||||
|
||||
btDefaultCollisionConfiguration::btDefaultCollisionConfiguration()
|
||||
:m_persistentManifoldPoolSize(DEFAULT_MAX_OVERLAPPING_PAIRS),
|
||||
m_stackAllocatorSize(DEFAULT_STACK_ALLOCATOR_SIZE),
|
||||
m_collisionAlgorithmPoolSize(DEFAULT_MAX_OVERLAPPING_PAIRS),
|
||||
m_collisionAlgorithmMaxElementSize(0)
|
||||
{
|
||||
|
||||
//default CreationFunctions, filling the m_doubleDispatch table
|
||||
m_convexConvexCreateFunc = new btConvexConvexAlgorithm::CreateFunc;
|
||||
m_convexConcaveCreateFunc = new btConvexConcaveCollisionAlgorithm::CreateFunc;
|
||||
m_swappedConvexConcaveCreateFunc = new btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
|
||||
m_compoundCreateFunc = new btCompoundCollisionAlgorithm::CreateFunc;
|
||||
m_swappedCompoundCreateFunc = new btCompoundCollisionAlgorithm::SwappedCreateFunc;
|
||||
m_emptyCreateFunc = new btEmptyAlgorithm::CreateFunc;
|
||||
m_sphereSphereCF = new btSphereSphereCollisionAlgorithm::CreateFunc;
|
||||
m_sphereBoxCF = new btSphereBoxCollisionAlgorithm::CreateFunc;
|
||||
m_boxSphereCF = new btSphereBoxCollisionAlgorithm::CreateFunc;
|
||||
m_boxSphereCF->m_swapped = true;
|
||||
|
||||
m_sphereTriangleCF = new btSphereTriangleCollisionAlgorithm::CreateFunc;
|
||||
m_triangleSphereCF = new btSphereTriangleCollisionAlgorithm::CreateFunc;
|
||||
m_triangleSphereCF->m_swapped = true;
|
||||
|
||||
|
||||
///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
|
||||
int maxSize = sizeof(btConvexConvexAlgorithm);
|
||||
int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm);
|
||||
int maxSize3 = sizeof(btCompoundCollisionAlgorithm);
|
||||
int maxSize4 = sizeof(btEmptyAlgorithm);
|
||||
|
||||
m_collisionAlgorithmMaxElementSize = btMax(maxSize,maxSize2);
|
||||
m_collisionAlgorithmMaxElementSize = btMax(m_collisionAlgorithmMaxElementSize,maxSize3);
|
||||
m_collisionAlgorithmMaxElementSize = btMax(m_collisionAlgorithmMaxElementSize,maxSize4);
|
||||
|
||||
}
|
||||
|
||||
btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
|
||||
{
|
||||
delete m_convexConvexCreateFunc;
|
||||
delete m_convexConcaveCreateFunc;
|
||||
delete m_swappedConvexConcaveCreateFunc;
|
||||
delete m_compoundCreateFunc;
|
||||
delete m_swappedCompoundCreateFunc;
|
||||
delete m_emptyCreateFunc;
|
||||
delete m_sphereSphereCF;
|
||||
delete m_sphereBoxCF;
|
||||
delete m_boxSphereCF;
|
||||
delete m_sphereTriangleCF;
|
||||
delete m_triangleSphereCF;
|
||||
|
||||
|
||||
}
|
||||
|
||||
///pool size for the persistent contact manifold
|
||||
int btDefaultCollisionConfiguration::getPersistentManifoldPoolSize()
|
||||
{
|
||||
return m_persistentManifoldPoolSize;
|
||||
}
|
||||
|
||||
int btDefaultCollisionConfiguration::getStackAllocatorSize()
|
||||
{
|
||||
return m_stackAllocatorSize;
|
||||
}
|
||||
|
||||
int btDefaultCollisionConfiguration::getCollisionAlgorithmPoolSize()
|
||||
{
|
||||
return m_collisionAlgorithmPoolSize;
|
||||
}
|
||||
|
||||
int btDefaultCollisionConfiguration::getCollisionAlgorithmMaxElementSize()
|
||||
{
|
||||
return m_collisionAlgorithmMaxElementSize;
|
||||
|
||||
}
|
||||
|
||||
|
||||
btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
|
||||
{
|
||||
|
||||
|
||||
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
|
||||
{
|
||||
return m_sphereSphereCF;
|
||||
}
|
||||
|
||||
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE))
|
||||
{
|
||||
return m_sphereBoxCF;
|
||||
}
|
||||
|
||||
if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
|
||||
{
|
||||
return m_boxSphereCF;
|
||||
}
|
||||
|
||||
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE))
|
||||
{
|
||||
return m_sphereTriangleCF;
|
||||
}
|
||||
|
||||
if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
|
||||
{
|
||||
return m_triangleSphereCF;
|
||||
}
|
||||
|
||||
|
||||
if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
|
||||
{
|
||||
return m_convexConvexCreateFunc;
|
||||
}
|
||||
|
||||
if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1))
|
||||
{
|
||||
return m_convexConcaveCreateFunc;
|
||||
}
|
||||
|
||||
if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0))
|
||||
{
|
||||
return m_swappedConvexConcaveCreateFunc;
|
||||
}
|
||||
|
||||
if (btBroadphaseProxy::isCompound(proxyType0))
|
||||
{
|
||||
return m_compoundCreateFunc;
|
||||
} else
|
||||
{
|
||||
if (btBroadphaseProxy::isCompound(proxyType1))
|
||||
{
|
||||
return m_swappedCompoundCreateFunc;
|
||||
}
|
||||
}
|
||||
|
||||
//failed to find an algorithm
|
||||
return m_emptyCreateFunc;
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef BT_DEFAULT_COLLISION_CONFIGURATION
|
||||
#define BT_DEFAULT_COLLISION_CONFIGURATION
|
||||
|
||||
#include "btCollisionConfiguration.h"
|
||||
|
||||
///btCollisionConfiguration allows to configure Bullet collision detection
|
||||
///stack allocator size, default collision algorithms and persistent manifold pool size
|
||||
///todo: describe the meaning
|
||||
class btDefaultCollisionConfiguration : public btCollisionConfiguration
|
||||
{
|
||||
|
||||
int m_persistentManifoldPoolSize;
|
||||
|
||||
int m_stackAllocatorSize;
|
||||
|
||||
int m_collisionAlgorithmPoolSize;
|
||||
|
||||
int m_collisionAlgorithmMaxElementSize;
|
||||
|
||||
//default CreationFunctions, filling the m_doubleDispatch table
|
||||
btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
|
||||
btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
|
||||
btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
|
||||
btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
|
||||
btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
|
||||
btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
|
||||
btCollisionAlgorithmCreateFunc* m_sphereSphereCF;
|
||||
btCollisionAlgorithmCreateFunc* m_sphereBoxCF;
|
||||
btCollisionAlgorithmCreateFunc* m_boxSphereCF;
|
||||
btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
|
||||
btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
|
||||
|
||||
public:
|
||||
|
||||
btDefaultCollisionConfiguration();
|
||||
|
||||
virtual ~btDefaultCollisionConfiguration();
|
||||
|
||||
///pool size for the persistent contact manifold
|
||||
virtual int getPersistentManifoldPoolSize();
|
||||
|
||||
virtual int getStackAllocatorSize();
|
||||
|
||||
virtual int getCollisionAlgorithmPoolSize();
|
||||
|
||||
virtual int getCollisionAlgorithmMaxElementSize();
|
||||
|
||||
btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
|
||||
|
||||
void setStackAllocatorSize(int size)
|
||||
{
|
||||
m_stackAllocatorSize = size;
|
||||
}
|
||||
|
||||
void setPersistentManifoldPoolSize(int size)
|
||||
{
|
||||
m_persistentManifoldPoolSize = size;
|
||||
}
|
||||
|
||||
void setCollisionAlgorithmPoolSize(int size)
|
||||
{
|
||||
m_collisionAlgorithmPoolSize = size;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //BT_DEFAULT_COLLISION_CONFIGURATION
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btEmptyCollisionAlgorithm.h"
|
||||
|
||||
|
||||
|
||||
btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
|
||||
: btCollisionAlgorithm(ci)
|
||||
{
|
||||
}
|
||||
|
||||
void btEmptyAlgorithm::processCollision (btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* )
|
||||
{
|
||||
}
|
||||
|
||||
btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* )
|
||||
{
|
||||
return btScalar(1.);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef EMPTY_ALGORITH
|
||||
#define EMPTY_ALGORITH
|
||||
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||
#include "btCollisionCreateFunc.h"
|
||||
#include "btCollisionDispatcher.h"
|
||||
|
||||
#define ATTRIBUTE_ALIGNED(a)
|
||||
|
||||
///EmptyAlgorithm is a stub for unsupported collision pairs.
|
||||
///The dispatcher can dispatch a persistent btEmptyAlgorithm to avoid a search every frame.
|
||||
class btEmptyAlgorithm : public btCollisionAlgorithm
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
|
||||
|
||||
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
struct CreateFunc :public btCollisionAlgorithmCreateFunc
|
||||
{
|
||||
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
(void)body0;
|
||||
(void)body1;
|
||||
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm));
|
||||
return new(mem) btEmptyAlgorithm(ci);
|
||||
}
|
||||
};
|
||||
|
||||
} ATTRIBUTE_ALIGNED(16);
|
||||
|
||||
#endif //EMPTY_ALGORITH
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "btManifoldResult.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
|
||||
|
||||
///This is to allow MaterialCombiner/Custom Friction/Restitution values
|
||||
ContactAddedCallback gContactAddedCallback=0;
|
||||
|
||||
///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
|
||||
inline btScalar calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1)
|
||||
{
|
||||
btScalar friction = body0->getFriction() * body1->getFriction();
|
||||
|
||||
const btScalar MAX_FRICTION = btScalar(10.);
|
||||
if (friction < -MAX_FRICTION)
|
||||
friction = -MAX_FRICTION;
|
||||
if (friction > MAX_FRICTION)
|
||||
friction = MAX_FRICTION;
|
||||
return friction;
|
||||
|
||||
}
|
||||
|
||||
inline btScalar calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1)
|
||||
{
|
||||
return body0->getRestitution() * body1->getRestitution();
|
||||
}
|
||||
|
||||
|
||||
|
||||
btManifoldResult::btManifoldResult(btCollisionObject* body0,btCollisionObject* body1)
|
||||
:m_manifoldPtr(0),
|
||||
m_body0(body0),
|
||||
m_body1(body1)
|
||||
{
|
||||
m_rootTransA = body0->getWorldTransform();
|
||||
m_rootTransB = body1->getWorldTransform();
|
||||
}
|
||||
|
||||
|
||||
void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
|
||||
{
|
||||
assert(m_manifoldPtr);
|
||||
//order in manifold needs to match
|
||||
|
||||
if (depth > m_manifoldPtr->getContactBreakingThreshold())
|
||||
return;
|
||||
|
||||
bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
|
||||
|
||||
btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
|
||||
|
||||
btVector3 localA;
|
||||
btVector3 localB;
|
||||
|
||||
if (isSwapped)
|
||||
{
|
||||
localA = m_rootTransB.invXform(pointA );
|
||||
localB = m_rootTransA.invXform(pointInWorld);
|
||||
} else
|
||||
{
|
||||
localA = m_rootTransA.invXform(pointA );
|
||||
localB = m_rootTransB.invXform(pointInWorld);
|
||||
}
|
||||
|
||||
btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
|
||||
newPt.m_positionWorldOnA = pointA;
|
||||
newPt.m_positionWorldOnB = pointInWorld;
|
||||
|
||||
int insertIndex = m_manifoldPtr->getCacheEntry(newPt);
|
||||
|
||||
newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1);
|
||||
newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1);
|
||||
|
||||
|
||||
///todo, check this for any side effects
|
||||
if (insertIndex >= 0)
|
||||
{
|
||||
//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
|
||||
m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
|
||||
} else
|
||||
{
|
||||
m_manifoldPtr->AddManifoldPoint(newPt);
|
||||
}
|
||||
|
||||
//User can override friction and/or restitution
|
||||
if (gContactAddedCallback &&
|
||||
//and if either of the two bodies requires custom material
|
||||
((m_body0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
|
||||
(m_body1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
|
||||
{
|
||||
//experimental feature info, for per-triangle material etc.
|
||||
btCollisionObject* obj0 = isSwapped? m_body1 : m_body0;
|
||||
btCollisionObject* obj1 = isSwapped? m_body0 : m_body1;
|
||||
(*gContactAddedCallback)(newPt,obj0,m_partId0,m_index0,obj1,m_partId1,m_index1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MANIFOLD_RESULT_H
|
||||
#define MANIFOLD_RESULT_H
|
||||
|
||||
class btCollisionObject;
|
||||
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
||||
class btManifoldPoint;
|
||||
|
||||
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
|
||||
|
||||
#include "LinearMath/btTransform.h"
|
||||
|
||||
typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1);
|
||||
extern ContactAddedCallback gContactAddedCallback;
|
||||
|
||||
|
||||
|
||||
///btManifoldResult is a helper class to manage contact results.
|
||||
class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result
|
||||
{
|
||||
btPersistentManifold* m_manifoldPtr;
|
||||
|
||||
//we need this for compounds
|
||||
btTransform m_rootTransA;
|
||||
btTransform m_rootTransB;
|
||||
|
||||
btCollisionObject* m_body0;
|
||||
btCollisionObject* m_body1;
|
||||
int m_partId0;
|
||||
int m_partId1;
|
||||
int m_index0;
|
||||
int m_index1;
|
||||
public:
|
||||
|
||||
btManifoldResult()
|
||||
{
|
||||
}
|
||||
|
||||
btManifoldResult(btCollisionObject* body0,btCollisionObject* body1);
|
||||
|
||||
virtual ~btManifoldResult() {};
|
||||
|
||||
void setPersistentManifold(btPersistentManifold* manifoldPtr)
|
||||
{
|
||||
m_manifoldPtr = manifoldPtr;
|
||||
}
|
||||
|
||||
virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1)
|
||||
{
|
||||
m_partId0=partId0;
|
||||
m_partId1=partId1;
|
||||
m_index0=index0;
|
||||
m_index1=index1;
|
||||
}
|
||||
|
||||
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth);
|
||||
|
||||
SIMD_FORCE_INLINE void refreshContactPoints()
|
||||
{
|
||||
btAssert(m_manifoldPtr);
|
||||
if (!m_manifoldPtr->getNumContacts())
|
||||
return;
|
||||
|
||||
bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
|
||||
|
||||
if (isSwapped)
|
||||
{
|
||||
m_manifoldPtr->refreshContactPoints(m_rootTransB,m_rootTransA);
|
||||
} else
|
||||
{
|
||||
m_manifoldPtr->refreshContactPoints(m_rootTransA,m_rootTransB);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //MANIFOLD_RESULT_H
|
|
@ -0,0 +1,357 @@
|
|||
|
||||
|
||||
#include "LinearMath/btScalar.h"
|
||||
#include "btSimulationIslandManager.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "LinearMath/btQuickprof.h"
|
||||
|
||||
btSimulationIslandManager::btSimulationIslandManager()
|
||||
{
|
||||
}
|
||||
|
||||
btSimulationIslandManager::~btSimulationIslandManager()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void btSimulationIslandManager::initUnionFind(int n)
|
||||
{
|
||||
m_unionFind.reset(n);
|
||||
}
|
||||
|
||||
|
||||
void btSimulationIslandManager::findUnions(btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
{
|
||||
for (int i=0;i<dispatcher->getNumManifolds();i++)
|
||||
{
|
||||
const btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
|
||||
//static objects (invmass btScalar(0.)) don't merge !
|
||||
|
||||
const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
|
||||
const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
|
||||
|
||||
if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
|
||||
((colObj1) && ((colObj1)->mergesSimulationIslands())))
|
||||
{
|
||||
|
||||
m_unionFind.unite((colObj0)->getIslandTag(),
|
||||
(colObj1)->getIslandTag());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
initUnionFind( int (colWorld->getCollisionObjectArray().size()));
|
||||
|
||||
// put the index into m_controllers into m_tag
|
||||
{
|
||||
|
||||
int index = 0;
|
||||
int i;
|
||||
for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
|
||||
{
|
||||
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
|
||||
collisionObject->setIslandTag(index);
|
||||
collisionObject->setCompanionId(-1);
|
||||
collisionObject->setHitFraction(btScalar(1.));
|
||||
index++;
|
||||
|
||||
}
|
||||
}
|
||||
// do the union find
|
||||
|
||||
findUnions(dispatcher);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
|
||||
{
|
||||
// put the islandId ('find' value) into m_tag
|
||||
{
|
||||
|
||||
|
||||
int index = 0;
|
||||
int i;
|
||||
for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
|
||||
{
|
||||
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
|
||||
if (collisionObject->mergesSimulationIslands())
|
||||
{
|
||||
collisionObject->setIslandTag( m_unionFind.find(index) );
|
||||
collisionObject->setCompanionId(-1);
|
||||
} else
|
||||
{
|
||||
collisionObject->setIslandTag(-1);
|
||||
collisionObject->setCompanionId(-2);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline int getIslandId(const btPersistentManifold* lhs)
|
||||
{
|
||||
int islandId;
|
||||
const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
|
||||
const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
|
||||
islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag();
|
||||
return islandId;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// function object that routes calls to operator<
|
||||
class btPersistentManifoldSortPredicate
|
||||
{
|
||||
public:
|
||||
|
||||
SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs )
|
||||
{
|
||||
return getIslandId(lhs) < getIslandId(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// todo: this is random access, it can be walked 'cache friendly'!
|
||||
//
|
||||
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback)
|
||||
{
|
||||
|
||||
BEGIN_PROFILE("islandUnionFindAndHeapSort");
|
||||
|
||||
//we are going to sort the unionfind array, and store the element id in the size
|
||||
//afterwards, we clean unionfind, to make sure no-one uses it anymore
|
||||
|
||||
getUnionFind().sortIslands();
|
||||
int numElem = getUnionFind().getNumElements();
|
||||
|
||||
int endIslandIndex=1;
|
||||
int startIslandIndex;
|
||||
|
||||
|
||||
//update the sleeping state for bodies, if all are sleeping
|
||||
for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
|
||||
{
|
||||
int islandId = getUnionFind().getElement(startIslandIndex).m_id;
|
||||
for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
|
||||
{
|
||||
}
|
||||
|
||||
//int numSleeping = 0;
|
||||
|
||||
bool allSleeping = true;
|
||||
|
||||
int idx;
|
||||
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
|
||||
{
|
||||
int i = getUnionFind().getElement(idx).m_sz;
|
||||
|
||||
btCollisionObject* colObj0 = collisionObjects[i];
|
||||
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
|
||||
{
|
||||
printf("error in island management\n");
|
||||
}
|
||||
|
||||
assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
|
||||
if (colObj0->getIslandTag() == islandId)
|
||||
{
|
||||
if (colObj0->getActivationState()== ACTIVE_TAG)
|
||||
{
|
||||
allSleeping = false;
|
||||
}
|
||||
if (colObj0->getActivationState()== DISABLE_DEACTIVATION)
|
||||
{
|
||||
allSleeping = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (allSleeping)
|
||||
{
|
||||
int idx;
|
||||
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
|
||||
{
|
||||
int i = getUnionFind().getElement(idx).m_sz;
|
||||
btCollisionObject* colObj0 = collisionObjects[i];
|
||||
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
|
||||
{
|
||||
printf("error in island management\n");
|
||||
}
|
||||
|
||||
assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
|
||||
|
||||
if (colObj0->getIslandTag() == islandId)
|
||||
{
|
||||
colObj0->setActivationState( ISLAND_SLEEPING );
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
|
||||
int idx;
|
||||
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
|
||||
{
|
||||
int i = getUnionFind().getElement(idx).m_sz;
|
||||
|
||||
btCollisionObject* colObj0 = collisionObjects[i];
|
||||
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
|
||||
{
|
||||
printf("error in island management\n");
|
||||
}
|
||||
|
||||
assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
|
||||
|
||||
if (colObj0->getIslandTag() == islandId)
|
||||
{
|
||||
if ( colObj0->getActivationState() == ISLAND_SLEEPING)
|
||||
{
|
||||
colObj0->setActivationState( WANTS_DEACTIVATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int i;
|
||||
int maxNumManifolds = dispatcher->getNumManifolds();
|
||||
|
||||
#define SPLIT_ISLANDS 1
|
||||
#ifdef SPLIT_ISLANDS
|
||||
|
||||
btAlignedObjectArray<btPersistentManifold*> islandmanifold;
|
||||
islandmanifold.reserve(maxNumManifolds);
|
||||
#endif //SPLIT_ISLANDS
|
||||
|
||||
|
||||
for (i=0;i<maxNumManifolds ;i++)
|
||||
{
|
||||
btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
|
||||
|
||||
btCollisionObject* colObj0 = static_cast<btCollisionObject*>(manifold->getBody0());
|
||||
btCollisionObject* colObj1 = static_cast<btCollisionObject*>(manifold->getBody1());
|
||||
|
||||
//todo: check sleeping conditions!
|
||||
if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
|
||||
((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
|
||||
{
|
||||
|
||||
//kinematic objects don't merge islands, but wake up all connected objects
|
||||
if (colObj0->isStaticOrKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
|
||||
{
|
||||
colObj1->activate();
|
||||
}
|
||||
if (colObj1->isStaticOrKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
|
||||
{
|
||||
colObj0->activate();
|
||||
}
|
||||
#ifdef SPLIT_ISLANDS
|
||||
// //filtering for response
|
||||
if (dispatcher->needsResponse(colObj0,colObj1))
|
||||
islandmanifold.push_back(manifold);
|
||||
#endif //SPLIT_ISLANDS
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SPLIT_ISLANDS
|
||||
btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
|
||||
|
||||
callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1);
|
||||
#else
|
||||
// Sort manifolds, based on islands
|
||||
// Sort the vector using predicate and std::sort
|
||||
//std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate);
|
||||
|
||||
int numManifolds = int (islandmanifold.size());
|
||||
|
||||
//we should do radix sort, it it much faster (O(n) instead of O (n log2(n))
|
||||
islandmanifold.heapSort(btPersistentManifoldSortPredicate());
|
||||
|
||||
//now process all active islands (sets of manifolds for now)
|
||||
|
||||
int startManifoldIndex = 0;
|
||||
int endManifoldIndex = 1;
|
||||
|
||||
//int islandId;
|
||||
|
||||
END_PROFILE("islandUnionFindAndHeapSort");
|
||||
|
||||
btAlignedObjectArray<btCollisionObject*> islandBodies;
|
||||
|
||||
|
||||
//traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
|
||||
for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
|
||||
{
|
||||
int islandId = getUnionFind().getElement(startIslandIndex).m_id;
|
||||
|
||||
|
||||
bool islandSleeping = false;
|
||||
|
||||
for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
|
||||
{
|
||||
int i = getUnionFind().getElement(endIslandIndex).m_sz;
|
||||
btCollisionObject* colObj0 = collisionObjects[i];
|
||||
islandBodies.push_back(colObj0);
|
||||
if (!colObj0->isActive())
|
||||
islandSleeping = true;
|
||||
}
|
||||
|
||||
|
||||
//find the accompanying contact manifold for this islandId
|
||||
int numIslandManifolds = 0;
|
||||
btPersistentManifold** startManifold = 0;
|
||||
|
||||
if (startManifoldIndex<numManifolds)
|
||||
{
|
||||
int curIslandId = getIslandId(islandmanifold[startManifoldIndex]);
|
||||
if (curIslandId == islandId)
|
||||
{
|
||||
startManifold = &islandmanifold[startManifoldIndex];
|
||||
|
||||
for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(islandmanifold[endManifoldIndex]));endManifoldIndex++)
|
||||
{
|
||||
|
||||
}
|
||||
/// Process the actual simulation, only if not sleeping/deactivated
|
||||
numIslandManifolds = endManifoldIndex-startManifoldIndex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!islandSleeping)
|
||||
{
|
||||
callback->ProcessIsland(&islandBodies[0],islandBodies.size(),startManifold,numIslandManifolds, islandId);
|
||||
}
|
||||
|
||||
if (numIslandManifolds)
|
||||
{
|
||||
startManifoldIndex = endManifoldIndex;
|
||||
}
|
||||
|
||||
islandBodies.resize(0);
|
||||
}
|
||||
#endif //SPLIT_ISLANDS
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SIMULATION_ISLAND_MANAGER_H
|
||||
#define SIMULATION_ISLAND_MANAGER_H
|
||||
|
||||
#include "BulletCollision/CollisionDispatch/btUnionFind.h"
|
||||
#include "btCollisionCreateFunc.h"
|
||||
|
||||
class btCollisionObject;
|
||||
class btCollisionWorld;
|
||||
class btDispatcher;
|
||||
|
||||
///SimulationIslandManager creates and handles simulation islands, using btUnionFind
|
||||
class btSimulationIslandManager
|
||||
{
|
||||
btUnionFind m_unionFind;
|
||||
|
||||
public:
|
||||
btSimulationIslandManager();
|
||||
virtual ~btSimulationIslandManager();
|
||||
|
||||
|
||||
void initUnionFind(int n);
|
||||
|
||||
|
||||
btUnionFind& getUnionFind() { return m_unionFind;}
|
||||
|
||||
virtual void updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher);
|
||||
virtual void storeIslandActivationState(btCollisionWorld* world);
|
||||
|
||||
|
||||
void findUnions(btDispatcher* dispatcher);
|
||||
|
||||
|
||||
|
||||
struct IslandCallback
|
||||
{
|
||||
virtual ~IslandCallback() {};
|
||||
|
||||
virtual void ProcessIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold** manifolds,int numManifolds, int islandId) = 0;
|
||||
};
|
||||
|
||||
void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback);
|
||||
|
||||
};
|
||||
|
||||
#endif //SIMULATION_ISLAND_MANAGER_H
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btSphereBoxCollisionAlgorithm.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||
#include "BulletCollision/CollisionShapes/btSphereShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btBoxShape.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
//#include <stdio.h>
|
||||
|
||||
btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped)
|
||||
: btCollisionAlgorithm(ci),
|
||||
m_ownManifold(false),
|
||||
m_manifoldPtr(mf),
|
||||
m_isSwapped(isSwapped)
|
||||
{
|
||||
btCollisionObject* sphereObj = m_isSwapped? col1 : col0;
|
||||
btCollisionObject* boxObj = m_isSwapped? col0 : col1;
|
||||
|
||||
if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObj,boxObj))
|
||||
{
|
||||
m_manifoldPtr = m_dispatcher->getNewManifold(sphereObj,boxObj);
|
||||
m_ownManifold = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
|
||||
{
|
||||
if (m_ownManifold)
|
||||
{
|
||||
if (m_manifoldPtr)
|
||||
m_dispatcher->releaseManifold(m_manifoldPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
(void)dispatchInfo;
|
||||
(void)resultOut;
|
||||
if (!m_manifoldPtr)
|
||||
return;
|
||||
|
||||
btCollisionObject* sphereObj = m_isSwapped? body1 : body0;
|
||||
btCollisionObject* boxObj = m_isSwapped? body0 : body1;
|
||||
|
||||
|
||||
btSphereShape* sphere0 = (btSphereShape*)sphereObj->getCollisionShape();
|
||||
|
||||
btVector3 normalOnSurfaceB;
|
||||
btVector3 pOnBox,pOnSphere;
|
||||
btVector3 sphereCenter = sphereObj->getWorldTransform().getOrigin();
|
||||
btScalar radius = sphere0->getRadius();
|
||||
|
||||
btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius);
|
||||
|
||||
resultOut->setPersistentManifold(m_manifoldPtr);
|
||||
|
||||
if (dist < SIMD_EPSILON)
|
||||
{
|
||||
btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize();
|
||||
|
||||
/// report a contact. internally this will be kept persistent, and contact reduction is done
|
||||
|
||||
resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist);
|
||||
|
||||
}
|
||||
|
||||
if (m_ownManifold)
|
||||
{
|
||||
if (m_manifoldPtr->getNumContacts())
|
||||
{
|
||||
resultOut->refreshContactPoints();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
(void)resultOut;
|
||||
(void)dispatchInfo;
|
||||
(void)col0;
|
||||
(void)col1;
|
||||
|
||||
//not yet
|
||||
return btScalar(1.);
|
||||
}
|
||||
|
||||
|
||||
btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* boxObj, btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius )
|
||||
{
|
||||
|
||||
btScalar margins;
|
||||
btVector3 bounds[2];
|
||||
btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape();
|
||||
|
||||
bounds[0] = -boxShape->getHalfExtentsWithoutMargin();
|
||||
bounds[1] = boxShape->getHalfExtentsWithoutMargin();
|
||||
|
||||
margins = boxShape->getMargin();//also add sphereShape margin?
|
||||
|
||||
const btTransform& m44T = boxObj->getWorldTransform();
|
||||
|
||||
btVector3 boundsVec[2];
|
||||
btScalar fPenetration;
|
||||
|
||||
boundsVec[0] = bounds[0];
|
||||
boundsVec[1] = bounds[1];
|
||||
|
||||
btVector3 marginsVec( margins, margins, margins );
|
||||
|
||||
// add margins
|
||||
bounds[0] += marginsVec;
|
||||
bounds[1] -= marginsVec;
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
btVector3 tmp, prel, n[6], normal, v3P;
|
||||
btScalar fSep = btScalar(10000000.0), fSepThis;
|
||||
|
||||
n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) );
|
||||
n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) );
|
||||
n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) );
|
||||
n[3].setValue( btScalar(1.0), btScalar(0.0), btScalar(0.0) );
|
||||
n[4].setValue( btScalar(0.0), btScalar(1.0), btScalar(0.0) );
|
||||
n[5].setValue( btScalar(0.0), btScalar(0.0), btScalar(1.0) );
|
||||
|
||||
// convert point in local space
|
||||
prel = m44T.invXform( sphereCenter);
|
||||
|
||||
bool bFound = false;
|
||||
|
||||
v3P = prel;
|
||||
|
||||
for (int i=0;i<6;i++)
|
||||
{
|
||||
int j = i<3? 0:1;
|
||||
if ( (fSepThis = ((v3P-bounds[j]) .dot(n[i]))) > btScalar(0.0) )
|
||||
{
|
||||
v3P = v3P - n[i]*fSepThis;
|
||||
bFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if ( bFound )
|
||||
{
|
||||
bounds[0] = boundsVec[0];
|
||||
bounds[1] = boundsVec[1];
|
||||
|
||||
normal = (prel - v3P).normalize();
|
||||
pointOnBox = v3P + normal*margins;
|
||||
v3PointOnSphere = prel - normal*fRadius;
|
||||
|
||||
if ( ((v3PointOnSphere - pointOnBox) .dot (normal)) > btScalar(0.0) )
|
||||
{
|
||||
return btScalar(1.0);
|
||||
}
|
||||
|
||||
// transform back in world space
|
||||
tmp = m44T( pointOnBox);
|
||||
pointOnBox = tmp;
|
||||
tmp = m44T( v3PointOnSphere);
|
||||
v3PointOnSphere = tmp;
|
||||
btScalar fSeps2 = (pointOnBox-v3PointOnSphere).length2();
|
||||
|
||||
//if this fails, fallback into deeper penetration case, below
|
||||
if (fSeps2 > SIMD_EPSILON)
|
||||
{
|
||||
fSep = - btSqrt(fSeps2);
|
||||
normal = (pointOnBox-v3PointOnSphere);
|
||||
normal *= btScalar(1.)/fSep;
|
||||
}
|
||||
|
||||
return fSep;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Deep penetration case
|
||||
|
||||
fPenetration = getSpherePenetration( boxObj,pointOnBox, v3PointOnSphere, sphereCenter, fRadius,bounds[0],bounds[1] );
|
||||
|
||||
bounds[0] = boundsVec[0];
|
||||
bounds[1] = boundsVec[1];
|
||||
|
||||
if ( fPenetration <= btScalar(0.0) )
|
||||
return (fPenetration-margins);
|
||||
else
|
||||
return btScalar(1.0);
|
||||
}
|
||||
|
||||
btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject* boxObj,btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax)
|
||||
{
|
||||
|
||||
btVector3 bounds[2];
|
||||
|
||||
bounds[0] = aabbMin;
|
||||
bounds[1] = aabbMax;
|
||||
|
||||
btVector3 p0, tmp, prel, n[6], normal;
|
||||
btScalar fSep = btScalar(-10000000.0), fSepThis;
|
||||
|
||||
// set p0 and normal to a default value to shup up GCC
|
||||
p0.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
|
||||
normal.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
|
||||
|
||||
n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) );
|
||||
n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) );
|
||||
n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) );
|
||||
n[3].setValue( btScalar(1.0), btScalar(0.0), btScalar(0.0) );
|
||||
n[4].setValue( btScalar(0.0), btScalar(1.0), btScalar(0.0) );
|
||||
n[5].setValue( btScalar(0.0), btScalar(0.0), btScalar(1.0) );
|
||||
|
||||
const btTransform& m44T = boxObj->getWorldTransform();
|
||||
|
||||
// convert point in local space
|
||||
prel = m44T.invXform( sphereCenter);
|
||||
|
||||
///////////
|
||||
|
||||
for (int i=0;i<6;i++)
|
||||
{
|
||||
int j = i<3 ? 0:1;
|
||||
if ( (fSepThis = ((prel-bounds[j]) .dot( n[i]))-fRadius) > btScalar(0.0) ) return btScalar(1.0);
|
||||
if ( fSepThis > fSep )
|
||||
{
|
||||
p0 = bounds[j]; normal = (btVector3&)n[i];
|
||||
fSep = fSepThis;
|
||||
}
|
||||
}
|
||||
|
||||
pointOnBox = prel - normal*(normal.dot((prel-p0)));
|
||||
v3PointOnSphere = pointOnBox + normal*fSep;
|
||||
|
||||
// transform back in world space
|
||||
tmp = m44T( pointOnBox);
|
||||
pointOnBox = tmp;
|
||||
tmp = m44T( v3PointOnSphere); v3PointOnSphere = tmp;
|
||||
normal = (pointOnBox-v3PointOnSphere).normalize();
|
||||
|
||||
return fSep;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SPHERE_BOX_COLLISION_ALGORITHM_H
|
||||
#define SPHERE_BOX_COLLISION_ALGORITHM_H
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
|
||||
class btPersistentManifold;
|
||||
#include "btCollisionDispatcher.h"
|
||||
|
||||
#include "LinearMath/btVector3.h"
|
||||
|
||||
/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
|
||||
/// Other features are frame-coherency (persistent data) and collision response.
|
||||
class btSphereBoxCollisionAlgorithm : public btCollisionAlgorithm
|
||||
{
|
||||
bool m_ownManifold;
|
||||
btPersistentManifold* m_manifoldPtr;
|
||||
bool m_isSwapped;
|
||||
|
||||
public:
|
||||
|
||||
btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
|
||||
|
||||
virtual ~btSphereBoxCollisionAlgorithm();
|
||||
|
||||
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius );
|
||||
|
||||
btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax);
|
||||
|
||||
struct CreateFunc :public btCollisionAlgorithmCreateFunc
|
||||
{
|
||||
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
|
||||
if (!m_swapped)
|
||||
{
|
||||
return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false);
|
||||
} else
|
||||
{
|
||||
return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif //SPHERE_BOX_COLLISION_ALGORITHM_H
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btSphereSphereCollisionAlgorithm.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||
#include "BulletCollision/CollisionShapes/btSphereShape.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
|
||||
btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1)
|
||||
: btCollisionAlgorithm(ci),
|
||||
m_ownManifold(false),
|
||||
m_manifoldPtr(mf)
|
||||
{
|
||||
if (!m_manifoldPtr)
|
||||
{
|
||||
m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1);
|
||||
m_ownManifold = true;
|
||||
}
|
||||
}
|
||||
|
||||
btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm()
|
||||
{
|
||||
if (m_ownManifold)
|
||||
{
|
||||
if (m_manifoldPtr)
|
||||
m_dispatcher->releaseManifold(m_manifoldPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
(void)dispatchInfo;
|
||||
|
||||
if (!m_manifoldPtr)
|
||||
return;
|
||||
|
||||
resultOut->setPersistentManifold(m_manifoldPtr);
|
||||
|
||||
btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape();
|
||||
btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape();
|
||||
|
||||
btVector3 diff = col0->getWorldTransform().getOrigin()- col1->getWorldTransform().getOrigin();
|
||||
btScalar len = diff.length();
|
||||
btScalar radius0 = sphere0->getRadius();
|
||||
btScalar radius1 = sphere1->getRadius();
|
||||
|
||||
m_manifoldPtr->clearManifold();
|
||||
|
||||
///iff distance positive, don't generate a new contact
|
||||
if ( len > (radius0+radius1))
|
||||
{
|
||||
return;
|
||||
}
|
||||
///distance (negative means penetration)
|
||||
btScalar dist = len - (radius0+radius1);
|
||||
|
||||
btVector3 normalOnSurfaceB = diff / len;
|
||||
///point on A (worldspace)
|
||||
btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
|
||||
///point on B (worldspace)
|
||||
btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;
|
||||
|
||||
/// report a contact. internally this will be kept persistent, and contact reduction is done
|
||||
|
||||
|
||||
resultOut->addContactPoint(normalOnSurfaceB,pos1,dist);
|
||||
|
||||
//no resultOut->refreshContactPoints(); needed, because of clearManifold (all points are new)
|
||||
|
||||
}
|
||||
|
||||
btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
(void)col0;
|
||||
(void)col1;
|
||||
(void)dispatchInfo;
|
||||
(void)resultOut;
|
||||
|
||||
//not yet
|
||||
return btScalar(1.);
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H
|
||||
#define SPHERE_SPHERE_COLLISION_ALGORITHM_H
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
|
||||
#include "btCollisionDispatcher.h"
|
||||
|
||||
class btPersistentManifold;
|
||||
|
||||
/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection.
|
||||
/// Other features are frame-coherency (persistent data) and collision response.
|
||||
/// Also provides the most basic sample for custom/user btCollisionAlgorithm
|
||||
class btSphereSphereCollisionAlgorithm : public btCollisionAlgorithm
|
||||
{
|
||||
bool m_ownManifold;
|
||||
btPersistentManifold* m_manifoldPtr;
|
||||
|
||||
public:
|
||||
btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
|
||||
|
||||
btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
|
||||
: btCollisionAlgorithm(ci) {}
|
||||
|
||||
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
|
||||
virtual ~btSphereSphereCollisionAlgorithm();
|
||||
|
||||
struct CreateFunc :public btCollisionAlgorithmCreateFunc
|
||||
{
|
||||
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
|
||||
return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif //SPHERE_SPHERE_COLLISION_ALGORITHM_H
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "btSphereTriangleCollisionAlgorithm.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||
#include "BulletCollision/CollisionShapes/btSphereShape.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "SphereTriangleDetector.h"
|
||||
|
||||
|
||||
btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1,bool swapped)
|
||||
: btCollisionAlgorithm(ci),
|
||||
m_ownManifold(false),
|
||||
m_manifoldPtr(mf),
|
||||
m_swapped(swapped)
|
||||
{
|
||||
if (!m_manifoldPtr)
|
||||
{
|
||||
m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1);
|
||||
m_ownManifold = true;
|
||||
}
|
||||
}
|
||||
|
||||
btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm()
|
||||
{
|
||||
if (m_ownManifold)
|
||||
{
|
||||
if (m_manifoldPtr)
|
||||
m_dispatcher->releaseManifold(m_manifoldPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
if (!m_manifoldPtr)
|
||||
return;
|
||||
|
||||
btCollisionObject* sphereObj = m_swapped? col1 : col0;
|
||||
btCollisionObject* triObj = m_swapped? col0 : col1;
|
||||
|
||||
btSphereShape* sphere = (btSphereShape*)sphereObj->getCollisionShape();
|
||||
btTriangleShape* triangle = (btTriangleShape*)triObj->getCollisionShape();
|
||||
|
||||
/// report a contact. internally this will be kept persistent, and contact reduction is done
|
||||
resultOut->setPersistentManifold(m_manifoldPtr);
|
||||
SphereTriangleDetector detector(sphere,triangle);
|
||||
|
||||
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
|
||||
input.m_maximumDistanceSquared = btScalar(1e30);//todo: tighter bounds
|
||||
input.m_transformA = col0->getWorldTransform();
|
||||
input.m_transformB = col1->getWorldTransform();
|
||||
|
||||
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
|
||||
|
||||
if (m_ownManifold)
|
||||
resultOut->refreshContactPoints();
|
||||
|
||||
}
|
||||
|
||||
btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
(void)resultOut;
|
||||
(void)dispatchInfo;
|
||||
(void)col0;
|
||||
(void)col1;
|
||||
|
||||
//not yet
|
||||
return btScalar(1.);
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
|
||||
#define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
|
||||
class btPersistentManifold;
|
||||
#include "btCollisionDispatcher.h"
|
||||
|
||||
/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection.
|
||||
/// Other features are frame-coherency (persistent data) and collision response.
|
||||
/// Also provides the most basic sample for custom/user btCollisionAlgorithm
|
||||
class btSphereTriangleCollisionAlgorithm : public btCollisionAlgorithm
|
||||
{
|
||||
bool m_ownManifold;
|
||||
btPersistentManifold* m_manifoldPtr;
|
||||
bool m_swapped;
|
||||
|
||||
public:
|
||||
btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool swapped);
|
||||
|
||||
btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
|
||||
: btCollisionAlgorithm(ci) {}
|
||||
|
||||
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
|
||||
virtual ~btSphereTriangleCollisionAlgorithm();
|
||||
|
||||
struct CreateFunc :public btCollisionAlgorithmCreateFunc
|
||||
{
|
||||
|
||||
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
|
||||
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
|
||||
|
||||
return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif //SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btUnionFind.h"
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
|
||||
|
||||
btUnionFind::~btUnionFind()
|
||||
{
|
||||
Free();
|
||||
|
||||
}
|
||||
|
||||
btUnionFind::btUnionFind()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void btUnionFind::allocate(int N)
|
||||
{
|
||||
m_elements.resize(N);
|
||||
}
|
||||
void btUnionFind::Free()
|
||||
{
|
||||
m_elements.clear();
|
||||
}
|
||||
|
||||
|
||||
void btUnionFind::reset(int N)
|
||||
{
|
||||
allocate(N);
|
||||
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
m_elements[i].m_id = i; m_elements[i].m_sz = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class btUnionFindElementSortPredicate
|
||||
{
|
||||
public:
|
||||
|
||||
bool operator() ( const btElement& lhs, const btElement& rhs )
|
||||
{
|
||||
return lhs.m_id < rhs.m_id;
|
||||
}
|
||||
};
|
||||
|
||||
///this is a special operation, destroying the content of btUnionFind.
|
||||
///it sorts the elements, based on island id, in order to make it easy to iterate over islands
|
||||
void btUnionFind::sortIslands()
|
||||
{
|
||||
|
||||
//first store the original body index, and islandId
|
||||
int numElements = m_elements.size();
|
||||
|
||||
for (int i=0;i<numElements;i++)
|
||||
{
|
||||
m_elements[i].m_id = find(i);
|
||||
m_elements[i].m_sz = i;
|
||||
}
|
||||
|
||||
// Sort the vector using predicate and std::sort
|
||||
//std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
|
||||
//perhaps use radix sort?
|
||||
m_elements.heapSort(btUnionFindElementSortPredicate());
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef UNION_FIND_H
|
||||
#define UNION_FIND_H
|
||||
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
|
||||
#define USE_PATH_COMPRESSION 1
|
||||
|
||||
struct btElement
|
||||
{
|
||||
int m_id;
|
||||
int m_sz;
|
||||
};
|
||||
|
||||
///UnionFind calculates connected subsets
|
||||
// Implements weighted Quick Union with path compression
|
||||
// optimization: could use short ints instead of ints (halving memory, would limit the number of rigid bodies to 64k, sounds reasonable)
|
||||
class btUnionFind
|
||||
{
|
||||
private:
|
||||
btAlignedObjectArray<btElement> m_elements;
|
||||
|
||||
public:
|
||||
|
||||
btUnionFind();
|
||||
~btUnionFind();
|
||||
|
||||
|
||||
//this is a special operation, destroying the content of btUnionFind.
|
||||
//it sorts the elements, based on island id, in order to make it easy to iterate over islands
|
||||
void sortIslands();
|
||||
|
||||
void reset(int N);
|
||||
|
||||
SIMD_FORCE_INLINE int getNumElements() const
|
||||
{
|
||||
return int(m_elements.size());
|
||||
}
|
||||
SIMD_FORCE_INLINE bool isRoot(int x) const
|
||||
{
|
||||
return (x == m_elements[x].m_id);
|
||||
}
|
||||
|
||||
btElement& getElement(int index)
|
||||
{
|
||||
return m_elements[index];
|
||||
}
|
||||
const btElement& getElement(int index) const
|
||||
{
|
||||
return m_elements[index];
|
||||
}
|
||||
|
||||
void allocate(int N);
|
||||
void Free();
|
||||
|
||||
|
||||
|
||||
|
||||
int find(int p, int q)
|
||||
{
|
||||
return (find(p) == find(q));
|
||||
}
|
||||
|
||||
void unite(int p, int q)
|
||||
{
|
||||
int i = find(p), j = find(q);
|
||||
if (i == j)
|
||||
return;
|
||||
|
||||
#ifndef USE_PATH_COMPRESSION
|
||||
//weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) )
|
||||
if (m_elements[i].m_sz < m_elements[j].m_sz)
|
||||
{
|
||||
m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_elements[j].m_id = i; m_elements[i].m_sz += m_elements[j].m_sz;
|
||||
}
|
||||
#else
|
||||
m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz;
|
||||
#endif //USE_PATH_COMPRESSION
|
||||
}
|
||||
|
||||
int find(int x)
|
||||
{
|
||||
//assert(x < m_N);
|
||||
//assert(x >= 0);
|
||||
|
||||
while (x != m_elements[x].m_id)
|
||||
{
|
||||
//not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically
|
||||
|
||||
#ifdef USE_PATH_COMPRESSION
|
||||
//
|
||||
m_elements[x].m_id = m_elements[m_elements[x].m_id].m_id;
|
||||
#endif //
|
||||
x = m_elements[x].m_id;
|
||||
//assert(x < m_N);
|
||||
//assert(x >= 0);
|
||||
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //UNION_FIND_H
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btBoxShape.h"
|
||||
|
||||
|
||||
//{
|
||||
|
||||
|
||||
void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
|
||||
{
|
||||
const btVector3& halfExtents = getHalfExtentsWithoutMargin();
|
||||
|
||||
btMatrix3x3 abs_b = t.getBasis().absolute();
|
||||
btPoint3 center = t.getOrigin();
|
||||
btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
|
||||
abs_b[1].dot(halfExtents),
|
||||
abs_b[2].dot(halfExtents));
|
||||
extent += btVector3(getMargin(),getMargin(),getMargin());
|
||||
|
||||
aabbMin = center - extent;
|
||||
aabbMax = center + extent;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
|
||||
{
|
||||
//btScalar margin = btScalar(0.);
|
||||
btVector3 halfExtents = getHalfExtentsWithMargin();
|
||||
|
||||
btScalar lx=btScalar(2.)*(halfExtents.x());
|
||||
btScalar ly=btScalar(2.)*(halfExtents.y());
|
||||
btScalar lz=btScalar(2.)*(halfExtents.z());
|
||||
|
||||
inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
|
||||
mass/(btScalar(12.0)) * (lx*lx + lz*lz),
|
||||
mass/(btScalar(12.0)) * (lx*lx + ly*ly));
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,323 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef OBB_BOX_MINKOWSKI_H
|
||||
#define OBB_BOX_MINKOWSKI_H
|
||||
|
||||
#include "btPolyhedralConvexShape.h"
|
||||
#include "btCollisionMargin.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
#include "LinearMath/btPoint3.h"
|
||||
#include "LinearMath/btSimdMinMax.h"
|
||||
|
||||
///btBoxShape implements both a feature based (vertex/edge/plane) and implicit (getSupportingVertex) Box
|
||||
class btBoxShape: public btPolyhedralConvexShape
|
||||
{
|
||||
|
||||
//btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead
|
||||
|
||||
|
||||
public:
|
||||
|
||||
btVector3 getHalfExtentsWithMargin() const
|
||||
{
|
||||
btVector3 halfExtents = getHalfExtentsWithoutMargin();
|
||||
btVector3 margin(getMargin(),getMargin(),getMargin());
|
||||
halfExtents += margin;
|
||||
return halfExtents;
|
||||
}
|
||||
|
||||
const btVector3& getHalfExtentsWithoutMargin() const
|
||||
{
|
||||
return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included
|
||||
}
|
||||
|
||||
|
||||
virtual int getShapeType() const { return BOX_SHAPE_PROXYTYPE;}
|
||||
|
||||
virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
|
||||
{
|
||||
btVector3 halfExtents = getHalfExtentsWithoutMargin();
|
||||
btVector3 margin(getMargin(),getMargin(),getMargin());
|
||||
halfExtents += margin;
|
||||
|
||||
return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
|
||||
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
|
||||
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
|
||||
{
|
||||
const btVector3& halfExtents = getHalfExtentsWithoutMargin();
|
||||
|
||||
return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
|
||||
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
|
||||
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
|
||||
}
|
||||
|
||||
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
|
||||
{
|
||||
const btVector3& halfExtents = getHalfExtentsWithoutMargin();
|
||||
|
||||
for (int i=0;i<numVectors;i++)
|
||||
{
|
||||
const btVector3& vec = vectors[i];
|
||||
supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
|
||||
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
|
||||
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
btBoxShape( const btVector3& boxHalfExtents)
|
||||
{
|
||||
btVector3 margin(getMargin(),getMargin(),getMargin());
|
||||
m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
|
||||
};
|
||||
|
||||
virtual void setMargin(btScalar collisionMargin)
|
||||
{
|
||||
//correct the m_implicitShapeDimensions for the margin
|
||||
btVector3 oldMargin(getMargin(),getMargin(),getMargin());
|
||||
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
|
||||
|
||||
btConvexInternalShape::setMargin(collisionMargin);
|
||||
btVector3 newMargin(getMargin(),getMargin(),getMargin());
|
||||
m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
|
||||
|
||||
}
|
||||
virtual void setLocalScaling(const btVector3& scaling)
|
||||
{
|
||||
btVector3 oldMargin(getMargin(),getMargin(),getMargin());
|
||||
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
|
||||
btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
|
||||
|
||||
btConvexInternalShape::setLocalScaling(scaling);
|
||||
|
||||
m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
|
||||
|
||||
}
|
||||
|
||||
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
|
||||
|
||||
|
||||
|
||||
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
|
||||
|
||||
virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const
|
||||
{
|
||||
//this plane might not be aligned...
|
||||
btVector4 plane ;
|
||||
getPlaneEquation(plane,i);
|
||||
planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ());
|
||||
planeSupport = localGetSupportingVertex(-planeNormal);
|
||||
}
|
||||
|
||||
|
||||
virtual int getNumPlanes() const
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
virtual int getNumVertices() const
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
virtual int getNumEdges() const
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
|
||||
|
||||
virtual void getVertex(int i,btVector3& vtx) const
|
||||
{
|
||||
btVector3 halfExtents = getHalfExtentsWithoutMargin();
|
||||
|
||||
vtx = btVector3(
|
||||
halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
|
||||
halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1),
|
||||
halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2));
|
||||
}
|
||||
|
||||
|
||||
virtual void getPlaneEquation(btVector4& plane,int i) const
|
||||
{
|
||||
btVector3 halfExtents = getHalfExtentsWithoutMargin();
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.));
|
||||
plane[3] = -halfExtents.x();
|
||||
break;
|
||||
case 1:
|
||||
plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.));
|
||||
plane[3] = -halfExtents.x();
|
||||
break;
|
||||
case 2:
|
||||
plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.));
|
||||
plane[3] = -halfExtents.y();
|
||||
break;
|
||||
case 3:
|
||||
plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.));
|
||||
plane[3] = -halfExtents.y();
|
||||
break;
|
||||
case 4:
|
||||
plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.));
|
||||
plane[3] = -halfExtents.z();
|
||||
break;
|
||||
case 5:
|
||||
plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.));
|
||||
plane[3] = -halfExtents.z();
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const
|
||||
//virtual void getEdge(int i,Edge& edge) const
|
||||
{
|
||||
int edgeVert0 = 0;
|
||||
int edgeVert1 = 0;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
edgeVert0 = 0;
|
||||
edgeVert1 = 1;
|
||||
break;
|
||||
case 1:
|
||||
edgeVert0 = 0;
|
||||
edgeVert1 = 2;
|
||||
break;
|
||||
case 2:
|
||||
edgeVert0 = 1;
|
||||
edgeVert1 = 3;
|
||||
|
||||
break;
|
||||
case 3:
|
||||
edgeVert0 = 2;
|
||||
edgeVert1 = 3;
|
||||
break;
|
||||
case 4:
|
||||
edgeVert0 = 0;
|
||||
edgeVert1 = 4;
|
||||
break;
|
||||
case 5:
|
||||
edgeVert0 = 1;
|
||||
edgeVert1 = 5;
|
||||
|
||||
break;
|
||||
case 6:
|
||||
edgeVert0 = 2;
|
||||
edgeVert1 = 6;
|
||||
break;
|
||||
case 7:
|
||||
edgeVert0 = 3;
|
||||
edgeVert1 = 7;
|
||||
break;
|
||||
case 8:
|
||||
edgeVert0 = 4;
|
||||
edgeVert1 = 5;
|
||||
break;
|
||||
case 9:
|
||||
edgeVert0 = 4;
|
||||
edgeVert1 = 6;
|
||||
break;
|
||||
case 10:
|
||||
edgeVert0 = 5;
|
||||
edgeVert1 = 7;
|
||||
break;
|
||||
case 11:
|
||||
edgeVert0 = 6;
|
||||
edgeVert1 = 7;
|
||||
break;
|
||||
default:
|
||||
btAssert(0);
|
||||
|
||||
}
|
||||
|
||||
getVertex(edgeVert0,pa );
|
||||
getVertex(edgeVert1,pb );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual bool isInside(const btPoint3& pt,btScalar tolerance) const
|
||||
{
|
||||
btVector3 halfExtents = getHalfExtentsWithoutMargin();
|
||||
|
||||
//btScalar minDist = 2*tolerance;
|
||||
|
||||
bool result = (pt.x() <= (halfExtents.x()+tolerance)) &&
|
||||
(pt.x() >= (-halfExtents.x()-tolerance)) &&
|
||||
(pt.y() <= (halfExtents.y()+tolerance)) &&
|
||||
(pt.y() >= (-halfExtents.y()-tolerance)) &&
|
||||
(pt.z() <= (halfExtents.z()+tolerance)) &&
|
||||
(pt.z() >= (-halfExtents.z()-tolerance));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//debugging
|
||||
virtual const char* getName()const
|
||||
{
|
||||
return "Box";
|
||||
}
|
||||
|
||||
virtual int getNumPreferredPenetrationDirections() const
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.));
|
||||
break;
|
||||
case 1:
|
||||
penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.));
|
||||
break;
|
||||
case 2:
|
||||
penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.));
|
||||
break;
|
||||
case 3:
|
||||
penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.));
|
||||
break;
|
||||
case 4:
|
||||
penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.));
|
||||
break;
|
||||
case 5:
|
||||
penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.));
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //OBB_BOX_MINKOWSKI_H
|
||||
|
||||
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
//#define DISABLE_BVH
|
||||
|
||||
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
|
||||
|
||||
|
||||
///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
|
||||
///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
|
||||
btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
|
||||
:btTriangleMeshShape(meshInterface),
|
||||
m_bvh(0),
|
||||
m_useQuantizedAabbCompression(useQuantizedAabbCompression),
|
||||
m_ownsBvh(false)
|
||||
{
|
||||
//construct bvh from meshInterface
|
||||
#ifndef DISABLE_BVH
|
||||
|
||||
btVector3 bvhAabbMin,bvhAabbMax;
|
||||
meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax);
|
||||
|
||||
if (buildBvh)
|
||||
{
|
||||
m_bvh = new btOptimizedBvh();
|
||||
m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
|
||||
m_ownsBvh = true;
|
||||
}
|
||||
|
||||
#endif //DISABLE_BVH
|
||||
|
||||
}
|
||||
|
||||
btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
|
||||
:btTriangleMeshShape(meshInterface),
|
||||
m_bvh(0),
|
||||
m_useQuantizedAabbCompression(useQuantizedAabbCompression),
|
||||
m_ownsBvh(false)
|
||||
{
|
||||
//construct bvh from meshInterface
|
||||
#ifndef DISABLE_BVH
|
||||
|
||||
if (buildBvh)
|
||||
{
|
||||
m_bvh = new btOptimizedBvh();
|
||||
m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
|
||||
m_ownsBvh = true;
|
||||
}
|
||||
|
||||
#endif //DISABLE_BVH
|
||||
|
||||
}
|
||||
|
||||
void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax)
|
||||
{
|
||||
m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax );
|
||||
|
||||
m_localAabbMin.setMin(aabbMin);
|
||||
m_localAabbMax.setMax(aabbMax);
|
||||
}
|
||||
|
||||
|
||||
void btBvhTriangleMeshShape::refitTree()
|
||||
{
|
||||
m_bvh->refit( m_meshInterface );
|
||||
|
||||
recalcLocalAabb();
|
||||
}
|
||||
|
||||
btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
|
||||
{
|
||||
if (m_ownsBvh)
|
||||
delete m_bvh;
|
||||
}
|
||||
|
||||
//perform bvh tree traversal and report overlapping triangles to 'callback'
|
||||
void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
|
||||
{
|
||||
|
||||
#ifdef DISABLE_BVH
|
||||
//brute force traverse all triangles
|
||||
btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax);
|
||||
#else
|
||||
|
||||
//first get all the nodes
|
||||
|
||||
|
||||
struct MyNodeOverlapCallback : public btNodeOverlapCallback
|
||||
{
|
||||
btStridingMeshInterface* m_meshInterface;
|
||||
btTriangleCallback* m_callback;
|
||||
btVector3 m_triangle[3];
|
||||
|
||||
|
||||
MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
|
||||
:m_meshInterface(meshInterface),
|
||||
m_callback(callback)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
|
||||
{
|
||||
const unsigned char *vertexbase;
|
||||
int numverts;
|
||||
PHY_ScalarType type;
|
||||
int stride;
|
||||
const unsigned char *indexbase;
|
||||
int indexstride;
|
||||
int numfaces;
|
||||
PHY_ScalarType indicestype;
|
||||
|
||||
|
||||
m_meshInterface->getLockedReadOnlyVertexIndexBase(
|
||||
&vertexbase,
|
||||
numverts,
|
||||
type,
|
||||
stride,
|
||||
&indexbase,
|
||||
indexstride,
|
||||
numfaces,
|
||||
indicestype,
|
||||
nodeSubPart);
|
||||
|
||||
int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride);
|
||||
|
||||
const btVector3& meshScaling = m_meshInterface->getScaling();
|
||||
for (int j=2;j>=0;j--)
|
||||
{
|
||||
|
||||
int graphicsindex = gfxbase[j];
|
||||
|
||||
|
||||
#ifdef DEBUG_TRIANGLE_MESH
|
||||
printf("%d ,",graphicsindex);
|
||||
#endif //DEBUG_TRIANGLE_MESH
|
||||
btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
|
||||
|
||||
m_triangle[j] = btVector3(
|
||||
graphicsbase[0]*meshScaling.getX(),
|
||||
graphicsbase[1]*meshScaling.getY(),
|
||||
graphicsbase[2]*meshScaling.getZ());
|
||||
#ifdef DEBUG_TRIANGLE_MESH
|
||||
printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
|
||||
#endif //DEBUG_TRIANGLE_MESH
|
||||
}
|
||||
|
||||
m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
|
||||
m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
|
||||
|
||||
m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
|
||||
|
||||
|
||||
#endif//DISABLE_BVH
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
|
||||
{
|
||||
if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
|
||||
{
|
||||
btTriangleMeshShape::setLocalScaling(scaling);
|
||||
if (m_ownsBvh)
|
||||
delete m_bvh;
|
||||
///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work
|
||||
m_bvh = new btOptimizedBvh();
|
||||
//rebuild the bvh...
|
||||
m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef BVH_TRIANGLE_MESH_SHAPE_H
|
||||
#define BVH_TRIANGLE_MESH_SHAPE_H
|
||||
|
||||
#include "btTriangleMeshShape.h"
|
||||
#include "btOptimizedBvh.h"
|
||||
#include "LinearMath/btAlignedAllocator.h"
|
||||
|
||||
///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
|
||||
///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
|
||||
ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape
|
||||
{
|
||||
|
||||
btOptimizedBvh* m_bvh;
|
||||
bool m_useQuantizedAabbCompression;
|
||||
bool m_ownsBvh;
|
||||
bool m_pad[11];////need padding due to alignment
|
||||
|
||||
public:
|
||||
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
btBvhTriangleMeshShape() :btTriangleMeshShape(0),m_bvh(0),m_ownsBvh(false) {};
|
||||
btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true);
|
||||
|
||||
///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
|
||||
btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true);
|
||||
|
||||
virtual ~btBvhTriangleMeshShape();
|
||||
|
||||
|
||||
/*
|
||||
virtual int getShapeType() const
|
||||
{
|
||||
return TRIANGLE_MESH_SHAPE_PROXYTYPE;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||
|
||||
void refitTree();
|
||||
|
||||
///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks
|
||||
void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax);
|
||||
|
||||
//debugging
|
||||
virtual const char* getName()const {return "BVHTRIANGLEMESH";}
|
||||
|
||||
|
||||
virtual void setLocalScaling(const btVector3& scaling);
|
||||
|
||||
btOptimizedBvh* getOptimizedBvh()
|
||||
{
|
||||
return m_bvh;
|
||||
}
|
||||
|
||||
|
||||
void setOptimizedBvh(btOptimizedBvh* bvh)
|
||||
{
|
||||
btAssert(!m_bvh);
|
||||
btAssert(!m_ownsBvh);
|
||||
|
||||
m_bvh = bvh;
|
||||
m_ownsBvh = false;
|
||||
}
|
||||
|
||||
bool usesQuantizedAabbCompression() const
|
||||
{
|
||||
return m_useQuantizedAabbCompression;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
#endif //BVH_TRIANGLE_MESH_SHAPE_H
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "btCapsuleShape.h"
|
||||
|
||||
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
|
||||
#include "LinearMath/btQuaternion.h"
|
||||
|
||||
btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
|
||||
{
|
||||
m_implicitShapeDimensions.setValue(radius,0.5f*height,radius);
|
||||
}
|
||||
|
||||
|
||||
btVector3 btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
|
||||
{
|
||||
|
||||
btVector3 supVec(0,0,0);
|
||||
|
||||
btScalar maxDot(btScalar(-1e30));
|
||||
|
||||
btVector3 vec = vec0;
|
||||
btScalar lenSqr = vec.length2();
|
||||
if (lenSqr < btScalar(0.0001))
|
||||
{
|
||||
vec.setValue(1,0,0);
|
||||
} else
|
||||
{
|
||||
btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
|
||||
vec *= rlen;
|
||||
}
|
||||
|
||||
btVector3 vtx;
|
||||
btScalar newDot;
|
||||
|
||||
btScalar radius = getRadius();
|
||||
|
||||
|
||||
{
|
||||
btVector3 pos(0,getHalfHeight(),0);
|
||||
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
|
||||
newDot = vec.dot(vtx);
|
||||
if (newDot > maxDot)
|
||||
{
|
||||
maxDot = newDot;
|
||||
supVec = vtx;
|
||||
}
|
||||
}
|
||||
{
|
||||
btVector3 pos(0,-getHalfHeight(),0);
|
||||
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
|
||||
newDot = vec.dot(vtx);
|
||||
if (newDot > maxDot)
|
||||
{
|
||||
maxDot = newDot;
|
||||
supVec = vtx;
|
||||
}
|
||||
}
|
||||
|
||||
return supVec;
|
||||
|
||||
}
|
||||
|
||||
void btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
|
||||
{
|
||||
|
||||
|
||||
btScalar radius = getRadius();
|
||||
|
||||
for (int j=0;j<numVectors;j++)
|
||||
{
|
||||
btScalar maxDot(btScalar(-1e30));
|
||||
const btVector3& vec = vectors[j];
|
||||
|
||||
btVector3 vtx;
|
||||
btScalar newDot;
|
||||
{
|
||||
btVector3 pos(0,getHalfHeight(),0);
|
||||
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
|
||||
newDot = vec.dot(vtx);
|
||||
if (newDot > maxDot)
|
||||
{
|
||||
maxDot = newDot;
|
||||
supportVerticesOut[j] = vtx;
|
||||
}
|
||||
}
|
||||
{
|
||||
btVector3 pos(0,-getHalfHeight(),0);
|
||||
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
|
||||
newDot = vec.dot(vtx);
|
||||
if (newDot > maxDot)
|
||||
{
|
||||
maxDot = newDot;
|
||||
supportVerticesOut[j] = vtx;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
|
||||
{
|
||||
//as an approximation, take the inertia of the box that bounds the spheres
|
||||
|
||||
btTransform ident;
|
||||
ident.setIdentity();
|
||||
|
||||
|
||||
btScalar radius = getRadius();
|
||||
|
||||
btVector3 halfExtents(radius,radius+getHalfHeight(),radius);
|
||||
|
||||
btScalar margin = CONVEX_DISTANCE_MARGIN;
|
||||
|
||||
btScalar lx=btScalar(2.)*(halfExtents[0]+margin);
|
||||
btScalar ly=btScalar(2.)*(halfExtents[1]+margin);
|
||||
btScalar lz=btScalar(2.)*(halfExtents[2]+margin);
|
||||
const btScalar x2 = lx*lx;
|
||||
const btScalar y2 = ly*ly;
|
||||
const btScalar z2 = lz*lz;
|
||||
const btScalar scaledmass = mass * btScalar(.08333333);
|
||||
|
||||
inertia[0] = scaledmass * (y2+z2);
|
||||
inertia[1] = scaledmass * (x2+z2);
|
||||
inertia[2] = scaledmass * (x2+y2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef BT_CAPSULE_SHAPE_H
|
||||
#define BT_CAPSULE_SHAPE_H
|
||||
|
||||
#include "btConvexInternalShape.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
|
||||
|
||||
|
||||
///btCapsuleShape represents a capsule around the Y axis
|
||||
///A more general solution that can represent capsules is the btMultiSphereShape
|
||||
class btCapsuleShape : public btConvexInternalShape
|
||||
{
|
||||
|
||||
public:
|
||||
btCapsuleShape(btScalar radius,btScalar height);
|
||||
|
||||
///CollisionShape Interface
|
||||
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
|
||||
|
||||
/// btConvexShape Interface
|
||||
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
|
||||
|
||||
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
|
||||
|
||||
virtual int getShapeType() const { return CAPSULE_SHAPE_PROXYTYPE; }
|
||||
|
||||
virtual const char* getName()const
|
||||
{
|
||||
return "CapsuleShape";
|
||||
}
|
||||
|
||||
btScalar getRadius() const
|
||||
{
|
||||
return m_implicitShapeDimensions.getX();
|
||||
}
|
||||
|
||||
btScalar getHalfHeight() const
|
||||
{
|
||||
return m_implicitShapeDimensions.getY();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //BT_CAPSULE_SHAPE_H
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef COLLISION_MARGIN_H
|
||||
#define COLLISION_MARGIN_H
|
||||
|
||||
//used by Gjk and some other algorithms
|
||||
|
||||
#define CONVEX_DISTANCE_MARGIN btScalar(0.04)// btScalar(0.1)//;//btScalar(0.01)
|
||||
|
||||
|
||||
|
||||
#endif //COLLISION_MARGIN_H
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||
|
||||
|
||||
/*
|
||||
Make sure this dummy function never changes so that it
|
||||
can be used by probes that are checking whether the
|
||||
library is actually installed.
|
||||
*/
|
||||
extern "C" void btBulletCollisionProbe () {}
|
||||
|
||||
|
||||
|
||||
void btCollisionShape::getBoundingSphere(btVector3& center,btScalar& radius) const
|
||||
{
|
||||
btTransform tr;
|
||||
tr.setIdentity();
|
||||
btVector3 aabbMin,aabbMax;
|
||||
|
||||
getAabb(tr,aabbMin,aabbMax);
|
||||
|
||||
radius = (aabbMax-aabbMin).length()*btScalar(0.5);
|
||||
center = (aabbMin+aabbMax)*btScalar(0.5);
|
||||
}
|
||||
|
||||
btScalar btCollisionShape::getAngularMotionDisc() const
|
||||
{
|
||||
btVector3 center;
|
||||
btScalar disc;
|
||||
getBoundingSphere(center,disc);
|
||||
disc += (center).length();
|
||||
return disc;
|
||||
}
|
||||
|
||||
void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax)
|
||||
{
|
||||
//start with static aabb
|
||||
getAabb(curTrans,temporalAabbMin,temporalAabbMax);
|
||||
|
||||
btScalar temporalAabbMaxx = temporalAabbMax.getX();
|
||||
btScalar temporalAabbMaxy = temporalAabbMax.getY();
|
||||
btScalar temporalAabbMaxz = temporalAabbMax.getZ();
|
||||
btScalar temporalAabbMinx = temporalAabbMin.getX();
|
||||
btScalar temporalAabbMiny = temporalAabbMin.getY();
|
||||
btScalar temporalAabbMinz = temporalAabbMin.getZ();
|
||||
|
||||
// add linear motion
|
||||
btVector3 linMotion = linvel*timeStep;
|
||||
//todo: simd would have a vector max/min operation, instead of per-element access
|
||||
if (linMotion.x() > btScalar(0.))
|
||||
temporalAabbMaxx += linMotion.x();
|
||||
else
|
||||
temporalAabbMinx += linMotion.x();
|
||||
if (linMotion.y() > btScalar(0.))
|
||||
temporalAabbMaxy += linMotion.y();
|
||||
else
|
||||
temporalAabbMiny += linMotion.y();
|
||||
if (linMotion.z() > btScalar(0.))
|
||||
temporalAabbMaxz += linMotion.z();
|
||||
else
|
||||
temporalAabbMinz += linMotion.z();
|
||||
|
||||
//add conservative angular motion
|
||||
btScalar angularMotion = angvel.length() * getAngularMotionDisc() * timeStep;
|
||||
btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion);
|
||||
temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz);
|
||||
temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz);
|
||||
|
||||
temporalAabbMin -= angularMotion3d;
|
||||
temporalAabbMax += angularMotion3d;
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef COLLISION_SHAPE_H
|
||||
#define COLLISION_SHAPE_H
|
||||
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "LinearMath/btMatrix3x3.h"
|
||||
#include "LinearMath/btPoint3.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types
|
||||
|
||||
///btCollisionShape provides interface for collision shapes that can be shared among btCollisionObjects.
|
||||
class btCollisionShape
|
||||
{
|
||||
public:
|
||||
|
||||
btCollisionShape()
|
||||
{
|
||||
}
|
||||
virtual ~btCollisionShape()
|
||||
{
|
||||
}
|
||||
|
||||
///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
|
||||
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
|
||||
|
||||
virtual void getBoundingSphere(btVector3& center,btScalar& radius) const;
|
||||
|
||||
///getAngularMotionDisc returns the maximus radius needed for Conservative Advancement to handle time-of-impact with rotations.
|
||||
virtual btScalar getAngularMotionDisc() const;
|
||||
|
||||
|
||||
///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep)
|
||||
///result is conservative
|
||||
void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax);
|
||||
|
||||
#ifndef __SPU__
|
||||
|
||||
SIMD_FORCE_INLINE bool isPolyhedral() const
|
||||
{
|
||||
return btBroadphaseProxy::isPolyhedral(getShapeType());
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE bool isConvex() const
|
||||
{
|
||||
return btBroadphaseProxy::isConvex(getShapeType());
|
||||
}
|
||||
SIMD_FORCE_INLINE bool isConcave() const
|
||||
{
|
||||
return btBroadphaseProxy::isConcave(getShapeType());
|
||||
}
|
||||
SIMD_FORCE_INLINE bool isCompound() const
|
||||
{
|
||||
return btBroadphaseProxy::isCompound(getShapeType());
|
||||
}
|
||||
|
||||
///isInfinite is used to catch simulation error (aabb check)
|
||||
SIMD_FORCE_INLINE bool isInfinite() const
|
||||
{
|
||||
return btBroadphaseProxy::isInfinite(getShapeType());
|
||||
}
|
||||
|
||||
virtual int getShapeType() const=0;
|
||||
virtual void setLocalScaling(const btVector3& scaling) =0;
|
||||
virtual const btVector3& getLocalScaling() const =0;
|
||||
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0;
|
||||
|
||||
|
||||
//debugging support
|
||||
virtual const char* getName()const =0 ;
|
||||
#endif //__SPU__
|
||||
|
||||
|
||||
|
||||
virtual void setMargin(btScalar margin) = 0;
|
||||
virtual btScalar getMargin() const = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif //COLLISION_SHAPE_H
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btCompoundShape.h"
|
||||
|
||||
|
||||
#include "btCollisionShape.h"
|
||||
|
||||
|
||||
btCompoundShape::btCompoundShape()
|
||||
:m_localAabbMin(btScalar(1e30),btScalar(1e30),btScalar(1e30)),
|
||||
m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)),
|
||||
m_aabbTree(0),
|
||||
m_collisionMargin(btScalar(0.)),
|
||||
m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
btCompoundShape::~btCompoundShape()
|
||||
{
|
||||
}
|
||||
|
||||
void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
|
||||
{
|
||||
//m_childTransforms.push_back(localTransform);
|
||||
//m_childShapes.push_back(shape);
|
||||
btCompoundShapeChild child;
|
||||
child.m_transform = localTransform;
|
||||
child.m_childShape = shape;
|
||||
child.m_childShapeType = shape->getShapeType();
|
||||
child.m_childMargin = shape->getMargin();
|
||||
|
||||
m_children.push_back(child);
|
||||
|
||||
//extend the local aabbMin/aabbMax
|
||||
btVector3 localAabbMin,localAabbMax;
|
||||
shape->getAabb(localTransform,localAabbMin,localAabbMax);
|
||||
for (int i=0;i<3;i++)
|
||||
{
|
||||
if (m_localAabbMin[i] > localAabbMin[i])
|
||||
{
|
||||
m_localAabbMin[i] = localAabbMin[i];
|
||||
}
|
||||
if (m_localAabbMax[i] < localAabbMax[i])
|
||||
{
|
||||
m_localAabbMax[i] = localAabbMax[i];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
|
||||
void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
|
||||
{
|
||||
btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
|
||||
btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
|
||||
|
||||
btMatrix3x3 abs_b = trans.getBasis().absolute();
|
||||
|
||||
btPoint3 center = trans(localCenter);
|
||||
|
||||
btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
|
||||
abs_b[1].dot(localHalfExtents),
|
||||
abs_b[2].dot(localHalfExtents));
|
||||
extent += btVector3(getMargin(),getMargin(),getMargin());
|
||||
|
||||
aabbMin = center - extent;
|
||||
aabbMax = center + extent;
|
||||
}
|
||||
|
||||
void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
|
||||
{
|
||||
//approximation: take the inertia from the aabb for now
|
||||
btTransform ident;
|
||||
ident.setIdentity();
|
||||
btVector3 aabbMin,aabbMax;
|
||||
getAabb(ident,aabbMin,aabbMax);
|
||||
|
||||
btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
|
||||
|
||||
btScalar lx=btScalar(2.)*(halfExtents.x());
|
||||
btScalar ly=btScalar(2.)*(halfExtents.y());
|
||||
btScalar lz=btScalar(2.)*(halfExtents.z());
|
||||
|
||||
inertia[0] = mass/(btScalar(12.0)) * (ly*ly + lz*lz);
|
||||
inertia[1] = mass/(btScalar(12.0)) * (lx*lx + lz*lz);
|
||||
inertia[2] = mass/(btScalar(12.0)) * (lx*lx + ly*ly);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef COMPOUND_SHAPE_H
|
||||
#define COMPOUND_SHAPE_H
|
||||
|
||||
#include "btCollisionShape.h"
|
||||
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "LinearMath/btMatrix3x3.h"
|
||||
#include "btCollisionMargin.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
|
||||
class btOptimizedBvh;
|
||||
|
||||
ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild
|
||||
{
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
btTransform m_transform;
|
||||
btCollisionShape* m_childShape;
|
||||
int m_childShapeType;
|
||||
btScalar m_childMargin;
|
||||
};
|
||||
|
||||
/// btCompoundShape allows to store multiple other btCollisionShapes
|
||||
/// This allows for concave collision objects. This is more general then the Static Concave btTriangleMeshShape.
|
||||
ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape
|
||||
{
|
||||
//btAlignedObjectArray<btTransform> m_childTransforms;
|
||||
//btAlignedObjectArray<btCollisionShape*> m_childShapes;
|
||||
btAlignedObjectArray<btCompoundShapeChild> m_children;
|
||||
btVector3 m_localAabbMin;
|
||||
btVector3 m_localAabbMax;
|
||||
|
||||
btOptimizedBvh* m_aabbTree;
|
||||
|
||||
public:
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
btCompoundShape();
|
||||
|
||||
virtual ~btCompoundShape();
|
||||
|
||||
void addChildShape(const btTransform& localTransform,btCollisionShape* shape);
|
||||
|
||||
int getNumChildShapes() const
|
||||
{
|
||||
return int (m_children.size());
|
||||
}
|
||||
|
||||
btCollisionShape* getChildShape(int index)
|
||||
{
|
||||
return m_children[index].m_childShape;
|
||||
}
|
||||
const btCollisionShape* getChildShape(int index) const
|
||||
{
|
||||
return m_children[index].m_childShape;
|
||||
}
|
||||
|
||||
btTransform getChildTransform(int index)
|
||||
{
|
||||
return m_children[index].m_transform;
|
||||
}
|
||||
const btTransform getChildTransform(int index) const
|
||||
{
|
||||
return m_children[index].m_transform;
|
||||
}
|
||||
|
||||
|
||||
btCompoundShapeChild* getChildList()
|
||||
{
|
||||
return &m_children[0];
|
||||
}
|
||||
|
||||
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
|
||||
void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
|
||||
|
||||
|
||||
virtual void setLocalScaling(const btVector3& scaling)
|
||||
{
|
||||
m_localScaling = scaling;
|
||||
}
|
||||
virtual const btVector3& getLocalScaling() const
|
||||
{
|
||||
return m_localScaling;
|
||||
}
|
||||
|
||||
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
|
||||
|
||||
virtual int getShapeType() const { return COMPOUND_SHAPE_PROXYTYPE;}
|
||||
|
||||
virtual void setMargin(btScalar margin)
|
||||
{
|
||||
m_collisionMargin = margin;
|
||||
}
|
||||
virtual btScalar getMargin() const
|
||||
{
|
||||
return m_collisionMargin;
|
||||
}
|
||||
virtual const char* getName()const
|
||||
{
|
||||
return "Compound";
|
||||
}
|
||||
|
||||
//this is optional, but should make collision queries faster, by culling non-overlapping nodes
|
||||
void createAabbTreeFromChildren();
|
||||
|
||||
const btOptimizedBvh* getAabbTree() const
|
||||
{
|
||||
return m_aabbTree;
|
||||
}
|
||||
|
||||
private:
|
||||
btScalar m_collisionMargin;
|
||||
protected:
|
||||
btVector3 m_localScaling;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //COMPOUND_SHAPE_H
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "btConcaveShape.h"
|
||||
|
||||
btConcaveShape::btConcaveShape() : m_collisionMargin(btScalar(0.))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
btConcaveShape::~btConcaveShape()
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef CONCAVE_SHAPE_H
|
||||
#define CONCAVE_SHAPE_H
|
||||
|
||||
#include "btCollisionShape.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
|
||||
#include "btTriangleCallback.h"
|
||||
|
||||
|
||||
///Concave shape proves an interface concave shapes that can produce triangles that overlapping a given AABB.
|
||||
///Static triangle mesh, infinite plane, height field/landscapes are example that implement this interface.
|
||||
class btConcaveShape : public btCollisionShape
|
||||
{
|
||||
protected:
|
||||
btScalar m_collisionMargin;
|
||||
|
||||
public:
|
||||
btConcaveShape();
|
||||
|
||||
virtual ~btConcaveShape();
|
||||
|
||||
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const = 0;
|
||||
|
||||
virtual btScalar getMargin() const {
|
||||
return m_collisionMargin;
|
||||
}
|
||||
virtual void setMargin(btScalar collisionMargin)
|
||||
{
|
||||
m_collisionMargin = collisionMargin;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //CONCAVE_SHAPE_H
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btConeShape.h"
|
||||
#include "LinearMath/btPoint3.h"
|
||||
|
||||
|
||||
|
||||
btConeShape::btConeShape (btScalar radius,btScalar height):
|
||||
m_radius (radius),
|
||||
m_height(height)
|
||||
{
|
||||
setConeUpIndex(1);
|
||||
btVector3 halfExtents;
|
||||
m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height));
|
||||
}
|
||||
|
||||
btConeShapeZ::btConeShapeZ (btScalar radius,btScalar height):
|
||||
btConeShape(radius,height)
|
||||
{
|
||||
setConeUpIndex(2);
|
||||
}
|
||||
|
||||
btConeShapeX::btConeShapeX (btScalar radius,btScalar height):
|
||||
btConeShape(radius,height)
|
||||
{
|
||||
setConeUpIndex(0);
|
||||
}
|
||||
|
||||
///choose upAxis index
|
||||
void btConeShape::setConeUpIndex(int upIndex)
|
||||
{
|
||||
switch (upIndex)
|
||||
{
|
||||
case 0:
|
||||
m_coneIndices[0] = 1;
|
||||
m_coneIndices[1] = 0;
|
||||
m_coneIndices[2] = 2;
|
||||
break;
|
||||
case 1:
|
||||
m_coneIndices[0] = 0;
|
||||
m_coneIndices[1] = 1;
|
||||
m_coneIndices[2] = 2;
|
||||
break;
|
||||
case 2:
|
||||
m_coneIndices[0] = 0;
|
||||
m_coneIndices[1] = 2;
|
||||
m_coneIndices[2] = 1;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
};
|
||||
}
|
||||
|
||||
btVector3 btConeShape::coneLocalSupport(const btVector3& v) const
|
||||
{
|
||||
|
||||
btScalar halfHeight = m_height * btScalar(0.5);
|
||||
|
||||
if (v[m_coneIndices[1]] > v.length() * m_sinAngle)
|
||||
{
|
||||
btVector3 tmp;
|
||||
|
||||
tmp[m_coneIndices[0]] = btScalar(0.);
|
||||
tmp[m_coneIndices[1]] = halfHeight;
|
||||
tmp[m_coneIndices[2]] = btScalar(0.);
|
||||
return tmp;
|
||||
}
|
||||
else {
|
||||
btScalar s = btSqrt(v[m_coneIndices[0]] * v[m_coneIndices[0]] + v[m_coneIndices[2]] * v[m_coneIndices[2]]);
|
||||
if (s > SIMD_EPSILON) {
|
||||
btScalar d = m_radius / s;
|
||||
btVector3 tmp;
|
||||
tmp[m_coneIndices[0]] = v[m_coneIndices[0]] * d;
|
||||
tmp[m_coneIndices[1]] = -halfHeight;
|
||||
tmp[m_coneIndices[2]] = v[m_coneIndices[2]] * d;
|
||||
return tmp;
|
||||
}
|
||||
else {
|
||||
btVector3 tmp;
|
||||
tmp[m_coneIndices[0]] = btScalar(0.);
|
||||
tmp[m_coneIndices[1]] = -halfHeight;
|
||||
tmp[m_coneIndices[2]] = btScalar(0.);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
btVector3 btConeShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
|
||||
{
|
||||
return coneLocalSupport(vec);
|
||||
}
|
||||
|
||||
void btConeShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
|
||||
{
|
||||
for (int i=0;i<numVectors;i++)
|
||||
{
|
||||
const btVector3& vec = vectors[i];
|
||||
supportVerticesOut[i] = coneLocalSupport(vec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
btVector3 btConeShape::localGetSupportingVertex(const btVector3& vec) const
|
||||
{
|
||||
btVector3 supVertex = coneLocalSupport(vec);
|
||||
if ( getMargin()!=btScalar(0.) )
|
||||
{
|
||||
btVector3 vecnorm = vec;
|
||||
if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
|
||||
{
|
||||
vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
|
||||
}
|
||||
vecnorm.normalize();
|
||||
supVertex+= getMargin() * vecnorm;
|
||||
}
|
||||
return supVertex;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef CONE_MINKOWSKI_H
|
||||
#define CONE_MINKOWSKI_H
|
||||
|
||||
#include "btConvexInternalShape.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
|
||||
|
||||
///btConeShape implements a Cone shape, around the Y axis
|
||||
class btConeShape : public btConvexInternalShape
|
||||
|
||||
{
|
||||
|
||||
btScalar m_sinAngle;
|
||||
btScalar m_radius;
|
||||
btScalar m_height;
|
||||
int m_coneIndices[3];
|
||||
btVector3 coneLocalSupport(const btVector3& v) const;
|
||||
|
||||
|
||||
public:
|
||||
btConeShape (btScalar radius,btScalar height);
|
||||
|
||||
virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
|
||||
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
|
||||
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
|
||||
|
||||
btScalar getRadius() const { return m_radius;}
|
||||
btScalar getHeight() const { return m_height;}
|
||||
|
||||
|
||||
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const
|
||||
{
|
||||
btTransform identity;
|
||||
identity.setIdentity();
|
||||
btVector3 aabbMin,aabbMax;
|
||||
getAabb(identity,aabbMin,aabbMax);
|
||||
|
||||
btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
|
||||
|
||||
btScalar margin = getMargin();
|
||||
|
||||
btScalar lx=btScalar(2.)*(halfExtents.x()+margin);
|
||||
btScalar ly=btScalar(2.)*(halfExtents.y()+margin);
|
||||
btScalar lz=btScalar(2.)*(halfExtents.z()+margin);
|
||||
const btScalar x2 = lx*lx;
|
||||
const btScalar y2 = ly*ly;
|
||||
const btScalar z2 = lz*lz;
|
||||
const btScalar scaledmass = mass * btScalar(0.08333333);
|
||||
|
||||
inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
|
||||
|
||||
// inertia.x() = scaledmass * (y2+z2);
|
||||
// inertia.y() = scaledmass * (x2+z2);
|
||||
// inertia.z() = scaledmass * (x2+y2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual int getShapeType() const { return CONE_SHAPE_PROXYTYPE; }
|
||||
|
||||
virtual const char* getName()const
|
||||
{
|
||||
return "Cone";
|
||||
}
|
||||
|
||||
///choose upAxis index
|
||||
void setConeUpIndex(int upIndex);
|
||||
|
||||
int getConeUpIndex() const
|
||||
{
|
||||
return m_coneIndices[1];
|
||||
}
|
||||
};
|
||||
|
||||
///btConeShape implements a Cone shape, around the X axis
|
||||
class btConeShapeX : public btConeShape
|
||||
{
|
||||
public:
|
||||
btConeShapeX(btScalar radius,btScalar height);
|
||||
};
|
||||
|
||||
///btConeShapeZ implements a Cone shape, around the Z axis
|
||||
class btConeShapeZ : public btConeShape
|
||||
{
|
||||
public:
|
||||
btConeShapeZ(btScalar radius,btScalar height);
|
||||
};
|
||||
#endif //CONE_MINKOWSKI_H
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "btConvexHullShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
|
||||
|
||||
#include "LinearMath/btQuaternion.h"
|
||||
|
||||
|
||||
|
||||
btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int stride)
|
||||
{
|
||||
m_points.resize(numPoints);
|
||||
|
||||
unsigned char* pointsBaseAddress = (unsigned char*)points;
|
||||
|
||||
for (int i=0;i<numPoints;i++)
|
||||
{
|
||||
btPoint3* point = (btPoint3*)(pointsBaseAddress + i*stride);
|
||||
m_points[i] = point[0];
|
||||
}
|
||||
|
||||
recalcLocalAabb();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void btConvexHullShape::addPoint(const btPoint3& point)
|
||||
{
|
||||
m_points.push_back(point);
|
||||
recalcLocalAabb();
|
||||
|
||||
}
|
||||
|
||||
btVector3 btConvexHullShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
|
||||
{
|
||||
btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
|
||||
btScalar newDot,maxDot = btScalar(-1e30);
|
||||
|
||||
btVector3 vec = vec0;
|
||||
btScalar lenSqr = vec.length2();
|
||||
if (lenSqr < btScalar(0.0001))
|
||||
{
|
||||
vec.setValue(1,0,0);
|
||||
} else
|
||||
{
|
||||
btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
|
||||
vec *= rlen;
|
||||
}
|
||||
|
||||
|
||||
for (int i=0;i<m_points.size();i++)
|
||||
{
|
||||
btPoint3 vtx = m_points[i] * m_localScaling;
|
||||
|
||||
newDot = vec.dot(vtx);
|
||||
if (newDot > maxDot)
|
||||
{
|
||||
maxDot = newDot;
|
||||
supVec = vtx;
|
||||
}
|
||||
}
|
||||
return supVec;
|
||||
}
|
||||
|
||||
void btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
|
||||
{
|
||||
btScalar newDot;
|
||||
//use 'w' component of supportVerticesOut?
|
||||
{
|
||||
for (int i=0;i<numVectors;i++)
|
||||
{
|
||||
supportVerticesOut[i][3] = btScalar(-1e30);
|
||||
}
|
||||
}
|
||||
for (int i=0;i<m_points.size();i++)
|
||||
{
|
||||
btPoint3 vtx = m_points[i] * m_localScaling;
|
||||
|
||||
for (int j=0;j<numVectors;j++)
|
||||
{
|
||||
const btVector3& vec = vectors[j];
|
||||
|
||||
newDot = vec.dot(vtx);
|
||||
if (newDot > supportVerticesOut[j][3])
|
||||
{
|
||||
//WARNING: don't swap next lines, the w component would get overwritten!
|
||||
supportVerticesOut[j] = vtx;
|
||||
supportVerticesOut[j][3] = newDot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
btVector3 btConvexHullShape::localGetSupportingVertex(const btVector3& vec)const
|
||||
{
|
||||
btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
|
||||
|
||||
if ( getMargin()!=btScalar(0.) )
|
||||
{
|
||||
btVector3 vecnorm = vec;
|
||||
if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
|
||||
{
|
||||
vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
|
||||
}
|
||||
vecnorm.normalize();
|
||||
supVertex+= getMargin() * vecnorm;
|
||||
}
|
||||
return supVertex;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
|
||||
//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
|
||||
int btConvexHullShape::getNumVertices() const
|
||||
{
|
||||
return m_points.size();
|
||||
}
|
||||
|
||||
int btConvexHullShape::getNumEdges() const
|
||||
{
|
||||
return m_points.size();
|
||||
}
|
||||
|
||||
void btConvexHullShape::getEdge(int i,btPoint3& pa,btPoint3& pb) const
|
||||
{
|
||||
|
||||
int index0 = i%m_points.size();
|
||||
int index1 = (i+1)%m_points.size();
|
||||
pa = m_points[index0]*m_localScaling;
|
||||
pb = m_points[index1]*m_localScaling;
|
||||
}
|
||||
|
||||
void btConvexHullShape::getVertex(int i,btPoint3& vtx) const
|
||||
{
|
||||
vtx = m_points[i]*m_localScaling;
|
||||
}
|
||||
|
||||
int btConvexHullShape::getNumPlanes() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void btConvexHullShape::getPlane(btVector3& ,btPoint3& ,int ) const
|
||||
{
|
||||
|
||||
btAssert(0);
|
||||
}
|
||||
|
||||
//not yet
|
||||
bool btConvexHullShape::isInside(const btPoint3& ,btScalar ) const
|
||||
{
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef CONVEX_HULL_SHAPE_H
|
||||
#define CONVEX_HULL_SHAPE_H
|
||||
|
||||
#include "btPolyhedralConvexShape.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
|
||||
///ConvexHullShape implements an implicit (getSupportingVertex) Convex Hull of a Point Cloud (vertices)
|
||||
///No connectivity is needed. localGetSupportingVertex iterates linearly though all vertices.
|
||||
///on modern hardware, due to cache coherency this isn't that bad. Complex algorithms tend to trash the cash.
|
||||
///(memory is much slower then the cpu)
|
||||
ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexShape
|
||||
{
|
||||
btAlignedObjectArray<btPoint3> m_points;
|
||||
|
||||
public:
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
|
||||
///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory.
|
||||
///It is easier to not pass any points in the constructor, and just add one point at a time, using addPoint.
|
||||
///btConvexHullShape make an internal copy of the points.
|
||||
btConvexHullShape(const btScalar* points=0,int numPoints=0, int stride=sizeof(btPoint3));
|
||||
|
||||
void addPoint(const btPoint3& point);
|
||||
|
||||
btPoint3* getPoints()
|
||||
{
|
||||
return &m_points[0];
|
||||
}
|
||||
|
||||
int getNumPoints()
|
||||
{
|
||||
return m_points.size();
|
||||
}
|
||||
|
||||
virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
|
||||
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
|
||||
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
|
||||
|
||||
|
||||
virtual int getShapeType()const { return CONVEX_HULL_SHAPE_PROXYTYPE; }
|
||||
|
||||
//debugging
|
||||
virtual const char* getName()const {return "Convex";}
|
||||
|
||||
|
||||
virtual int getNumVertices() const;
|
||||
virtual int getNumEdges() const;
|
||||
virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const;
|
||||
virtual void getVertex(int i,btPoint3& vtx) const;
|
||||
virtual int getNumPlanes() const;
|
||||
virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const;
|
||||
virtual bool isInside(const btPoint3& pt,btScalar tolerance) const;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //CONVEX_HULL_SHAPE_H
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "btConvexInternalShape.h"
|
||||
|
||||
|
||||
btConvexInternalShape::btConvexInternalShape()
|
||||
: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
|
||||
m_collisionMargin(CONVEX_DISTANCE_MARGIN)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void btConvexInternalShape::setLocalScaling(const btVector3& scaling)
|
||||
{
|
||||
m_localScaling = scaling;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const
|
||||
{
|
||||
|
||||
btScalar margin = getMargin();
|
||||
for (int i=0;i<3;i++)
|
||||
{
|
||||
btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
|
||||
vec[i] = btScalar(1.);
|
||||
|
||||
btVector3 sv = localGetSupportingVertex(vec*trans.getBasis());
|
||||
|
||||
btVector3 tmp = trans(sv);
|
||||
maxAabb[i] = tmp[i]+margin;
|
||||
vec[i] = btScalar(-1.);
|
||||
tmp = trans(localGetSupportingVertex(vec*trans.getBasis()));
|
||||
minAabb[i] = tmp[i]-margin;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const
|
||||
{
|
||||
#ifndef __SPU__
|
||||
|
||||
btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
|
||||
|
||||
if ( getMargin()!=btScalar(0.) )
|
||||
{
|
||||
btVector3 vecnorm = vec;
|
||||
if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
|
||||
{
|
||||
vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
|
||||
}
|
||||
vecnorm.normalize();
|
||||
supVertex+= getMargin() * vecnorm;
|
||||
}
|
||||
return supVertex;
|
||||
|
||||
#else
|
||||
return btVector3(0,0,0);
|
||||
#endif //__SPU__
|
||||
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue