Merge pull request #701 from erwincoumans/master

Remove many memory leaks/technical debt in example code.
This commit is contained in:
erwincoumans
2016-07-16 22:01:19 -07:00
committed by GitHub
35 changed files with 803 additions and 418 deletions

Binary file not shown.

View File

@@ -63,7 +63,7 @@ struct CommonMultiBodyBase : public CommonExampleInterface
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
m_broadphase = new btDbvtBroadphase();
m_broadphase = new btDbvtBroadphase();//btSimpleBroadphase();
m_solver = new btMultiBodyConstraintSolver;
@@ -97,6 +97,20 @@ struct CommonMultiBodyBase : public CommonExampleInterface
{
m_dynamicsWorld->removeConstraint(m_dynamicsWorld->getConstraint(i));
}
for (i = m_dynamicsWorld->getNumMultiBodyConstraints() - 1; i >= 0; i--)
{
btMultiBodyConstraint* mbc = m_dynamicsWorld->getMultiBodyConstraint(i);
m_dynamicsWorld->removeMultiBodyConstraint(mbc);
delete mbc;
}
for (i = m_dynamicsWorld->getNumMultibodies() - 1; i >= 0; i--)
{
btMultiBody* mb = m_dynamicsWorld->getMultiBody(i);
m_dynamicsWorld->removeMultiBody(mb);
delete mb;
}
for (i = m_dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--)
{
btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];

View File

@@ -21,6 +21,7 @@ void GraphingTexture::destroy()
m_height=0;
glDeleteTextures(1,(GLuint*)&m_textureId);
m_textureId=0;
}
bool GraphingTexture::create(int texWidth, int texHeight)

View File

@@ -44,7 +44,7 @@ public:
CProfileIterator* profIter;
class MyMenuItems* m_menuItems;
MyProfileWindow ( Gwen::Controls::Base* pParent)
: Gwen::Controls::WindowControl( pParent ),
profIter(0)
@@ -83,6 +83,12 @@ public:
}
virtual ~MyProfileWindow()
{
delete m_node;
delete m_ctrl;
}
float dumpRecursive(CProfileIterator* profileIterator, Gwen::Controls::TreeNode* parentNode)
{
@@ -266,11 +272,16 @@ public:
MyProfileWindow* setupProfileWindow(GwenInternalData* data)
{
MyMenuItems* menuItems = new MyMenuItems;
MyProfileWindow* profWindow = new MyProfileWindow(data->pCanvas);
//profWindow->SetHidden(true);
profWindow->profIter = CProfileManager::Get_Iterator();
profWindow->m_menuItems = menuItems;
//profWindow->profIter = CProfileManager::Get_Iterator();
data->m_viewMenu->GetMenu()->AddItem( L"Profiler", menuItems,(Gwen::Event::Handler::Function)&MyMenuItems::MenuItemSelect);
menuItems->m_profWindow = profWindow;
return profWindow;
}
@@ -290,5 +301,6 @@ void profileWindowSetVisible(MyProfileWindow* window, bool visible)
}
void destroyProfileWindow(MyProfileWindow* window)
{
CProfileManager::Release_Iterator(window->profIter);
delete window;
}

View File

@@ -45,7 +45,10 @@ struct GwenInternalData
Gwen::Controls::ListBox* m_TextOutput;
Gwen::Controls::Label* m_exampleInfoGroupBox;
Gwen::Controls::ListBox* m_exampleInfoTextOutput;
struct MyTestMenuBar* m_menubar;
Gwen::Controls::StatusBar* m_bar;
Gwen::Controls::ScrollControl* m_windowRight;
Gwen::Controls::TabControl* m_tab;
int m_curYposition;

View File

@@ -17,6 +17,83 @@ GwenUserInterface::GwenUserInterface()
}
class MyMenuItems : public Gwen::Controls::Base
{
public:
b3FileOpenCallback m_fileOpenCallback;
b3QuitCallback m_quitCallback;
MyMenuItems() :Gwen::Controls::Base(0), m_fileOpenCallback(0)
{
}
void myQuitApp(Gwen::Controls::Base* pControl)
{
if (m_quitCallback)
{
(*m_quitCallback)();
}
}
void fileOpen(Gwen::Controls::Base* pControl)
{
if (m_fileOpenCallback)
{
(*m_fileOpenCallback)();
}
}
};
struct MyTestMenuBar : public Gwen::Controls::MenuStrip
{
Gwen::Controls::MenuItem* m_fileMenu;
Gwen::Controls::MenuItem* m_viewMenu;
MyMenuItems* m_menuItems;
MyTestMenuBar(Gwen::Controls::Base* pParent)
:Gwen::Controls::MenuStrip(pParent)
{
// Gwen::Controls::MenuStrip* menu = new Gwen::Controls::MenuStrip( pParent );
{
m_menuItems = new MyMenuItems();
m_menuItems->m_fileOpenCallback = 0;
m_menuItems->m_quitCallback = 0;
m_fileMenu = AddItem(L"File");
m_fileMenu->GetMenu()->AddItem(L"Open", m_menuItems, (Gwen::Event::Handler::Function)&MyMenuItems::fileOpen);
m_fileMenu->GetMenu()->AddItem(L"Quit", m_menuItems, (Gwen::Event::Handler::Function)&MyMenuItems::myQuitApp);
m_viewMenu = AddItem(L"View");
}
}
virtual ~MyTestMenuBar()
{
delete m_menuItems;
}
};
void GwenUserInterface::exit()
{
//m_data->m_menubar->RemoveAllChildren();
delete m_data->m_tab;
delete m_data->m_windowRight;
delete m_data->m_leftStatusBar;
delete m_data->m_TextOutput;
delete m_data->m_rightStatusBar;
delete m_data->m_bar;
delete m_data->m_menubar;
m_data->m_menubar = 0;
delete m_data->pCanvas;
m_data->pCanvas = 0;
}
GwenUserInterface::~GwenUserInterface()
{
for (int i=0;i<m_data->m_handlers.size();i++)
@@ -26,72 +103,15 @@ GwenUserInterface::~GwenUserInterface()
m_data->m_handlers.clear();
delete m_data->pCanvas;
delete m_data;
}
class MyMenuItems : public Gwen::Controls::Base
{
public:
b3FileOpenCallback m_fileOpenCallback;
b3QuitCallback m_quitCallback;
MyMenuItems() :Gwen::Controls::Base(0),m_fileOpenCallback(0)
{
}
void myQuitApp( Gwen::Controls::Base* pControl )
{
if (m_quitCallback)
{
(*m_quitCallback)();
}
}
void fileOpen( Gwen::Controls::Base* pControl )
{
if (m_fileOpenCallback)
{
(*m_fileOpenCallback)();
}
}
};
struct MyTestMenuBar : public Gwen::Controls::MenuStrip
{
Gwen::Controls::MenuItem* m_fileMenu;
Gwen::Controls::MenuItem* m_viewMenu;
MyMenuItems* m_menuItems;
MyTestMenuBar(Gwen::Controls::Base* pParent)
:Gwen::Controls::MenuStrip(pParent)
{
// Gwen::Controls::MenuStrip* menu = new Gwen::Controls::MenuStrip( pParent );
{
m_menuItems = new MyMenuItems();
m_menuItems->m_fileOpenCallback = 0;
m_menuItems->m_quitCallback = 0;
m_fileMenu = AddItem( L"File" );
m_fileMenu->GetMenu()->AddItem(L"Open",m_menuItems,(Gwen::Event::Handler::Function)&MyMenuItems::fileOpen);
m_fileMenu->GetMenu()->AddItem(L"Quit",m_menuItems,(Gwen::Event::Handler::Function)&MyMenuItems::myQuitApp);
m_viewMenu = AddItem( L"View" );
}
}
};
void GwenUserInterface::resize(int width, int height)
{
@@ -232,6 +252,7 @@ void GwenUserInterface::setStatusBarMessage(const char* message, bool isLeft)
}
}
void GwenUserInterface::registerFileOpenCallback(b3FileOpenCallback callback)
{
m_data->m_menuItems->m_fileOpenCallback = callback;
@@ -249,35 +270,43 @@ void GwenUserInterface::init(int width, int height,Gwen::Renderer::Base* rendere
m_data->pRenderer = renderer;//new GwenOpenGL3CoreRenderer(m_data->m_primRenderer,stash,width,height,retinaScale);
m_data->skin.SetRender( m_data->pRenderer );
m_data->pCanvas= new Gwen::Controls::Canvas( &m_data->skin );
m_data->pCanvas->SetSize( width,height);
m_data->pCanvas->SetDrawBackground( false);
m_data->pCanvas->SetBackgroundColor( Gwen::Color( 150, 170, 170, 255 ) );
MyTestMenuBar* menubar = new MyTestMenuBar(m_data->pCanvas);
m_data->m_viewMenu = menubar->m_viewMenu;
m_data->m_menuItems = menubar->m_menuItems;
m_data->m_menubar = menubar;
Gwen::Controls::StatusBar* bar = new Gwen::Controls::StatusBar(m_data->pCanvas);
m_data->m_bar = bar;
m_data->m_rightStatusBar = new Gwen::Controls::Label( bar );
m_data->m_rightStatusBar->SetWidth(width/2);
//m_data->m_rightStatusBar->SetText( L"Label Added to Right" );
bar->AddControl( m_data->m_rightStatusBar, true );
m_data->m_TextOutput = new Gwen::Controls::ListBox( m_data->pCanvas );
m_data->m_TextOutput->Dock( Gwen::Pos::Bottom );
m_data->m_TextOutput->SetHeight( 100 );
m_data->m_leftStatusBar = new Gwen::Controls::Label( bar );
//m_data->m_leftStatusBar->SetText( L"Label Added to Left" );
m_data->m_leftStatusBar->SetWidth(width/2);
bar->AddControl( m_data->m_leftStatusBar,false);
//Gwen::KeyboardFocus
/*Gwen::Controls::GroupBox* box = new Gwen::Controls::GroupBox(m_data->pCanvas);
box->SetText("text");
@@ -289,11 +318,14 @@ void GwenUserInterface::init(int width, int height,Gwen::Renderer::Base* rendere
windowRight->SetWidth(250);
windowRight->SetHeight(250);
windowRight->SetScroll(false,true);
m_data->m_windowRight = windowRight;
//windowLeft->SetSkin(
Gwen::Controls::TabControl* tab = new Gwen::Controls::TabControl(windowRight);
m_data->m_tab = tab;
//tab->SetHeight(300);
tab->SetWidth(240);
@@ -304,7 +336,8 @@ void GwenUserInterface::init(int width, int height,Gwen::Renderer::Base* rendere
Gwen::UnicodeString str1(L"Params");
m_data->m_demoPage = tab->AddPage(str1);
@@ -348,7 +381,7 @@ void GwenUserInterface::init(int width, int height,Gwen::Renderer::Base* rendere
//windowLeft->SetClosable(false);
// windowLeft->SetShouldDrawBackground(true);
windowLeft->SetTabable(true);
Gwen::Controls::TabControl* explorerTab = new Gwen::Controls::TabControl(windowLeft);
//tab->SetHeight(300);
@@ -388,7 +421,6 @@ void GwenUserInterface::init(int width, int height,Gwen::Renderer::Base* rendere
m_data->m_exampleInfoGroupBox->SetText("Example Description");
m_data->m_exampleInfoTextOutput = new Gwen::Controls::ListBox(m_data->m_explorerPage->GetPage());
//m_data->m_exampleInfoTextOutput->Dock( Gwen::Pos::Bottom );
m_data->m_exampleInfoTextOutput->SetPos(2, 332);

View File

@@ -26,6 +26,7 @@ class GwenUserInterface
virtual ~GwenUserInterface();
void init(int width, int height,Gwen::Renderer::Base* gwenRenderer,float retinaScale);
void exit();
void setFocus();
void forceUpdateScrollBars();

View File

@@ -42,19 +42,65 @@
#include "../Importers/ImportURDFDemo/ImportURDFSetup.h"
#include "../Importers/ImportBullet/SerializeSetup.h"
#include "Bullet3Common/b3HashMap.h"
struct GL3TexLoader : public MyTextureLoader
{
b3HashMap<b3HashString, GLint> m_hashMap;
virtual void LoadTexture(Gwen::Texture* pTexture)
{
Gwen::String namestr = pTexture->name.Get();
const char* n = namestr.c_str();
GLint* texIdPtr = m_hashMap[n];
if (texIdPtr)
{
pTexture->m_intData = *texIdPtr;
}
}
virtual void FreeTexture(Gwen::Texture* pTexture)
{
}
};
struct OpenGLExampleBrowserInternalData
{
Gwen::Renderer::Base* m_gwenRenderer;
CommonGraphicsApp* m_app;
// MyProfileWindow* m_profWindow;
btAlignedObjectArray<Gwen::Controls::TreeNode*> m_nodes;
GwenUserInterface* m_gui;
GL3TexLoader* m_myTexLoader;
struct MyMenuItemHander* m_handler2;
btAlignedObjectArray<MyMenuItemHander*> m_handlers;
OpenGLExampleBrowserInternalData()
: m_gwenRenderer(0),
m_app(0),
// m_profWindow(0),
m_gui(0),
m_myTexLoader(0),
m_handler2(0)
{
}
};
static CommonGraphicsApp* s_app=0;
static CommonWindowInterface* s_window = 0;
static CommonParameterInterface* s_parameterInterface=0;
static CommonRenderInterface* s_instancingRenderer=0;
static OpenGLGuiHelper* s_guiHelper=0;
static MyProfileWindow* s_profWindow =0;
//static MyProfileWindow* s_profWindow =0;
static SharedMemoryInterface* sSharedMem = 0;
#define DEMO_SELECTION_COMBOBOX 13
const char* startFileName = "0_Bullet3Demo.txt";
char staticPngFileName[1024];
static GwenUserInterface* gui = 0;
//static GwenUserInterface* gui = 0;
static GwenUserInterface* gui2 = 0;
static int sCurrentDemoIndex = -1;
static int sCurrentHightlighted = 0;
static CommonExampleInterface* sCurrentDemo = 0;
@@ -123,9 +169,9 @@ void MyKeyboardCallback(int key, int state)
//b3Printf("key=%d, state=%d", key, state);
bool handled = false;
if (gui && !handled )
if (gui2 && !handled )
{
handled = gui->keyboardCallback(key, state);
handled = gui2->keyboardCallback(key, state);
}
if (!handled && sCurrentDemo)
@@ -226,8 +272,8 @@ static void MyMouseMoveCallback( float x, float y)
bool handled = false;
if (sCurrentDemo)
handled = sCurrentDemo->mouseMoveCallback(x,y);
if (!handled && gui)
handled = gui->mouseMoveCallback(x,y);
if (!handled && gui2)
handled = gui2->mouseMoveCallback(x,y);
if (!handled)
{
if (prevMouseMoveCallback)
@@ -244,8 +290,8 @@ static void MyMouseButtonCallback(int button, int state, float x, float y)
if (sCurrentDemo)
handled = sCurrentDemo->mouseButtonCallback(button,state,x,y);
if (!handled && gui)
handled = gui->mouseButtonCallback(button,state,x,y);
if (!handled && gui2)
handled = gui2->mouseButtonCallback(button,state,x,y);
if (!handled)
{
@@ -333,7 +379,10 @@ void selectDemo(int demoIndex)
CommonExampleInterface::CreateFunc* func = gAllExamples->getExampleCreateFunc(demoIndex);
if (func)
{
s_parameterInterface->removeAllParameters();
if (s_parameterInterface)
{
s_parameterInterface->removeAllParameters();
}
int option = gAllExamples->getExampleOption(demoIndex);
s_guiHelper= new OpenGLGuiHelper(s_app, sUseOpenGL2);
CommonExampleOptions options(s_guiHelper, option);
@@ -341,12 +390,15 @@ void selectDemo(int demoIndex)
sCurrentDemo = (*func)(options);
if (sCurrentDemo)
{
if (gui)
if (gui2)
{
gui->setStatusBarMessage("Status: OK", false);
gui2->setStatusBarMessage("Status: OK", false);
}
b3Printf("Selected demo: %s",gAllExamples->getExampleName(demoIndex));
gui->setExampleDescription(gAllExamples->getExampleDescription(demoIndex));
if (gui2)
{
gui2->setExampleDescription(gAllExamples->getExampleDescription(demoIndex));
}
sCurrentDemo->initPhysics();
if(resetCamera)
@@ -437,10 +489,10 @@ void MyComboBoxCallback(int comboId, const char* item)
void MyGuiPrintf(const char* msg)
{
printf("b3Printf: %s\n",msg);
if (gui)
if (gui2)
{
gui->textOutput(msg);
gui->forceUpdateScrollBars();
gui2->textOutput(msg);
gui2->forceUpdateScrollBars();
}
}
@@ -449,10 +501,10 @@ void MyGuiPrintf(const char* msg)
void MyStatusBarPrintf(const char* msg)
{
printf("b3Printf: %s\n", msg);
if (gui)
if (gui2)
{
bool isLeft = true;
gui->setStatusBarMessage(msg,isLeft);
gui2->setStatusBarMessage(msg,isLeft);
}
}
@@ -460,12 +512,12 @@ void MyStatusBarPrintf(const char* msg)
void MyStatusBarError(const char* msg)
{
printf("Warning: %s\n", msg);
if (gui)
if (gui2)
{
bool isLeft = false;
gui->setStatusBarMessage(msg,isLeft);
gui->textOutput(msg);
gui->forceUpdateScrollBars();
gui2->setStatusBarMessage(msg,isLeft);
gui2->textOutput(msg);
gui2->forceUpdateScrollBars();
}
}
@@ -534,7 +586,7 @@ struct MyMenuItemHander :public Gwen::Event::Handler
{
// printf("select %d\n",m_buttonId);
sCurrentHightlighted = m_buttonId;
gui->setExampleDescription(gAllExamples->getExampleDescription(sCurrentHightlighted));
gui2->setExampleDescription(gAllExamples->getExampleDescription(sCurrentHightlighted));
}
void onButtonF(Gwen::Controls::Base* pControl)
@@ -549,26 +601,6 @@ struct MyMenuItemHander :public Gwen::Event::Handler
};
#include "Bullet3Common/b3HashMap.h"
struct GL3TexLoader : public MyTextureLoader
{
b3HashMap<b3HashString,GLint> m_hashMap;
virtual void LoadTexture( Gwen::Texture* pTexture )
{
Gwen::String namestr = pTexture->name.Get();
const char* n = namestr.c_str();
GLint* texIdPtr = m_hashMap[n];
if (texIdPtr)
{
pTexture->m_intData = *texIdPtr;
}
}
virtual void FreeTexture( Gwen::Texture* pTexture )
{
}
};
void quitCallback()
@@ -623,7 +655,7 @@ struct QuickCanvas : public Common2dCanvasInterface
m_curNumGraphWindows++;
MyGraphInput input(gui->getInternalData());
MyGraphInput input(gui2->getInternalData());
input.m_width=width;
input.m_height=height;
input.m_xPos = 10000;//GUI will clamp it to the right//300;
@@ -643,7 +675,10 @@ struct QuickCanvas : public Common2dCanvasInterface
virtual void destroyCanvas(int canvasId)
{
btAssert(canvasId>=0);
delete m_gt[canvasId];
m_gt[canvasId] = 0;
destroyTextureWindow(m_gw[canvasId]);
m_gw[canvasId] = 0;
m_curNumGraphWindows--;
}
virtual void setPixel(int canvasId, int x, int y, unsigned char red, unsigned char green,unsigned char blue, unsigned char alpha)
@@ -669,12 +704,51 @@ struct QuickCanvas : public Common2dCanvasInterface
OpenGLExampleBrowser::OpenGLExampleBrowser(class ExampleEntries* examples)
{
m_internalData = new OpenGLExampleBrowserInternalData;
gAllExamples = examples;
}
OpenGLExampleBrowser::~OpenGLExampleBrowser()
{
deleteDemo();
deleteDemo();
for (int i = 0; i < m_internalData->m_nodes.size(); i++)
{
delete m_internalData->m_nodes[i];
}
delete m_internalData->m_handler2;
for (int i = 0; i < m_internalData->m_handlers.size(); i++)
{
delete m_internalData->m_handlers[i];
}
m_internalData->m_handlers.clear();
m_internalData->m_nodes.clear();
delete s_parameterInterface;
s_parameterInterface = 0;
delete s_app->m_2dCanvasInterface;
s_app->m_2dCanvasInterface = 0;
m_internalData->m_gui->exit();
delete m_internalData->m_gui;
delete m_internalData->m_gwenRenderer;
delete m_internalData->m_myTexLoader;
delete m_internalData->m_app;
s_app = 0;
// delete m_internalData->m_profWindow;
delete m_internalData;
gFileImporterByExtension.clear();
gAllExamples = 0;
}
@@ -732,11 +806,10 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
char title[1024];
sprintf(title,"%s using OpenGL3+. %s", appTitle,optMode);
simpleApp = new SimpleOpenGL3App(title,width,height, gAllowRetina);
s_app = simpleApp;
}
#endif
m_internalData->m_app = s_app;
char* gVideoFileName = 0;
args.GetCmdLineArgument("mp4",gVideoFileName);
#ifndef NO_OPENGL3
@@ -792,43 +865,67 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
assert(glGetError()==GL_NO_ERROR);
{
GL3TexLoader* myTexLoader = new GL3TexLoader;
m_internalData->m_myTexLoader = myTexLoader;
gui = new GwenUserInterface;
GL3TexLoader* myTexLoader = new GL3TexLoader;
Gwen::Renderer::Base* gwenRenderer = 0;
if (sUseOpenGL2 )
{
gwenRenderer = new Gwen::Renderer::OpenGL_DebugFont();
}
sth_stash* fontstash = simpleApp->getFontStash();
if (sUseOpenGL2)
{
m_internalData->m_gwenRenderer = new Gwen::Renderer::OpenGL_DebugFont();
}
#ifndef NO_OPENGL3
else
{
sth_stash* fontstash=simpleApp->getFontStash();
gwenRenderer = new GwenOpenGL3CoreRenderer(simpleApp->m_primRenderer,fontstash,width,height,s_window->getRetinaScale(),myTexLoader);
}
else
{
sth_stash* fontstash = simpleApp->getFontStash();
m_internalData->m_gwenRenderer = new GwenOpenGL3CoreRenderer(simpleApp->m_primRenderer, fontstash, width, height, s_window->getRetinaScale(), myTexLoader);
}
#endif
gui2 = new GwenUserInterface;
m_internalData->m_gui = gui2;
m_internalData->m_myTexLoader = myTexLoader;
gui2->init(width, height, m_internalData->m_gwenRenderer, s_window->getRetinaScale());
}
//gui = 0;// new GwenUserInterface;
GL3TexLoader* myTexLoader = m_internalData->m_myTexLoader;
// = myTexLoader;
//
gui->init(width,height,gwenRenderer,s_window->getRetinaScale());
// gui->getInternalData()->m_explorerPage
Gwen::Controls::TreeControl* tree = gui->getInternalData()->m_explorerTreeCtrl;
if (gui2)
{
// gui->getInternalData()->m_explorerPage
Gwen::Controls::TreeControl* tree = gui2->getInternalData()->m_explorerTreeCtrl;
//gui->getInternalData()->pRenderer->setTextureLoader(myTexLoader);
// s_profWindow= setupProfileWindow(gui2->getInternalData());
//m_internalData->m_profWindow = s_profWindow;
// profileWindowSetVisible(s_profWindow,false);
gui2->setFocus();
s_parameterInterface = s_app->m_parameterInterface = new GwenParameterInterface(gui2->getInternalData());
s_app->m_2dCanvasInterface = new QuickCanvas(myTexLoader);
//gui->getInternalData()->pRenderer->setTextureLoader(myTexLoader);
s_profWindow= setupProfileWindow(gui->getInternalData());
profileWindowSetVisible(s_profWindow,false);
gui->setFocus();
s_parameterInterface = s_app->m_parameterInterface = new GwenParameterInterface(gui->getInternalData());
s_app->m_2dCanvasInterface = new QuickCanvas(myTexLoader);
///add some demos to the gAllExamples
@@ -839,7 +936,7 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
//int curDemo = 0;
int selectedDemo = 0;
Gwen::Controls::TreeNode* curNode = tree;
MyMenuItemHander* handler2 = new MyMenuItemHander(-1);
m_internalData->m_handler2 = new MyMenuItemHander(-1);
char* demoNameFromCommandOption = 0;
args.GetCmdLineArgument("start_demo_name", demoNameFromCommandOption);
@@ -847,7 +944,7 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
selectedDemo = -1;
}
tree->onReturnKeyDown.Add(handler2, &MyMenuItemHander::onButtonD);
tree->onReturnKeyDown.Add(m_internalData->m_handler2, &MyMenuItemHander::onButtonD);
int firstAvailableDemoIndex=-1;
Gwen::Controls::TreeNode* firstNode=0;
@@ -894,13 +991,18 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
}
}
#if 1
MyMenuItemHander* handler = new MyMenuItemHander(d);
m_internalData->m_handlers.push_back(handler);
pNode->onNamePress.Add(handler, &MyMenuItemHander::onButtonA);
pNode->GetButton()->onDoubleClick.Add(handler, &MyMenuItemHander::onButtonB);
pNode->GetButton()->onDown.Add(handler, &MyMenuItemHander::onButtonC);
pNode->onSelect.Add(handler, &MyMenuItemHander::onButtonE);
pNode->onReturnKeyDown.Add(handler, &MyMenuItemHander::onButtonG);
pNode->onSelectChange.Add(handler, &MyMenuItemHander::onButtonF);
#endif
// pNode->onKeyReturn.Add(handler, &MyMenuItemHander::onButtonD);
// pNode->GetButton()->onKeyboardReturn.Add(handler, &MyMenuItemHander::onButtonD);
// pNode->onNamePress.Add(handler, &MyMenuItemHander::onButtonD);
@@ -910,6 +1012,7 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
else
{
curNode = tree->AddNode(nodeUText);
m_internalData->m_nodes.push_back(curNode);
}
}
@@ -928,6 +1031,9 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
}
}
free(demoNameFromCommandOption);
demoNameFromCommandOption = 0;
btAssert(sCurrentDemo!=0);
if (sCurrentDemo==0)
{
@@ -935,9 +1041,11 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
exit(0);
}
gui->registerFileOpenCallback(fileOpenCallback);
gui->registerQuitCallback(quitCallback);
gui2->registerFileOpenCallback(fileOpenCallback);
gui2->registerQuitCallback(quitCallback);
}
return true;
}
@@ -1044,7 +1152,7 @@ void OpenGLExampleBrowser::update(float deltaTime)
{
if (s_guiHelper && s_guiHelper->getRenderInterface() && s_guiHelper->getRenderInterface()->getActiveCamera())
if (gui2 && s_guiHelper && s_guiHelper->getRenderInterface() && s_guiHelper->getRenderInterface()->getActiveCamera())
{
char msg[1024];
float camDist = s_guiHelper->getRenderInterface()->getActiveCamera()->getCameraDistance();
@@ -1053,7 +1161,7 @@ void OpenGLExampleBrowser::update(float deltaTime)
float camTarget[3];
s_guiHelper->getRenderInterface()->getActiveCamera()->getCameraTargetPosition(camTarget);
sprintf(msg,"dist=%f, pitch=%f, yaw=%f,target=%f,%f,%f", camDist,pitch,yaw,camTarget[0],camTarget[1],camTarget[2]);
gui->setStatusBarMessage(msg, true);
gui2->setStatusBarMessage(msg, true);
}
}
@@ -1061,16 +1169,24 @@ void OpenGLExampleBrowser::update(float deltaTime)
static int toggle = 1;
if (renderGui)
{
if (!pauseSimulation)
processProfileData(s_profWindow,false);
// if (!pauseSimulation)
// processProfileData(s_profWindow,false);
if (sUseOpenGL2)
if (sUseOpenGL2)
{
saveOpenGLState(s_instancingRenderer->getScreenWidth(),s_instancingRenderer->getScreenHeight());
saveOpenGLState(s_instancingRenderer->getScreenWidth(), s_instancingRenderer->getScreenHeight());
}
BT_PROFILE("Draw Gwen GUI");
gui->draw(s_instancingRenderer->getScreenWidth(),s_instancingRenderer->getScreenHeight());
BT_PROFILE("Draw Gwen GUI");
if (m_internalData->m_gui)
{
m_internalData->m_gui->draw(s_instancingRenderer->getScreenWidth(), s_instancingRenderer->getScreenHeight());
}
if (gui2)
{
gui2->draw(s_instancingRenderer->getScreenWidth(), s_instancingRenderer->getScreenHeight());
}
if (sUseOpenGL2)
{
restoreOpenGLState();
@@ -1084,14 +1200,20 @@ void OpenGLExampleBrowser::update(float deltaTime)
toggle=1-toggle;
{
BT_PROFILE("Sync Parameters");
s_parameterInterface->syncParameters();
if (s_parameterInterface)
{
s_parameterInterface->syncParameters();
}
}
{
BT_PROFILE("Swap Buffers");
s_app->swapBuffer();
}
gui->forceUpdateScrollBars();
if (gui2)
{
gui2->forceUpdateScrollBars();
}
}

View File

@@ -5,6 +5,9 @@
class OpenGLExampleBrowser : public ExampleBrowserInterface
{
struct OpenGLExampleBrowserInternalData* m_internalData;
public:
OpenGLExampleBrowser(class ExampleEntries* examples);

View File

@@ -167,6 +167,7 @@ OpenGLGuiHelper::OpenGLGuiHelper(CommonGraphicsApp* glApp, bool useOpenGL2)
OpenGLGuiHelper::~OpenGLGuiHelper()
{
delete m_data->m_debugDraw;
delete m_data->m_gl2ShapeDrawer;
delete m_data;
}

View File

@@ -1,4 +1,5 @@
#include "OpenGLExampleBrowser.h"
#include "Bullet3Common/b3CommandLineArgs.h"
@@ -14,38 +15,45 @@
#include "../Importers/ImportURDFDemo/ImportURDFSetup.h"
#include "../Importers/ImportSDFDemo/ImportSDFSetup.h"
#include "../Importers/ImportSTLDemo/ImportSTLSetup.h"
#include "LinearMath/btAlignedAllocator.h"
int main(int argc, char* argv[])
{
b3CommandLineArgs args(argc,argv);
b3Clock clock;
ExampleEntriesAll examples;
examples.initExampleEntries();
OpenGLExampleBrowser* exampleBrowser = new OpenGLExampleBrowser(&examples);
bool init = exampleBrowser->init(argc,argv);
exampleBrowser->registerFileImporter(".urdf",ImportURDFCreateFunc);
exampleBrowser->registerFileImporter(".sdf",ImportSDFCreateFunc);
exampleBrowser->registerFileImporter(".obj",ImportObjCreateFunc);
exampleBrowser->registerFileImporter(".stl",ImportSTLCreateFunc);
clock.reset();
if (init)
{
do
{
float deltaTimeInSeconds = clock.getTimeMicroseconds()/1000000.f;
clock.reset();
exampleBrowser->update(deltaTimeInSeconds);
b3CommandLineArgs args(argc, argv);
b3Clock clock;
ExampleEntriesAll examples;
examples.initExampleEntries();
OpenGLExampleBrowser* exampleBrowser = new OpenGLExampleBrowser(&examples);
bool init = exampleBrowser->init(argc, argv);
exampleBrowser->registerFileImporter(".urdf", ImportURDFCreateFunc);
exampleBrowser->registerFileImporter(".sdf", ImportSDFCreateFunc);
exampleBrowser->registerFileImporter(".obj", ImportObjCreateFunc);
exampleBrowser->registerFileImporter(".stl", ImportSTLCreateFunc);
clock.reset();
if (init)
{
do
{
float deltaTimeInSeconds = clock.getTimeMicroseconds() / 1000000.f;
clock.reset();
exampleBrowser->update(deltaTimeInSeconds);
} while (!exampleBrowser->requestedExit());
}
delete exampleBrowser;
} while (!exampleBrowser->requestedExit());
}
delete exampleBrowser;
#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
int numBytesLeaked = btDumpMemoryLeaks();
btAssert(numBytesLeaked==0);
#endif//BT_DEBUG_MEMORY_ALLOCATIONS
return 0;
}

View File

@@ -1058,13 +1058,14 @@ btCollisionShape* BulletURDFImporter::getAllocatedCollisionShape(int index)
{
const UrdfCollision& col = link->m_collisionArray[v];
btCollisionShape* childShape = convertURDFToCollisionShape(&col ,pathPrefix);
m_data->m_allocatedCollisionShapes.push_back(childShape);
if (childShape)
{
btTransform childTrans = col.m_linkLocalFrame;
compoundShape->addChildShape(localInertiaFrame.inverse()*childTrans,childShape);
}
}
}
}

View File

@@ -207,7 +207,7 @@ void ImportUrdfSetup::initPhysics()
BulletURDFImporter u2b(m_guiHelper, 0);
bool loadOk = u2b.loadURDF(m_fileName);
bool loadOk = u2b.loadURDF(m_fileName);
#ifdef TEST_MULTIBODY_SERIALIZATION
//test to serialize a multibody to disk or shared memory, with base, link and joint names
@@ -238,7 +238,11 @@ void ImportUrdfSetup::initPhysics()
m_data->m_rb = creation.getRigidBody();
m_data->m_mb = creation.getBulletMultiBody();
btMultiBody* mb = m_data->m_mb;
for (int i = 0; i < u2b.getNumAllocatedCollisionShapes(); i++)
{
m_collisionShapes.push_back(u2b.getAllocatedCollisionShape(i));
}
if (m_useMultiBody && mb )
{
std::string* name = new std::string(u2b.getLinkName(u2b.getRootLinkIndex()));
@@ -348,6 +352,7 @@ void ImportUrdfSetup::initPhysics()
btVector3 groundHalfExtents(20,20,20);
groundHalfExtents[upAxis]=1.f;
btBoxShape* box = new btBoxShape(groundHalfExtents);
m_collisionShapes.push_back(box);
box->initializePolyhedralFeatures();
m_guiHelper->createCollisionShapeGraphicsObject(box);

View File

@@ -61,7 +61,9 @@ static bool parseVector4(btVector4& vec4, const std::string& vector_str)
vec4.setZero();
btArray<std::string> pieces;
btArray<float> rgba;
urdfStringSplit(pieces, vector_str, urdfIsAnyOf(" "));
btAlignedObjectArray<std::string> strArray;
urdfIsAnyOf(" ", strArray);
urdfStringSplit(pieces, vector_str, strArray);
for (int i = 0; i < pieces.size(); ++i)
{
if (!pieces[i].empty())
@@ -82,7 +84,9 @@ static bool parseVector3(btVector3& vec3, const std::string& vector_str, ErrorLo
vec3.setZero();
btArray<std::string> pieces;
btArray<float> rgba;
urdfStringSplit(pieces, vector_str, urdfIsAnyOf(" "));
btAlignedObjectArray<std::string> strArray;
urdfIsAnyOf(" ", strArray);
urdfStringSplit(pieces, vector_str, strArray);
for (int i = 0; i < pieces.size(); ++i)
{
if (!pieces[i].empty())

View File

@@ -8,7 +8,7 @@
#include "urdfStringSplit.h"
void urdfStringSplit( btAlignedObjectArray<std::string>&pieces, const std::string& vector_str, btAlignedObjectArray<std::string> separators)
void urdfStringSplit( btAlignedObjectArray<std::string>&pieces, const std::string& vector_str, const btAlignedObjectArray<std::string>& separators)
{
assert(separators.size()==1);
if (separators.size()==1)
@@ -20,10 +20,9 @@ void urdfStringSplit( btAlignedObjectArray<std::string>&pieces, const std::strin
urdfStrArrayFree(strArray);
}
}
btAlignedObjectArray<std::string> urdfIsAnyOf(const char* seps)
void urdfIsAnyOf(const char* seps, btAlignedObjectArray<std::string>& strArray)
{
btAlignedObjectArray<std::string> strArray;
int numSeps = strlen(seps);
for (int i=0;i<numSeps;i++)
{
@@ -32,8 +31,6 @@ void urdfStringSplit( btAlignedObjectArray<std::string>&pieces, const std::strin
sep2[0] = seps[i];
strArray.push_back(sep2);
}
return strArray;
}

View File

@@ -7,9 +7,9 @@
#include "LinearMath/btAlignedObjectArray.h"
void urdfStringSplit( btAlignedObjectArray<std::string>&pieces, const std::string& vector_str, btAlignedObjectArray<std::string> separators);
void urdfStringSplit( btAlignedObjectArray<std::string>&pieces, const std::string& vector_str, const btAlignedObjectArray<std::string>& separators);
btAlignedObjectArray<std::string> urdfIsAnyOf(const char* seps);
void urdfIsAnyOf(const char* seps, btAlignedObjectArray<std::string>& strArray);
///The string split C code is by Lars Wirzenius
///See http://stackoverflow.com/questions/2531605/how-to-split-a-string-with-a-delimiter-larger-than-one-single-char

View File

@@ -105,7 +105,7 @@ InverseDynamicsExample::InverseDynamicsExample(struct GUIHelperInterface* helper
InverseDynamicsExample::~InverseDynamicsExample()
{
delete m_multiBody;
delete m_inverseModel;
delete m_timeSeriesCanvas;
}
@@ -166,6 +166,10 @@ void InverseDynamicsExample::initPhysics()
btTransform identityTrans;
identityTrans.setIdentity();
ConvertURDF2Bullet(u2b,creation, identityTrans,m_dynamicsWorld,true,u2b.getPathPrefix());
for (int i = 0; i < u2b.getNumAllocatedCollisionShapes(); i++)
{
m_collisionShapes.push_back(u2b.getAllocatedCollisionShape(i));
}
m_multiBody = creation.getBulletMultiBody();
if (m_multiBody)
{

View File

@@ -650,9 +650,14 @@ void SimpleOpenGL3App::setBackgroundColor(float red, float green, float blue)
SimpleOpenGL3App::~SimpleOpenGL3App()
{
delete m_instancingRenderer;
delete m_primRenderer ;
sth_delete(m_data->m_fontStash);
delete m_data->m_renderCallbacks;
TwDeleteDefaultFonts();
m_window->closeWindow();
delete m_window;
delete m_data ;
}

View File

@@ -4883,18 +4883,33 @@ static const unsigned char s_FontFixed1[] = {
void TwGenerateDefaultFonts()
{
g_DefaultSmallFont = TwGenerateFont(s_Font0, FONT0_BM_W, FONT0_BM_H);
assert(g_DefaultSmallFont && g_DefaultSmallFont->m_NbCharRead==224);
if (g_DefaultSmallFont == 0)
{
g_DefaultSmallFont = TwGenerateFont(s_Font0, FONT0_BM_W, FONT0_BM_H);
assert(g_DefaultSmallFont && g_DefaultSmallFont->m_NbCharRead == 224);
}
g_DefaultNormalFont = TwGenerateFont(s_Font1, FONT1_BM_W, FONT1_BM_H);
assert(g_DefaultNormalFont && g_DefaultNormalFont->m_NbCharRead==224);
if (g_DefaultNormalFont == 0)
{
g_DefaultNormalFont = TwGenerateFont(s_Font1, FONT1_BM_W, FONT1_BM_H);
assert(g_DefaultNormalFont && g_DefaultNormalFont->m_NbCharRead == 224);
}
g_DefaultNormalFontAA = TwGenerateFont(s_Font1AA, FONT1AA_BM_W, FONT1AA_BM_H);
assert(g_DefaultNormalFontAA && g_DefaultNormalFontAA->m_NbCharRead==224);
g_DefaultLargeFont = TwGenerateFont(s_Font2AA, FONT2AA_BM_W, FONT2AA_BM_H);
assert(g_DefaultLargeFont && g_DefaultLargeFont->m_NbCharRead==224);
g_DefaultFixed1Font = TwGenerateFont(s_FontFixed1, FONTFIXED1_BM_W, FONTFIXED1_BM_H);
assert(g_DefaultFixed1Font && g_DefaultFixed1Font->m_NbCharRead==224);
if (g_DefaultNormalFontAA == 0)
{
g_DefaultNormalFontAA = TwGenerateFont(s_Font1AA, FONT1AA_BM_W, FONT1AA_BM_H);
assert(g_DefaultNormalFontAA && g_DefaultNormalFontAA->m_NbCharRead == 224);
}
if (g_DefaultLargeFont == 0)
{
g_DefaultLargeFont = TwGenerateFont(s_Font2AA, FONT2AA_BM_W, FONT2AA_BM_H);
assert(g_DefaultLargeFont && g_DefaultLargeFont->m_NbCharRead == 224);
}
if (g_DefaultFixed1Font == 0)
{
g_DefaultFixed1Font = TwGenerateFont(s_FontFixed1, FONTFIXED1_BM_W, FONTFIXED1_BM_H);
assert(g_DefaultFixed1Font && g_DefaultFixed1Font->m_NbCharRead == 224);
}
}
// ---------------------------------------------------------------------------

View File

@@ -31,6 +31,10 @@ struct UrdfLinkNameMapUtil
UrdfLinkNameMapUtil():m_mb(0),m_memSerializer(0)
{
}
virtual ~UrdfLinkNameMapUtil()
{
delete m_memSerializer;
}
};
@@ -701,15 +705,6 @@ bool PhysicsServerCommandProcessor::loadSdf(const char* fileName, char* bufferSe
{
btCollisionShape* shape =u2b.getAllocatedCollisionShape(i);
m_data->m_collisionShapes.push_back(shape);
if (shape->isCompound())
{
btCompoundShape* compound = (btCompoundShape*) shape;
for (int childIndex=0;childIndex<compound->getNumChildShapes();childIndex++)
{
m_data->m_collisionShapes.push_back(compound->getChildShape(childIndex));
}
}
}
btTransform rootTrans;
@@ -851,15 +846,6 @@ bool PhysicsServerCommandProcessor::loadUrdf(const char* fileName, const btVecto
{
btCollisionShape* shape =u2b.getAllocatedCollisionShape(i);
m_data->m_collisionShapes.push_back(shape);
if (shape->isCompound())
{
btCompoundShape* compound = (btCompoundShape*) shape;
for (int childIndex=0;childIndex<compound->getNumChildShapes();childIndex++)
{
m_data->m_collisionShapes.push_back(compound->getChildShape(childIndex));
}
}
}
btMultiBody* mb = creation.getBulletMultiBody();

View File

@@ -78,7 +78,6 @@ PhysicsServerSharedMemory::PhysicsServerSharedMemory(SharedMemoryInterface* shar
}
m_data->m_commandProcessor = new PhysicsServerCommandProcessor;
m_data->m_commandProcessor ->createEmptyDynamicsWorld();
}

View File

@@ -701,7 +701,16 @@ void TinyRendererVisualShapeConverter::copyCameraImageData(unsigned char* pixels
void TinyRendererVisualShapeConverter::resetAll()
{
//todo: free memory
for (int i=0;i<m_data->m_swRenderInstances.size();i++)
{
TinyRendererObjectArray** ptrptr = m_data->m_swRenderInstances.getAtIndex(i);
if (ptrptr && *ptrptr)
{
TinyRendererObjectArray* ptr = *ptrptr;
delete ptr;
}
}
m_data->m_swRenderInstances.clear();
}

View File

@@ -1,3 +1,6 @@
#include "OpenGLWindow/SimpleOpenGL3App.h"
#include "Bullet3Common/b3Quaternion.h"
#include "Bullet3Common/b3CommandLineArgs.h"
@@ -58,98 +61,103 @@ void MyKeyboardCallback(int keycode, int state)
int main(int argc, char* argv[])
{
b3CommandLineArgs myArgs(argc,argv);
SimpleOpenGL3App* app = new SimpleOpenGL3App("SimpleOpenGL3App",gWidth,gHeight,true);
app->m_instancingRenderer->getActiveCamera()->setCameraDistance(13);
app->m_instancingRenderer->getActiveCamera()->setCameraPitch(0);
app->m_instancingRenderer->getActiveCamera()->setCameraTargetPosition(0,0,0);
sOldKeyboardCB = app->m_window->getKeyboardCallback();
app->m_window->setKeyboardCallback(MyKeyboardCallback);
sOldMouseMoveCB = app->m_window->getMouseMoveCallback();
app->m_window->setMouseMoveCallback(MyMouseMoveCallback);
sOldMouseButtonCB = app->m_window->getMouseButtonCallback();
app->m_window->setMouseButtonCallback(MyMouseButtonCallback);
sOldWheelCB = app->m_window->getWheelCallback();
app->m_window->setWheelCallback(MyWheelCallback);
sOldResizeCB = app->m_window->getResizeCallback();
app->m_window->setResizeCallback(MyResizeCallback);
myArgs.GetCmdLineArgument("mp4_file",gVideoFileName);
if (gVideoFileName)
app->dumpFramesToVideo(gVideoFileName);
myArgs.GetCmdLineArgument("png_file",gPngFileName);
char fileName[1024];
int textureWidth = 128;
int textureHeight = 128;
unsigned char* image=new unsigned char[textureWidth*textureHeight*4];
int textureHandle = app->m_renderer->registerTexture(image,textureWidth,textureHeight);
int cubeIndex = app->registerCubeShape(1,1,1);
b3Vector3 pos = b3MakeVector3(0,0,0);
b3Quaternion orn(0,0,0,1);
b3Vector3 color=b3MakeVector3(1,0,0);
b3Vector3 scaling=b3MakeVector3 (1,1,1);
app->m_renderer->registerGraphicsInstance(cubeIndex,pos,orn,color,scaling);
app->m_renderer->writeTransforms();
do
{
static int frameCount = 0;
frameCount++;
if (gPngFileName)
{
printf("gPngFileName=%s\n",gPngFileName);
sprintf(fileName,"%s%d.png",gPngFileName,frameCount++);
app->dumpNextFrameToPng(fileName);
}
//update the texels of the texture using a simple pattern, animated using frame index
for(int y=0;y<textureHeight;++y)
{
const int t=(y+frameCount)>>4;
unsigned char* pi=image+y*textureWidth*3;
for(int x=0;x<textureWidth;++x)
{
const int s=x>>4;
const unsigned char b=180;
unsigned char c=b+((s+(t&1))&1)*(255-b);
pi[0]=pi[1]=pi[2]=pi[3]=c;pi+=3;
}
}
app->m_renderer->activateTexture(textureHandle);
app->m_renderer->updateTexture(textureHandle,image);
float color[4] = {255,1,1,1};
app->m_primRenderer->drawTexturedRect(100,200,gWidth/2-50,gHeight/2-50,color,0,0,1,1,true);
app->m_instancingRenderer->init();
app->m_instancingRenderer->updateCamera();
app->m_renderer->renderScene();
app->drawGrid();
char bla[1024];
sprintf(bla,"Simple test frame %d", frameCount);
app->drawText(bla,10,10);
app->swapBuffer();
} while (!app->m_window->requestedExit());
b3CommandLineArgs myArgs(argc, argv);
delete app;
SimpleOpenGL3App* app = new SimpleOpenGL3App("SimpleOpenGL3App", gWidth, gHeight, true);
app->m_instancingRenderer->getActiveCamera()->setCameraDistance(13);
app->m_instancingRenderer->getActiveCamera()->setCameraPitch(0);
app->m_instancingRenderer->getActiveCamera()->setCameraTargetPosition(0, 0, 0);
sOldKeyboardCB = app->m_window->getKeyboardCallback();
app->m_window->setKeyboardCallback(MyKeyboardCallback);
sOldMouseMoveCB = app->m_window->getMouseMoveCallback();
app->m_window->setMouseMoveCallback(MyMouseMoveCallback);
sOldMouseButtonCB = app->m_window->getMouseButtonCallback();
app->m_window->setMouseButtonCallback(MyMouseButtonCallback);
sOldWheelCB = app->m_window->getWheelCallback();
app->m_window->setWheelCallback(MyWheelCallback);
sOldResizeCB = app->m_window->getResizeCallback();
app->m_window->setResizeCallback(MyResizeCallback);
myArgs.GetCmdLineArgument("mp4_file", gVideoFileName);
if (gVideoFileName)
app->dumpFramesToVideo(gVideoFileName);
myArgs.GetCmdLineArgument("png_file", gPngFileName);
char fileName[1024];
int textureWidth = 128;
int textureHeight = 128;
unsigned char* image = new unsigned char[textureWidth*textureHeight * 4];
int textureHandle = app->m_renderer->registerTexture(image, textureWidth, textureHeight);
int cubeIndex = app->registerCubeShape(1, 1, 1);
b3Vector3 pos = b3MakeVector3(0, 0, 0);
b3Quaternion orn(0, 0, 0, 1);
b3Vector3 color = b3MakeVector3(1, 0, 0);
b3Vector3 scaling = b3MakeVector3 (1, 1, 1);
app->m_renderer->registerGraphicsInstance(cubeIndex, pos, orn, color, scaling);
app->m_renderer->writeTransforms();
do
{
static int frameCount = 0;
frameCount++;
if (gPngFileName)
{
printf("gPngFileName=%s\n", gPngFileName);
sprintf(fileName, "%s%d.png", gPngFileName, frameCount++);
app->dumpNextFrameToPng(fileName);
}
//update the texels of the texture using a simple pattern, animated using frame index
for (int y = 0; y < textureHeight; ++y)
{
const int t = (y + frameCount) >> 4;
unsigned char* pi = image + y*textureWidth * 3;
for (int x = 0; x < textureWidth; ++x)
{
const int s = x >> 4;
const unsigned char b = 180;
unsigned char c = b + ((s + (t & 1)) & 1)*(255 - b);
pi[0] = pi[1] = pi[2] = pi[3] = c; pi += 3;
}
}
app->m_renderer->activateTexture(textureHandle);
app->m_renderer->updateTexture(textureHandle, image);
float color[4] = { 255, 1, 1, 1 };
app->m_primRenderer->drawTexturedRect(100, 200, gWidth / 2 - 50, gHeight / 2 - 50, color, 0, 0, 1, 1, true);
app->m_instancingRenderer->init();
app->m_instancingRenderer->updateCamera();
app->m_renderer->renderScene();
app->drawGrid();
char bla[1024];
sprintf(bla, "Simple test frame %d", frameCount);
app->drawText(bla, 10, 10);
app->swapBuffer();
} while (!app->m_window->requestedExit());
delete app;
delete[] image;
}
return 0;
}

View File

@@ -28,22 +28,22 @@ subject to the following restrictions:
int main(int argc, char* argv[])
{
DummyGUIHelper noGfx;
CommonExampleOptions options(&noGfx);
CommonExampleInterface* example = StandaloneExampleCreateFunc(options);
example->initPhysics();
for (int i=0;i<1000;i++)
{
printf("Simulating step %d\n",i);
example->stepSimulation(1.f/60.f);
DummyGUIHelper noGfx;
CommonExampleOptions options(&noGfx);
CommonExampleInterface* example = StandaloneExampleCreateFunc(options);
example->initPhysics();
for (int i = 0; i < 1000; i++)
{
printf("Simulating step %d\n", i);
example->stepSimulation(1.f / 60.f);
}
example->exitPhysics();
delete example;
}
example->exitPhysics();
delete example;
return 0;
}

View File

@@ -122,6 +122,7 @@ subject to the following restrictions:
#error "DBVT_INT0_IMPL undefined"
#endif
//
// Defaults volumes
//
@@ -188,6 +189,9 @@ struct btDbvtNode
};
};
typedef btAlignedObjectArray<const btDbvtNode*> btNodeStack;
///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes.
///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
@@ -325,6 +329,16 @@ struct btDbvt
void collideTV( const btDbvtNode* root,
const btDbvtVolume& volume,
DBVT_IPOLICY) const;
DBVT_PREFIX
void collideTVNoStackAlloc( const btDbvtNode* root,
const btDbvtVolume& volume,
btNodeStack& stack,
DBVT_IPOLICY) const;
///rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thread-safe (uses locking etc)
///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time
DBVT_PREFIX
@@ -917,39 +931,72 @@ inline void btDbvt::collideTT( const btDbvtNode* root0,
}
#endif
//
DBVT_PREFIX
inline void btDbvt::collideTV( const btDbvtNode* root,
const btDbvtVolume& vol,
DBVT_IPOLICY) const
{
DBVT_CHECKTYPE
if(root)
{
ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol);
btAlignedObjectArray<const btDbvtNode*> stack;
stack.resize(0);
stack.reserve(SIMPLE_STACKSIZE);
stack.push_back(root);
do {
const btDbvtNode* n=stack[stack.size()-1];
stack.pop_back();
if(Intersect(n->volume,volume))
if(root)
{
ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol);
btAlignedObjectArray<const btDbvtNode*> stack;
stack.resize(0);
stack.reserve(SIMPLE_STACKSIZE);
stack.push_back(root);
do {
const btDbvtNode* n=stack[stack.size()-1];
stack.pop_back();
if(Intersect(n->volume,volume))
{
if(n->isinternal())
{
if(n->isinternal())
{
stack.push_back(n->childs[0]);
stack.push_back(n->childs[1]);
}
else
{
policy.Process(n);
}
stack.push_back(n->childs[0]);
stack.push_back(n->childs[1]);
}
} while(stack.size()>0);
}
else
{
policy.Process(n);
}
}
} while(stack.size()>0);
}
}
//
DBVT_PREFIX
inline void btDbvt::collideTVNoStackAlloc( const btDbvtNode* root,
const btDbvtVolume& vol,
btNodeStack& stack,
DBVT_IPOLICY) const
{
DBVT_CHECKTYPE
if(root)
{
ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol);
stack.resize(0);
stack.reserve(SIMPLE_STACKSIZE);
stack.push_back(root);
do {
const btDbvtNode* n=stack[stack.size()-1];
stack.pop_back();
if(Intersect(n->volume,volume))
{
if(n->isinternal())
{
stack.push_back(n->childs[0]);
stack.push_back(n->childs[1]);
}
else
{
policy.Process(n);
}
}
} while(stack.size()>0);
}
}
DBVT_PREFIX
inline void btDbvt::rayTestInternal( const btDbvtNode* root,
const btVector3& rayFrom,

View File

@@ -244,7 +244,7 @@ void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrap
///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
{
int i;
btManifoldArray manifoldArray;
manifoldArray.resize(0);
for (i=0;i<m_childCollisionAlgorithms.size();i++)
{
if (m_childCollisionAlgorithms[i])
@@ -274,7 +274,7 @@ void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrap
const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
//process all children, that overlap with the given AABB bounds
tree->collideTV(tree->m_root,bounds,callback);
tree->collideTVNoStackAlloc(tree->m_root,bounds,stack2,callback);
} else
{
@@ -291,7 +291,7 @@ void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrap
//iterate over all children, perform an AABB check inside ProcessChildShape
int numChildren = m_childCollisionAlgorithms.size();
int i;
btManifoldArray manifoldArray;
manifoldArray.resize(0);
const btCollisionShape* childShape = 0;
btTransform orgTrans;

View File

@@ -26,6 +26,7 @@ class btDispatcher;
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "btCollisionCreateFunc.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
class btDispatcher;
class btCollisionObject;
@@ -36,6 +37,9 @@ extern btShapePairCallback gCompoundChildShapePairCallback;
/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
btNodeStack stack2;
btManifoldArray manifoldArray;
protected:
btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithms;
bool m_isSwapped;

View File

@@ -503,9 +503,11 @@ void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper*
// printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
worldVertsB1.resize(0);
btPolyhedralContactClipping::clipHullAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
body0Wrap->getWorldTransform(),
body1Wrap->getWorldTransform(), minDist-threshold, threshold, *resultOut);
body1Wrap->getWorldTransform(), minDist-threshold, threshold, worldVertsB1,worldVertsB2,
*resultOut);
}
if (m_ownManifold)
@@ -568,8 +570,9 @@ void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper*
if (foundSepAxis)
{
worldVertsB2.resize(0);
btPolyhedralContactClipping::clipFaceAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(),
body0Wrap->getWorldTransform(), vertices, minDist-threshold, maxDist, *resultOut);
body0Wrap->getWorldTransform(), vertices, worldVertsB2,minDist-threshold, maxDist, *resultOut);
}

View File

@@ -24,6 +24,7 @@ subject to the following restrictions:
#include "btCollisionCreateFunc.h"
#include "btCollisionDispatcher.h"
#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h"
class btConvexPenetrationDepthSolver;
@@ -45,6 +46,8 @@ class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm
btSimplexSolverInterface* m_simplexSolver;
btConvexPenetrationDepthSolver* m_pdSolver;
btVertexArray worldVertsB1;
btVertexArray worldVertsB2;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;

View File

@@ -411,9 +411,9 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron&
return true;
}
void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut)
void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1,btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut)
{
btVertexArray worldVertsB2;
worldVertsB2.resize(0);
btVertexArray* pVtxIn = &worldVertsB1;
btVertexArray* pVtxOut = &worldVertsB2;
pVtxOut->reserve(pVtxIn->size());
@@ -527,7 +527,7 @@ void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatin
void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut)
void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btVertexArray& worldVertsB1,btVertexArray& worldVertsB2,btDiscreteCollisionDetectorInterface::Result& resultOut)
{
btVector3 separatingNormal = separatingNormal1.normalized();
@@ -552,7 +552,7 @@ void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatin
}
}
}
btVertexArray worldVertsB1;
worldVertsB1.resize(0);
{
const btFace& polyB = hullB.m_faces[closestFaceB];
const int numVertices = polyB.m_indices.size();
@@ -565,6 +565,6 @@ void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatin
if (closestFaceB>=0)
clipFaceAgainstHull(separatingNormal, hullA, transA,worldVertsB1, minDist, maxDist,resultOut);
clipFaceAgainstHull(separatingNormal, hullA, transA,worldVertsB1, worldVertsB2,minDist, maxDist,resultOut);
}

View File

@@ -32,8 +32,11 @@ typedef btAlignedObjectArray<btVector3> btVertexArray;
// Clips a face to the back of a plane
struct btPolyhedralContactClipping
{
static void clipHullAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut);
static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut);
static void clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btVertexArray& worldVertsB1,btVertexArray& worldVertsB2,btDiscreteCollisionDetectorInterface::Result& resultOut);
static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1,btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut);
static bool findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut);

View File

@@ -396,22 +396,17 @@ btMultiBodyDynamicsWorld::~btMultiBodyDynamicsWorld ()
void btMultiBodyDynamicsWorld::forwardKinematics()
{
btAlignedObjectArray<btQuaternion> world_to_local;
btAlignedObjectArray<btVector3> local_origin;
for (int b=0;b<m_multiBodies.size();b++)
{
btMultiBody* bod = m_multiBodies[b];
bod->forwardKinematics(world_to_local,local_origin);
bod->forwardKinematics(m_scratch_world_to_local,m_scratch_local_origin);
}
}
void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
{
forwardKinematics();
btAlignedObjectArray<btScalar> scratch_r;
btAlignedObjectArray<btVector3> scratch_v;
btAlignedObjectArray<btMatrix3x3> scratch_m;
BT_PROFILE("solveConstraints");
@@ -463,9 +458,9 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
if (!isSleeping)
{
//useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd)
scratch_v.resize(bod->getNumLinks()+1);
scratch_m.resize(bod->getNumLinks()+1);
m_scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd)
m_scratch_v.resize(bod->getNumLinks()+1);
m_scratch_m.resize(bod->getNumLinks()+1);
bod->addBaseForce(m_gravity * bod->getBaseMass());
@@ -500,15 +495,15 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
if (!isSleeping)
{
//useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd)
scratch_v.resize(bod->getNumLinks()+1);
scratch_m.resize(bod->getNumLinks()+1);
m_scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd)
m_scratch_v.resize(bod->getNumLinks()+1);
m_scratch_m.resize(bod->getNumLinks()+1);
bool doNotUpdatePos = false;
{
if(!bod->isUsingRK4Integration())
{
bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, scratch_r, scratch_v, scratch_m);
bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m);
}
else
{
@@ -594,9 +589,9 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
//
btScalar h = solverInfo.m_timeStep;
#define output &scratch_r[bod->getNumDofs()]
#define output &m_scratch_r[bod->getNumDofs()]
//calc qdd0 from: q0 & qd0
bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., scratch_r, scratch_v, scratch_m);
bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m);
pCopy(output, scratch_qdd0, 0, numDofs);
//calc q1 = q0 + h/2 * qd0
pResetQx();
@@ -606,7 +601,7 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
//
//calc qdd1 from: q1 & qd1
pCopyToVelocityVector(bod, scratch_qd1);
bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., scratch_r, scratch_v, scratch_m);
bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m);
pCopy(output, scratch_qdd1, 0, numDofs);
//calc q2 = q0 + h/2 * qd1
pResetQx();
@@ -616,7 +611,7 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
//
//calc qdd2 from: q2 & qd2
pCopyToVelocityVector(bod, scratch_qd2);
bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., scratch_r, scratch_v, scratch_m);
bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m);
pCopy(output, scratch_qdd2, 0, numDofs);
//calc q3 = q0 + h * qd2
pResetQx();
@@ -626,7 +621,7 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
//
//calc qdd3 from: q3 & qd3
pCopyToVelocityVector(bod, scratch_qd3);
bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., scratch_r, scratch_v, scratch_m);
bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m);
pCopy(output, scratch_qdd3, 0, numDofs);
//
@@ -661,7 +656,7 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
{
for(int link = 0; link < bod->getNumLinks(); ++link)
bod->getLink(link).updateCacheMultiDof();
bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0, scratch_r, scratch_v, scratch_m);
bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0, m_scratch_r, m_scratch_v, m_scratch_m);
}
}
@@ -701,16 +696,16 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
if (!isSleeping)
{
//useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd)
scratch_v.resize(bod->getNumLinks()+1);
scratch_m.resize(bod->getNumLinks()+1);
m_scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd)
m_scratch_v.resize(bod->getNumLinks()+1);
m_scratch_m.resize(bod->getNumLinks()+1);
{
if(!bod->isUsingRK4Integration())
{
bool isConstraintPass = true;
bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, scratch_r, scratch_v, scratch_m, isConstraintPass);
bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass);
}
}
}
@@ -732,9 +727,7 @@ void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
{
BT_PROFILE("btMultiBody stepPositions");
//integrate and update the Featherstone hierarchies
btAlignedObjectArray<btQuaternion> world_to_local;
btAlignedObjectArray<btVector3> local_origin;
for (int b=0;b<m_multiBodies.size();b++)
{
btMultiBody* bod = m_multiBodies[b];
@@ -770,10 +763,10 @@ void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
}
}
world_to_local.resize(nLinks+1);
local_origin.resize(nLinks+1);
m_scratch_world_to_local.resize(nLinks+1);
m_scratch_local_origin.resize(nLinks+1);
bod->updateCollisionObjectWorldTransforms(world_to_local,local_origin);
bod->updateCollisionObjectWorldTransforms(m_scratch_world_to_local,m_scratch_local_origin);
} else
{
@@ -818,8 +811,6 @@ void btMultiBodyDynamicsWorld::debugDrawWorld()
{
BT_PROFILE("btMultiBody debugDrawWorld");
btAlignedObjectArray<btQuaternion> world_to_local1;
btAlignedObjectArray<btVector3> local_origin1;
for (int c=0;c<m_multiBodyConstraints.size();c++)
{
@@ -830,7 +821,7 @@ void btMultiBodyDynamicsWorld::debugDrawWorld()
for (int b = 0; b<m_multiBodies.size(); b++)
{
btMultiBody* bod = m_multiBodies[b];
bod->forwardKinematics(world_to_local1,local_origin1);
bod->forwardKinematics(m_scratch_world_to_local1,m_scratch_local_origin1);
getDebugDrawer()->drawTransform(bod->getBaseWorldTransform(), 0.1);

View File

@@ -36,6 +36,16 @@ protected:
btMultiBodyConstraintSolver* m_multiBodyConstraintSolver;
MultiBodyInplaceSolverIslandCallback* m_solverMultiBodyIslandCallback;
//cached data to avoid memory allocations
btAlignedObjectArray<btQuaternion> m_scratch_world_to_local;
btAlignedObjectArray<btVector3> m_scratch_local_origin;
btAlignedObjectArray<btQuaternion> m_scratch_world_to_local1;
btAlignedObjectArray<btVector3> m_scratch_local_origin1;
btAlignedObjectArray<btScalar> m_scratch_r;
btAlignedObjectArray<btVector3> m_scratch_v;
btAlignedObjectArray<btMatrix3x3> m_scratch_m;
virtual void calculateSimulationIslands();
virtual void updateActivationState(btScalar timeStep);
virtual void solveConstraints(btContactSolverInfo& solverInfo);

View File

@@ -105,30 +105,94 @@ void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc)
}
#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
static int allocations_id[10241024];
static int allocations_bytes[10241024];
static int mynumallocs = 0;
#include <stdio.h>
int btDumpMemoryLeaks()
{
int totalLeak = 0;
for (int i=0;i<mynumallocs;i++)
{
printf("Error: leaked memory of allocation #%d (%d bytes)\n", allocations_id[i], allocations_bytes[i]);
totalLeak+=allocations_bytes[i];
}
if (totalLeak)
{
printf("Error: memory leaks: %d allocations were not freed and leaked together %d bytes\n",mynumallocs,totalLeak);
}
return totalLeak;
}
//this generic allocator provides the total allocated number of bytes
#include <stdio.h>
struct btDebugPtrMagic
{
union
{
void** vptrptr;
void* vptr;
int* iptr;
char* cptr;
};
};
void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename)
{
if (size==0)
{
printf("Whaat? size==0");
return 0;
}
static int allocId = 0;
void *ret;
char *real;
// to find some particular memory leak, you could do something like this:
// if (allocId==172)
// {
// printf("catch me!\n");
// }
// if (size>1024*1024)
// {
// printf("big alloc!%d\n", size);
// }
gTotalBytesAlignedAllocs += size;
gNumAlignedAllocs++;
real = (char *)sAllocFunc(size + 2*sizeof(void *) + (alignment-1));
int sz4prt = 4*sizeof(void *);
real = (char *)sAllocFunc(size + sz4prt + (alignment-1));
if (real) {
ret = (void*) btAlignPointer(real + 2*sizeof(void *), alignment);
*((void **)(ret)-1) = (void *)(real);
*((int*)(ret)-2) = size;
ret = (void*) btAlignPointer(real + sz4prt, alignment);
btDebugPtrMagic p;
p.vptr = ret;
p.cptr-=sizeof(void*);
*p.vptrptr = (void*)real;
p.cptr-=sizeof(void*);
*p.iptr = size;
p.cptr-=sizeof(void*);
*p.iptr = allocId;
allocations_id[mynumallocs] = allocId;
allocations_bytes[mynumallocs] = size;
mynumallocs++;
} else {
ret = (void *)(real);//??
}
printf("allocation#%d at address %x, from %s,line %d, size %d\n",gNumAlignedAllocs,real, filename,line,size);
printf("allocation %d at address %x, from %s,line %d, size %d (total allocated = %d)\n",allocId,real, filename,line,size,gTotalBytesAlignedAllocs);
allocId++;
int* ptr = (int*)ret;
*ptr = 12;
return (ret);
@@ -138,19 +202,43 @@ void btAlignedFreeInternal (void* ptr,int line,char* filename)
{
void* real;
gNumAlignedFree++;
if (ptr) {
real = *((void **)(ptr)-1);
int size = *((int*)(ptr)-2);
gTotalBytesAlignedAllocs -= size;
gNumAlignedFree++;
printf("free #%d at address %x, from %s,line %d, size %d\n",gNumAlignedFree,real, filename,line,size);
btDebugPtrMagic p;
p.vptr = ptr;
p.cptr-=sizeof(void*);
real = *p.vptrptr;
p.cptr-=sizeof(void*);
int size = *p.iptr;
p.cptr-=sizeof(void*);
int allocId = *p.iptr;
bool found = false;
for (int i=0;i<mynumallocs;i++)
{
if ( allocations_id[i] == allocId)
{
allocations_id[i] = allocations_id[mynumallocs-1];
allocations_bytes[i] = allocations_bytes[mynumallocs-1];
mynumallocs--;
found = true;
break;
}
}
gTotalBytesAlignedAllocs -= size;
int diff = gNumAlignedAllocs-gNumAlignedFree;
printf("free %d at address %x, from %s,line %d, size %d (total remain = %d in %d non-freed allocations)\n",allocId,real, filename,line,size, gTotalBytesAlignedAllocs, diff);
sFreeFunc(real);
} else
{
printf("NULL ptr\n");
//printf("deleting a NULL ptr, no effect\n");
}
}

View File

@@ -21,9 +21,15 @@ subject to the following restrictions:
///that is better portable and more predictable
#include "btScalar.h"
//#define BT_DEBUG_MEMORY_ALLOCATIONS 1
///BT_DEBUG_MEMORY_ALLOCATIONS preprocessor can be set in build system
///for regression tests to detect memory leaks
///#define BT_DEBUG_MEMORY_ALLOCATIONS 1
#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
int btDumpMemoryLeaks();
#define btAlignedAlloc(a,b) \
btAlignedAllocInternal(a,b,__LINE__,__FILE__)