From 1af84ad8526cb544c3908edb5f5b863a343b4c67 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Sun, 4 Jul 2010 13:20:09 +0200 Subject: [PATCH 01/56] added readme, wee --- .gitignore | 2 ++ README | 12 ++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 .gitignore create mode 100644 README diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..d6ff91a9e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*~ +*.o diff --git a/README b/README new file mode 100644 index 000000000..621fe8d60 --- /dev/null +++ b/README @@ -0,0 +1,12 @@ +OpenEngine README +================= + +OpenEngine is a bunch of stand-alone game engine modules collected from the OpenMW project (see http://github.com/korslund/openmw or http://openmw.com ) and from certain other projects. + +It is currently a very early work in progress, and development will follow OpenMW closely for a while forward. + +OpenEngine will depend heavily on Mangle ( http://github.com/korslund/mangle/ ) and will thus aim to be backend agnostic. When finished it should work with a variety for free and commercial middleware libraries as backends for graphics, sound, physics, input and so on. + +All questions can be directed to Nicolay Korslund at korslund@gmail.com + +- Nicolay From 5d73b47cc06803f416f1da969ac0450e80ff5199 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Sun, 4 Jul 2010 14:28:51 +0200 Subject: [PATCH 02/56] Added input component --- .gitignore | 1 + .gitmodules | 3 + input/dispatch_map.hpp | 75 ++++++++++++++++ input/dispatcher.hpp | 49 +++++++++++ input/func_binder.hpp | 104 +++++++++++++++++++++++ input/poller.hpp | 46 ++++++++++ input/tests/Makefile | 18 ++++ input/tests/dispatch_map_test.cpp | 54 ++++++++++++ input/tests/funcbind_test.cpp | 47 ++++++++++ input/tests/output/dispatch_map_test.out | 18 ++++ input/tests/output/funcbind_test.out | 15 ++++ input/tests/output/sdl_binder_test.out | 4 + input/tests/output/sdl_driver_test.out | 4 + input/tests/sdl_binder_test.cpp | 71 ++++++++++++++++ input/tests/sdl_driver_test.cpp | 31 +++++++ input/tests/test.sh | 18 ++++ mangle | 1 + testall.sh | 11 +++ 18 files changed, 570 insertions(+) create mode 100644 .gitmodules create mode 100644 input/dispatch_map.hpp create mode 100644 input/dispatcher.hpp create mode 100644 input/func_binder.hpp create mode 100644 input/poller.hpp create mode 100644 input/tests/Makefile create mode 100644 input/tests/dispatch_map_test.cpp create mode 100644 input/tests/funcbind_test.cpp create mode 100644 input/tests/output/dispatch_map_test.out create mode 100644 input/tests/output/funcbind_test.out create mode 100644 input/tests/output/sdl_binder_test.out create mode 100644 input/tests/output/sdl_driver_test.out create mode 100644 input/tests/sdl_binder_test.cpp create mode 100644 input/tests/sdl_driver_test.cpp create mode 100755 input/tests/test.sh create mode 160000 mangle create mode 100755 testall.sh diff --git a/.gitignore b/.gitignore index d6ff91a9e..23a5e931b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *~ *.o +*_test diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..0a9a9121f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "mangle"] + path = mangle + url = git://github.com/korslund/mangle diff --git a/input/dispatch_map.hpp b/input/dispatch_map.hpp new file mode 100644 index 000000000..356660e75 --- /dev/null +++ b/input/dispatch_map.hpp @@ -0,0 +1,75 @@ +#ifndef _INPUT_DISPATCHMAP_H +#define _INPUT_DISPATCHMAP_H + +#include +#include +#include + +namespace Input { + +/** + DispatchMap is a simple connection system that connects incomming + signals with outgoing signals. + + The signals can be connected one-to-one, many-to-one, one-to-many + or many-to-many. + + The dispatch map is completely system agnostic. It is a pure data + structure and all signals are just integer indices. It does not + delegate any actions, but used together with Dispatcher it can be + used to build an event system. + */ +struct DispatchMap +{ + typedef std::set OutList; + typedef std::map InMap; + + typedef OutList::iterator Oit; + typedef InMap::iterator Iit; + + InMap map; + + void bind(int in, int out) + { + map[in].insert(out); + } + + void unbind(int in, int out) + { + Iit it = map.find(in); + if(it != map.end()) + { + it->second.erase(out); + + // If there are no more elements, then remove the entire list + if(it->second.empty()) + map.erase(it); + } + } + + /// Check if a given input is bound to anything + bool isBound(int in) const + { + return map.find(in) != map.end(); + } + + /** + Get the list of outputs bound to the given input. Only call this + on inputs that you know are bound to something. + + The returned set is only intended for immediate iteration. Do not + store references to it. + */ + const OutList &getList(int in) const + { + assert(isBound(in)); + InMap::const_iterator it = map.find(in); + assert(it != map.end()); + const OutList &out = it->second; + assert(!out.empty()); + return out; + } +}; + +} +#endif diff --git a/input/dispatcher.hpp b/input/dispatcher.hpp new file mode 100644 index 000000000..107211a49 --- /dev/null +++ b/input/dispatcher.hpp @@ -0,0 +1,49 @@ +#ifndef _INPUT_DISPATCHER_H +#define _INPUT_DISPATCHER_H + +#include "dispatch_map.hpp" +#include "func_binder.hpp" +#include + +namespace Input { + +struct Dispatcher : Mangle::Input::Event +{ + DispatchMap map; + FuncBinder funcs; + + /** + Constructor. Takes the number of actions and passes it to + FuncBinder. + */ + Dispatcher(int actions) : funcs(actions) {} + + void bind(int action, int key) { map.bind(key, action); } + void unbind(int action, int key) { map.unbind(key, action); } + bool isBound(int key) const { return map.isBound(key); } + + /** + Instigate an event. It is translated through the dispatch map and + sent to the function bindings. + */ + typedef DispatchMap::OutList _O; + void event(Type type, int index, const void* p) + { + // No bindings, nothing happens + if(!isBound(index)) + return; + + // Only treat key-down events for now + if(type != EV_KeyDown) + return; + + // Get the mapped actions and execute them + const _O &list = map.getList(index); + _O::const_iterator it; + for(it = list.begin(); it != list.end(); it++) + funcs.call(*it, p); + } +}; + +} +#endif diff --git a/input/func_binder.hpp b/input/func_binder.hpp new file mode 100644 index 000000000..20119b07b --- /dev/null +++ b/input/func_binder.hpp @@ -0,0 +1,104 @@ +#ifndef _INPUT_FUNCBINDER_H +#define _INPUT_FUNCBINDER_H + +#include +#include +#include +#include + +namespace Input { + +/** + An Action defines the user defined action corresponding to a + binding. + + The first parameter is the action index that invoked this call. You + can assign the same function to multiple actions, and this can help + you keep track of which action was invoked. + + The second parameter is an optional user-defined parameter, + represented by a void pointer. In many cases it is practical to + point this to temporaries (stack values), so make sure not to store + permanent references to it unless you've planning for this on the + calling side as well. + */ +typedef boost::function Action; + +/** + The FuncBinder is a simple struct that binds user-defined indices + to functions. It is useful for binding eg. keyboard events to + specific actions in your program, but can potentially have many + other uses as well. + */ +class FuncBinder +{ + struct FuncBinding + { + std::string name; + Action action; + }; + + std::vector bindings; + +public: + /** + Constructor. Initialize the struct by telling it how many action + indices you intend to bind. + + The indices you use should be 0 <= i < number. + */ + FuncBinder(int number) : bindings(number) {} + + /** + Bind an action to an index. + */ + void bind(int index, Action action, const std::string &name="") + { + assert(index >= 0 && index < (int)bindings.size()); + + FuncBinding &fb = bindings[index]; + fb.action = action; + fb.name = name; + } + + /** + Unbind an index, reverting a previous bind(). + */ + void unbind(int index) + { + assert(index >= 0 && index < (int)bindings.size()); + + bindings[index] = FuncBinding(); + } + + /** + Call a specific action. Takes an optional parameter that is + passed to the action. + */ + void call(int index, const void *p=NULL) const + { + assert(index >= 0 && index < (int)bindings.size()); + + const FuncBinding &fb = bindings[index]; + if(fb.action) fb.action(index, p); + } + + /// Check if a given index is bound to anything + bool isBound(int index) const + { + assert(index >= 0 && index < (int)bindings.size()); + + return !bindings[index].action.empty(); + } + + /// Return the name associated with an action (empty if not bound) + const std::string &getName(int index) const + { + assert(index >= 0 && index < (int)bindings.size()); + + return bindings[index].name; + } +}; + +} +#endif diff --git a/input/poller.hpp b/input/poller.hpp new file mode 100644 index 000000000..794f79b74 --- /dev/null +++ b/input/poller.hpp @@ -0,0 +1,46 @@ +#ifndef _INPUT_POLLER_H +#define _INPUT_POLLER_H + +#include "dispatch_map.hpp" +#include + +namespace Input { + +/** The poller is used to check (poll) for keys rather than waiting + for events. */ +struct Poller +{ + DispatchMap map; + Mangle::Input::Driver &input; + + Poller(Mangle::Input::Driver &drv) + : input(drv) {} + + /** Bind or unbind a given action with a key. The action is the first + parameter, the key is the second. + */ + void bind(int in, int out) { map.bind(in, out); } + void unbind(int in, int out) { map.unbind(in, out); } + bool isBound(int in) const { return map.isBound(in); } + + /// Check whether a given action button is currently pressed. + typedef DispatchMap::OutList _O; + bool isDown(int index) const + { + // No bindings, no action + if(!isBound(index)) + return false; + + // Get all the keys bound to this action, and check them. + const _O &list = map.getList(index); + _O::const_iterator it; + for(it = list.begin(); it != list.end(); it++) + // If there's any match, we're good to go. + if(input.isDown(*it)) return true; + + return false; + } +}; + +} +#endif diff --git a/input/tests/Makefile b/input/tests/Makefile new file mode 100644 index 000000000..91a0b2663 --- /dev/null +++ b/input/tests/Makefile @@ -0,0 +1,18 @@ +GCC=g++ + +all: funcbind_test dispatch_map_test sdl_driver_test sdl_binder_test + +funcbind_test: funcbind_test.cpp ../func_binder.hpp + $(GCC) $< -o $@ + +dispatch_map_test: dispatch_map_test.cpp ../dispatch_map.hpp + $(GCC) $< -o $@ + +sdl_driver_test: sdl_driver_test.cpp + $(GCC) $< ../../mangle/input/servers/sdl_driver.cpp -o $@ -I/usr/include/SDL/ -lSDL -I../../ + +sdl_binder_test: sdl_binder_test.cpp + $(GCC) $< ../../mangle/input/servers/sdl_driver.cpp -o $@ -I/usr/include/SDL/ -lSDL -I../../ + +clean: + rm *_test diff --git a/input/tests/dispatch_map_test.cpp b/input/tests/dispatch_map_test.cpp new file mode 100644 index 000000000..5cc7e1ef2 --- /dev/null +++ b/input/tests/dispatch_map_test.cpp @@ -0,0 +1,54 @@ +#include +using namespace std; + +#include "../dispatch_map.hpp" + +using namespace Input; + +typedef DispatchMap::OutList OutList; +typedef OutList::const_iterator Cit; + +void showList(const DispatchMap::OutList &out) +{ + for(Cit it = out.begin(); + it != out.end(); it++) + { + cout << " " << *it << endl; + } +} + +void showAll(DispatchMap &map) +{ + cout << "\nPrinting everything:\n"; + for(DispatchMap::Iit it = map.map.begin(); + it != map.map.end(); it++) + { + cout << it->first << ":\n"; + showList(map.getList(it->first)); + } +} + +int main() +{ + cout << "Testing the dispatch map\n"; + + DispatchMap dsp; + + dsp.bind(1,9); + dsp.bind(2,-5); + dsp.bind(2,9); + dsp.bind(3,10); + dsp.bind(3,12); + dsp.bind(3,10); + + showAll(dsp); + + dsp.unbind(1,9); + dsp.unbind(5,8); + dsp.unbind(3,11); + dsp.unbind(3,12); + dsp.unbind(3,12); + + showAll(dsp); + return 0; +} diff --git a/input/tests/funcbind_test.cpp b/input/tests/funcbind_test.cpp new file mode 100644 index 000000000..4716f8b81 --- /dev/null +++ b/input/tests/funcbind_test.cpp @@ -0,0 +1,47 @@ +#include +using namespace std; + +#include "../func_binder.hpp" + +void f1(int i, const void *p) +{ + cout << " F1 i=" << i << endl; + + if(p) + cout << " Got a nice gift: " + << *((const float*)p) << endl; +} + +void f2(int i, const void *p) +{ + cout << " F2 i=" << i << endl; +} + +using namespace Input; + +int main() +{ + cout << "This will test the function binding system\n"; + + FuncBinder bnd(5); + + bnd.bind(0, &f1, "This is action 1"); + bnd.bind(1, &f2); + bnd.bind(2, &f1, "This is action 3"); + bnd.bind(3, &f2, "This is action 4"); + + bnd.unbind(2); + + for(int i=0; i<5; i++) + { + cout << "Calling " << i << ": '" << bnd.getName(i) << "'\n"; + bnd.call(i); + if(!bnd.isBound(i)) cout << " (not bound)\n"; + } + + cout << "\nCalling with parameter:\n"; + float f = 3.1415; + bnd.call(0, &f); + + return 0; +} diff --git a/input/tests/output/dispatch_map_test.out b/input/tests/output/dispatch_map_test.out new file mode 100644 index 000000000..01aa9d9d9 --- /dev/null +++ b/input/tests/output/dispatch_map_test.out @@ -0,0 +1,18 @@ +Testing the dispatch map + +Printing everything: +1: + 9 +2: + -5 + 9 +3: + 10 + 12 + +Printing everything: +2: + -5 + 9 +3: + 10 diff --git a/input/tests/output/funcbind_test.out b/input/tests/output/funcbind_test.out new file mode 100644 index 000000000..862c5c972 --- /dev/null +++ b/input/tests/output/funcbind_test.out @@ -0,0 +1,15 @@ +This will test the function binding system +Calling 0: 'This is action 1' + F1 i=0 +Calling 1: '' + F2 i=1 +Calling 2: '' + (not bound) +Calling 3: 'This is action 4' + F2 i=3 +Calling 4: '' + (not bound) + +Calling with parameter: + F1 i=0 + Got a nice gift: 3.1415 diff --git a/input/tests/output/sdl_binder_test.out b/input/tests/output/sdl_binder_test.out new file mode 100644 index 000000000..fd4eb90e3 --- /dev/null +++ b/input/tests/output/sdl_binder_test.out @@ -0,0 +1,4 @@ +Hold the Q key to quit: +You are running in script mode, aborting. Run this test with a parameter (any at all) to test the input loop properly + +Bye bye! diff --git a/input/tests/output/sdl_driver_test.out b/input/tests/output/sdl_driver_test.out new file mode 100644 index 000000000..fd4eb90e3 --- /dev/null +++ b/input/tests/output/sdl_driver_test.out @@ -0,0 +1,4 @@ +Hold the Q key to quit: +You are running in script mode, aborting. Run this test with a parameter (any at all) to test the input loop properly + +Bye bye! diff --git a/input/tests/sdl_binder_test.cpp b/input/tests/sdl_binder_test.cpp new file mode 100644 index 000000000..715e797bb --- /dev/null +++ b/input/tests/sdl_binder_test.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include "../dispatcher.hpp" +#include "../poller.hpp" + +using namespace std; +using namespace Mangle::Input; +using namespace Input; + +enum Actions + { + A_Quit, + A_Left, + A_Right, + + A_LAST + }; + +bool quit=false; + +void doExit(int,const void*) +{ + quit = true; +} + +void goLeft(int,const void*) +{ + cout << "Going left\n"; +} + +int main(int argc, char** argv) +{ + SDL_Init(SDL_INIT_VIDEO); + SDL_SetVideoMode(640, 480, 0, SDL_SWSURFACE); + SDLDriver input; + Dispatcher disp(A_LAST); + Poller poll(input); + + input.setEvent(&disp); + + disp.funcs.bind(A_Quit, &doExit); + disp.funcs.bind(A_Left, &goLeft); + + disp.bind(A_Quit, SDLK_q); + disp.bind(A_Left, SDLK_a); + disp.bind(A_Left, SDLK_LEFT); + + poll.bind(A_Right, SDLK_d); + poll.bind(A_Right, SDLK_RIGHT); + + cout << "Hold the Q key to quit:\n"; + //input->setEvent(&mycb); + while(!quit) + { + input.capture(); + if(poll.isDown(A_Right)) + cout << "We're going right!\n"; + SDL_Delay(20); + + if(argc == 1) + { + cout << "You are running in script mode, aborting. Run this test with a parameter (any at all) to test the input loop properly\n"; + break; + } + } + cout << "\nBye bye!\n"; + + SDL_Quit(); + return 0; +} diff --git a/input/tests/sdl_driver_test.cpp b/input/tests/sdl_driver_test.cpp new file mode 100644 index 000000000..1771bcfe4 --- /dev/null +++ b/input/tests/sdl_driver_test.cpp @@ -0,0 +1,31 @@ +#include +#include +#include + +using namespace std; +using namespace Mangle::Input; + +int main(int argc, char** argv) +{ + SDL_Init(SDL_INIT_VIDEO); + SDL_SetVideoMode(640, 480, 0, SDL_SWSURFACE); + SDLDriver input; + + cout << "Hold the Q key to quit:\n"; + //input->setEvent(&mycb); + while(!input.isDown(SDLK_q)) + { + input.capture(); + SDL_Delay(20); + + if(argc == 1) + { + cout << "You are running in script mode, aborting. Run this test with a parameter (any at all) to test the input loop properly\n"; + break; + } + } + cout << "\nBye bye!\n"; + + SDL_Quit(); + return 0; +} diff --git a/input/tests/test.sh b/input/tests/test.sh new file mode 100755 index 000000000..2d07708ad --- /dev/null +++ b/input/tests/test.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +make || exit + +mkdir -p output + +PROGS=*_test + +for a in $PROGS; do + if [ -f "output/$a.out" ]; then + echo "Running $a:" + ./$a | diff output/$a.out - + else + echo "Creating $a.out" + ./$a > "output/$a.out" + git add "output/$a.out" + fi +done diff --git a/mangle b/mangle new file mode 160000 index 000000000..7583fc3f1 --- /dev/null +++ b/mangle @@ -0,0 +1 @@ +Subproject commit 7583fc3f1bfa6d0fde56c925da959a5e9e50031a diff --git a/testall.sh b/testall.sh new file mode 100755 index 000000000..097fdabd5 --- /dev/null +++ b/testall.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +function run() +{ + echo "TESTING $1" + cd "$1/tests/" + ./test.sh + cd ../../ +} + +run input From fce290104e22a21f11ce3a525e8d9c49bec9fbc8 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Fri, 9 Jul 2010 21:21:04 +0200 Subject: [PATCH 03/56] Added gui/ and ogre/ from OpenMW --- gui/layout.hpp | 118 +++++++++++++++++++++++++++++++++++++++++ gui/manager.cpp | 43 +++++++++++++++ gui/manager.hpp | 33 ++++++++++++ input/dispatch_map.hpp | 4 +- input/dispatcher.hpp | 4 +- input/func_binder.hpp | 4 +- input/poller.hpp | 4 +- ogre/.gitignore | 1 + ogre/renderer.cpp | 80 ++++++++++++++++++++++++++++ ogre/renderer.hpp | 77 +++++++++++++++++++++++++++ 10 files changed, 360 insertions(+), 8 deletions(-) create mode 100644 gui/layout.hpp create mode 100644 gui/manager.cpp create mode 100644 gui/manager.hpp create mode 100644 ogre/.gitignore create mode 100644 ogre/renderer.cpp create mode 100644 ogre/renderer.hpp diff --git a/gui/layout.hpp b/gui/layout.hpp new file mode 100644 index 000000000..7a1b6b86c --- /dev/null +++ b/gui/layout.hpp @@ -0,0 +1,118 @@ +#ifndef OENGINE_MYGUI_LAYOUT_H +#define OENGINE_MYGUI_LAYOUT_H + +#include +#include + +namespace GUI +{ + /** The Layout class is an utility class used to load MyGUI layouts + from xml files, and to manipulate member widgets. + */ + class Layout + { + public: + Layout(const std::string & _layout, MyGUI::WidgetPtr _parent = nullptr) + : mMainWidget(nullptr) + { initialise(_layout, _parent); } + virtual ~Layout() { shutdown(); } + + template + void getWidget(T * & _widget, const std::string & _name, bool _throw = true) + { + _widget = nullptr; + for (MyGUI::VectorWidgetPtr::iterator iter=mListWindowRoot.begin(); + iter!=mListWindowRoot.end(); ++iter) + { + MyGUI::WidgetPtr find = (*iter)->findWidget(mPrefix + _name); + if (nullptr != find) + { + T * cast = find->castType(false); + if (nullptr != cast) + _widget = cast; + else if (_throw) + { + MYGUI_EXCEPT("Error cast : dest type = '" << T::getClassTypeName() + << "' source name = '" << find->getName() + << "' source type = '" << find->getTypeName() << "' in layout '" << mLayoutName << "'"); + } + return; + } + } + MYGUI_ASSERT( ! _throw, "widget name '" << _name << "' in layout '" << mLayoutName << "' not found."); + } + + void initialise(const std::string & _layout, + MyGUI::WidgetPtr _parent = nullptr) + { + const std::string MAIN_WINDOW = "_Main"; + mLayoutName = _layout; + + if (mLayoutName.empty()) + mMainWidget = _parent; + else + { + mPrefix = MyGUI::utility::toString(this, "_"); + mListWindowRoot = MyGUI::LayoutManager::getInstance().loadLayout(mLayoutName, mPrefix, _parent); + + const std::string main_name = mPrefix + MAIN_WINDOW; + for (MyGUI::VectorWidgetPtr::iterator iter=mListWindowRoot.begin(); iter!=mListWindowRoot.end(); ++iter) + { + if ((*iter)->getName() == main_name) + { + mMainWidget = (*iter); + break; + } + } + MYGUI_ASSERT(mMainWidget, "root widget name '" << MAIN_WINDOW << "' in layout '" << mLayoutName << "' not found."); + } + } + + void shutdown() + { + MyGUI::LayoutManager::getInstance().unloadLayout(mListWindowRoot); + mListWindowRoot.clear(); + } + + void setCoord(int x, int y, int w, int h) + { + mMainWidget->setCoord(x,y,w,h); + } + + void setVisible(bool b) + { + mMainWidget->setVisible(b); + } + + void setText(const std::string& name, const std::string& caption) + { + MyGUI::WidgetPtr pt; + getWidget(pt, name); + pt->setCaption(caption); + } + + void setTextColor(const std::string& name, float r, float g, float b) + { + MyGUI::WidgetPtr pt; + getWidget(pt, name); + MyGUI::StaticText *st = dynamic_cast(pt); + if(st != NULL) + st->setTextColour(MyGUI::Colour(b,g,r)); + } + + void setImage(const std::string& name, const std::string& imgName) + { + MyGUI::StaticImagePtr pt; + getWidget(pt, name); + pt->setImageTexture(imgName); + } + + protected: + + MyGUI::WidgetPtr mMainWidget; + std::string mPrefix; + std::string mLayoutName; + MyGUI::VectorWidgetPtr mListWindowRoot; + }; +} +#endif diff --git a/gui/manager.cpp b/gui/manager.cpp new file mode 100644 index 000000000..e5e01e7d7 --- /dev/null +++ b/gui/manager.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "manager.hpp" + +using namespace GUI; + +void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging) +{ + assert(wnd); + assert(mgr); + + using namespace MyGUI; + + // Enable/disable MyGUI logging to stdout. (Logging to MyGUI.log is + // still enabled.) In order to do this we have to initialize the log + // manager before the main gui system itself, otherwise the main + // object will get the chance to spit out a few messages before we + // can able to disable it. + LogManager::initialise(); + LogManager::setSTDOutputEnabled(logging); + + // Set up OGRE platform. We might make this more generic later. + mPlatform = new OgrePlatform(); + mPlatform->initialise(wnd, mgr); + + // Create GUI + mGui = new Gui(); + mGui->initialise(); +} + +void MyGUIManager::shutdown() +{ + if(mGui) delete mGui; + if(mPlatform) + { + mPlatform->shutdown(); + delete mPlatform; + } + mGui = NULL; + mPlatform = NULL; +} diff --git a/gui/manager.hpp b/gui/manager.hpp new file mode 100644 index 000000000..3669c0cb2 --- /dev/null +++ b/gui/manager.hpp @@ -0,0 +1,33 @@ +#ifndef OENGINE_MYGUI_MANAGER_H +#define OENGINE_MYGUI_MANAGER_H + +namespace MyGUI +{ + class OgrePlatform; + class Gui; +} + +namespace Ogre +{ + class RenderWindow; + class SceneManager; +} + +namespace GUI +{ + class MyGUIManager + { + MyGUI::OgrePlatform *mPlatform; + MyGUI::Gui *mGui; + + public: + MyGUIManager() : mPlatform(NULL), mGui(NULL) {} + MyGUIManager(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging=false) + { setup(wnd,mgr,logging); } + ~MyGUIManager() { shutdown(); } + + void setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging=false); + void shutdown(); + }; +} +#endif diff --git a/input/dispatch_map.hpp b/input/dispatch_map.hpp index 356660e75..a8e03e18d 100644 --- a/input/dispatch_map.hpp +++ b/input/dispatch_map.hpp @@ -1,5 +1,5 @@ -#ifndef _INPUT_DISPATCHMAP_H -#define _INPUT_DISPATCHMAP_H +#ifndef OENGINE_INPUT_DISPATCHMAP_H +#define OENGINE_INPUT_DISPATCHMAP_H #include #include diff --git a/input/dispatcher.hpp b/input/dispatcher.hpp index 107211a49..0a9cfd795 100644 --- a/input/dispatcher.hpp +++ b/input/dispatcher.hpp @@ -1,5 +1,5 @@ -#ifndef _INPUT_DISPATCHER_H -#define _INPUT_DISPATCHER_H +#ifndef OENGINE_INPUT_DISPATCHER_H +#define OENGINE_INPUT_DISPATCHER_H #include "dispatch_map.hpp" #include "func_binder.hpp" diff --git a/input/func_binder.hpp b/input/func_binder.hpp index 20119b07b..234971bae 100644 --- a/input/func_binder.hpp +++ b/input/func_binder.hpp @@ -1,5 +1,5 @@ -#ifndef _INPUT_FUNCBINDER_H -#define _INPUT_FUNCBINDER_H +#ifndef OENGINE_INPUT_FUNCBINDER_H +#define OENGINE_INPUT_FUNCBINDER_H #include #include diff --git a/input/poller.hpp b/input/poller.hpp index 794f79b74..9c93fe1bf 100644 --- a/input/poller.hpp +++ b/input/poller.hpp @@ -1,5 +1,5 @@ -#ifndef _INPUT_POLLER_H -#define _INPUT_POLLER_H +#ifndef OENGINE_INPUT_POLLER_H +#define OENGINE_INPUT_POLLER_H #include "dispatch_map.hpp" #include diff --git a/ogre/.gitignore b/ogre/.gitignore new file mode 100644 index 000000000..3367afdbb --- /dev/null +++ b/ogre/.gitignore @@ -0,0 +1 @@ +old diff --git a/ogre/renderer.cpp b/ogre/renderer.cpp new file mode 100644 index 000000000..982f0f050 --- /dev/null +++ b/ogre/renderer.cpp @@ -0,0 +1,80 @@ +#include "renderer.hpp" + +#include "OgreRoot.h" +#include "OgreRenderWindow.h" +#include "OgreLogManager.h" +#include "OgreLog.h" + +#include + +using namespace Ogre; +using namespace Render; + +void OgreRenderer::cleanup() +{ + if(mRoot) + delete mRoot; + mRoot = NULL; +} + +void OgreRenderer::screenshot(const std::string &file) +{ + mWindow->writeContentsToFile(file); +} + +bool OgreRenderer::configure(bool showConfig, + const std::string &pluginCfg, + bool _logging) +{ + // Set up logging first + new LogManager; + Log *log = LogManager::getSingleton().createLog("Ogre.log"); + logging = _logging; + + if(logging) + // Full log detail + log->setLogDetail(LL_BOREME); + else + // Disable logging + log->setDebugOutputEnabled(false); + + mRoot = new Root(pluginCfg, "ogre.cfg", ""); + + // Show the configuration dialog and initialise the system, if the + // showConfig parameter is specified. The settings are stored in + // ogre.cfg. If showConfig is false, the settings are assumed to + // already exist in ogre.cfg. + int result; + if(showConfig) + result = mRoot->showConfigDialog(); + else + result = mRoot->restoreConfig(); + + return !result; +} + +void OgreRenderer::createWindow(const std::string &title) +{ + assert(mRoot); + // Initialize OGRE window + mWindow = mRoot->initialise(true, title, ""); +} + +void OgreRenderer::createScene(const std::string camName, float fov, float nearClip) +{ + assert(mRoot); + assert(mWindow); + // Get the SceneManager, in this case a generic one + mScene = mRoot->createSceneManager(ST_GENERIC); + + // Create the camera + mCamera = mScene->createCamera(camName); + mCamera->setNearClipDistance(nearClip); + mCamera->setFOVy(Degree(fov)); + + // Create one viewport, entire window + mView = mWindow->addViewport(mCamera); + + // Alter the camera aspect ratio to match the viewport + mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); +} diff --git a/ogre/renderer.hpp b/ogre/renderer.hpp new file mode 100644 index 000000000..12dada2d5 --- /dev/null +++ b/ogre/renderer.hpp @@ -0,0 +1,77 @@ +#ifndef OENGINE_OGRE_RENDERER_H +#define OENGINE_OGRE_RENDERER_H + +/* + Ogre renderer class + */ + +#include +#include + +namespace Ogre +{ + class Root; + class RenderWindow; + class SceneManager; + class Camera; + class Viewport; +} + +namespace Render +{ + class OgreRenderer + { + Ogre::Root *mRoot; + Ogre::RenderWindow *mWindow; + Ogre::SceneManager *mScene; + Ogre::Camera *mCamera; + Ogre::Viewport *mView; + bool logging; + + public: + OgreRenderer() + : mRoot(NULL), mWindow(NULL), mScene(NULL) {} + ~OgreRenderer() { cleanup(); } + + /** Configure the renderer. This will load configuration files and + set up the Root and logging classes. */ + bool configure(bool showConfig, // Show config dialog box? + const std::string &pluginCfg, // plugin.cfg file + bool _logging); // Enable or disable logging + + /// Create a window with the given title + void createWindow(const std::string &title); + + /// Set up the scene manager, camera and viewport + void createScene(const std::string camName="Camera",// Camera name + float fov=55, // Field of view angle + float nearClip=5 // Near clip distance + ); + + /// Kill the renderer. + void cleanup(); + + /// Start the main rendering loop + void start() { mRoot->startRendering(); } + + /// Write a screenshot to file + void screenshot(const std::string &file); + + /// Get the Root + Ogre::Root *getRoot() { return mRoot; } + + /// Get the rendering window + Ogre::RenderWindow *getWindow() { return mWindow; } + + /// Get the scene manager + Ogre::SceneManager *getScene() { return mScene; } + + /// Camera + Ogre::Camera *getCamera() { return mCamera; } + + /// Viewport + Ogre::Viewport *getViewport() { return mView; } + }; +} + +#endif From e55ef227fe3bd9ce8f05b1f4a7cf8a6f62643acb Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Sat, 10 Jul 2010 12:34:48 +0200 Subject: [PATCH 04/56] Updated to latest Mangle --- mangle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mangle b/mangle index 7583fc3f1..18dc06571 160000 --- a/mangle +++ b/mangle @@ -1 +1 @@ -Subproject commit 7583fc3f1bfa6d0fde56c925da959a5e9e50031a +Subproject commit 18dc065715c12fd8793f8793c7bf834619527399 From b9b306cd4c14147c78d9c59d6e1edd97820ef036 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Sat, 10 Jul 2010 13:25:04 +0200 Subject: [PATCH 05/56] Added event listeners (mouselook and gui injector) and exit listener for Ogre --- gui/events.cpp | 23 ++++++++++++++++++ gui/events.hpp | 26 +++++++++++++++++++++ ogre/exitlistener.hpp | 33 ++++++++++++++++++++++++++ ogre/mouselook.cpp | 36 +++++++++++++++++++++++++++++ ogre/mouselook.hpp | 54 +++++++++++++++++++++++++++++++++++++++++++ ogre/renderer.cpp | 5 ++++ ogre/renderer.hpp | 3 +-- 7 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 gui/events.cpp create mode 100644 gui/events.hpp create mode 100644 ogre/exitlistener.hpp create mode 100644 ogre/mouselook.cpp create mode 100644 ogre/mouselook.hpp diff --git a/gui/events.cpp b/gui/events.cpp new file mode 100644 index 000000000..39b5e9f1c --- /dev/null +++ b/gui/events.cpp @@ -0,0 +1,23 @@ +#include +#include + +using namespace MyGUI; +using namespace OIS; + +void EventInjector::event(Type type, int index, const void *p) +{ + if(enabled) return; + + KeyEvent *key = (KeyEvent*)p; + MouseEvent *mouse = (MouseEvent*)p; + MouseButtonID id = (MouseButtonID)index; + + switch(type) + { + case EV_KeyDown: gui->injectKeyPress(key); break; + case EV_KeyUp: gui->injectKeyRelease(key); break; + case EV_MouseDown: gui->injectMousePress(mouse, id); break; + case EV_MouseUp: gui->injectMouseRelease(mouse, id); break; + case EV_MouseMove: gui->injectMouseMove(mouse); break; + } +} diff --git a/gui/events.hpp b/gui/events.hpp new file mode 100644 index 000000000..b994a422d --- /dev/null +++ b/gui/events.hpp @@ -0,0 +1,26 @@ +#ifndef OENGINE_MYGUI_EVENTS_H +#define OENGINE_MYGUI_EVENTS_H + +#include + +namespace MyGUI +{ + class Gui; +} + +namespace GUI +{ + /** Event handler that injects OIS events into MyGUI + */ + class EventInjector : Mangle::Input::Event + { + MyGUI::Gui *gui; + + public: + bool enabled; + + EventInjector(MyGUI::Gui *g) : gui(g), enabled(true) {} + void event(Type type, int index, const void *p); + }; +} +#endif diff --git a/ogre/exitlistener.hpp b/ogre/exitlistener.hpp new file mode 100644 index 000000000..e1af9604f --- /dev/null +++ b/ogre/exitlistener.hpp @@ -0,0 +1,33 @@ +#ifndef OENGINE_OGRE_EXITLISTEN_H +#define OENGINE_OGRE_EXITLISTEN_H + +/* + This FrameListener simply exits the rendering loop when the window + is closed. You can also tell it to exit manually by setting the exit + member to true; + */ + +#include +#include + +namespace Render +{ + struct ExitListener : Ogre::FrameListener + { + Ogre::RenderWindow *window; + bool exit; + + ExitListener(Ogre::RenderWindow *wnd) + : window(wnd), exit(false) {} + + bool frameStarted(const FrameEvent &evt) + { + if(window->isClosed()) + exit = true; + + return !exit; + } + }; +} + +#endif diff --git a/ogre/mouselook.cpp b/ogre/mouselook.cpp new file mode 100644 index 000000000..d4d15cee9 --- /dev/null +++ b/ogre/mouselook.cpp @@ -0,0 +1,36 @@ +#include "mouselook.hpp" + +#include +#include + +using namespace OIS; +using namespace Ogre; + +void MouseLookEvent::event(Type type, int index, const void *p) +{ + if(type != EV_MouseMove || camera == NULL) return; + + MouseEvent *arg = (MouseEvent*)(p); + + float x = arg->state.X.rel * sensX; + float y = arg->state.Y.rel * sensY; + + camera->yaw(Degree(-x)); + + if(flipProt) + { + // The camera before pitching + Quaternion nopitch = camera->getOrientation(); + + camera->pitch(Degree(-y)); + + // Apply some failsafe measures against the camera flipping + // upside down. Is the camera close to pointing straight up or + // down? + if(camera->getUp()[1] <= 0.1) + // If so, undo the last pitch + camera->setOrientation(nopitch); + } + else + camera->pitch(Degree(-y)); +} diff --git a/ogre/mouselook.hpp b/ogre/mouselook.hpp new file mode 100644 index 000000000..0b11c0b79 --- /dev/null +++ b/ogre/mouselook.hpp @@ -0,0 +1,54 @@ +#ifndef OENGINE_OGRE_MOUSELOOK_H +#define OENGINE_OGRE_MOUSELOOK_H + +/* + A mouse-look class for Ogre. Accepts input events from Mangle::Input + and translates them. + + You can adjust the mouse sensibility and switch to a different + camera. The mouselook class also has an optional wrap protection + that keeps the camera from flipping upside down. + + You can disable the mouse looker at any time by calling + setCamera(NULL), and reenable it by setting the camera back. + + NOTE: The current implementation will ONLY work for native OIS + events. + */ + +#include + +namespace Ogre +{ + class Camera; +} + +namespace Render +{ + class MouseLookEvent : public Mangle::Input::Event + { + Ogre::Camera* camera; + float sensX, sensY; // Mouse sensibility + bool flipProt; // Flip protection + + public: + MouseLookEvent(Ogre::Camera *cam=NULL, + float sX=0.2, float sY=0.2, + bool prot=true) + : camera(cam) + , sensX(sX) + , sensY(sy) + , flipProt(prot) + {} + + void setCamera(Ogre::Camera *cam) + { camera = cam; } + void setSens(float sX, float sY) + { sensX = sX; sensY = sY; } + void setProt(bool p) { flipProt = p; } + + void event(Type type, int index, const void *p); + }; +} + +#endif diff --git a/ogre/renderer.cpp b/ogre/renderer.cpp index 982f0f050..86382127c 100644 --- a/ogre/renderer.cpp +++ b/ogre/renderer.cpp @@ -17,6 +17,11 @@ void OgreRenderer::cleanup() mRoot = NULL; } +void OgreRenderer::start() +{ + mRoot->startRendering(); +} + void OgreRenderer::screenshot(const std::string &file) { mWindow->writeContentsToFile(file); diff --git a/ogre/renderer.hpp b/ogre/renderer.hpp index 12dada2d5..ac44f5ee1 100644 --- a/ogre/renderer.hpp +++ b/ogre/renderer.hpp @@ -5,7 +5,6 @@ Ogre renderer class */ -#include #include namespace Ogre @@ -52,7 +51,7 @@ namespace Render void cleanup(); /// Start the main rendering loop - void start() { mRoot->startRendering(); } + void start(); /// Write a screenshot to file void screenshot(const std::string &file); From 5333b8e230e285e9183b0639188283bdbc15af6c Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Sat, 10 Jul 2010 13:41:43 +0200 Subject: [PATCH 06/56] Fixed namespaces, added OEngine:: to everything --- gui/events.cpp | 3 +++ gui/events.hpp | 3 ++- gui/layout.hpp | 3 ++- gui/manager.cpp | 2 +- gui/manager.hpp | 3 ++- input/dispatch_map.hpp | 4 ++-- input/dispatcher.hpp | 4 ++-- input/func_binder.hpp | 4 ++-- input/poller.hpp | 4 ++-- input/tests/dispatch_map_test.cpp | 2 +- input/tests/funcbind_test.cpp | 2 +- input/tests/sdl_binder_test.cpp | 16 ++++++++-------- ogre/exitlistener.hpp | 4 ++-- ogre/mouselook.cpp | 1 + ogre/mouselook.hpp | 4 ++-- ogre/renderer.cpp | 2 +- ogre/renderer.hpp | 4 ++-- 17 files changed, 36 insertions(+), 29 deletions(-) diff --git a/gui/events.cpp b/gui/events.cpp index 39b5e9f1c..146d3ea80 100644 --- a/gui/events.cpp +++ b/gui/events.cpp @@ -1,8 +1,11 @@ #include #include +#include "events.hpp" + using namespace MyGUI; using namespace OIS; +using namespace OEngine::GUI; void EventInjector::event(Type type, int index, const void *p) { diff --git a/gui/events.hpp b/gui/events.hpp index b994a422d..ec483536a 100644 --- a/gui/events.hpp +++ b/gui/events.hpp @@ -8,6 +8,7 @@ namespace MyGUI class Gui; } +namespace OEngine { namespace GUI { /** Event handler that injects OIS events into MyGUI @@ -22,5 +23,5 @@ namespace GUI EventInjector(MyGUI::Gui *g) : gui(g), enabled(true) {} void event(Type type, int index, const void *p); }; -} +}} #endif diff --git a/gui/layout.hpp b/gui/layout.hpp index 7a1b6b86c..f02ddbdff 100644 --- a/gui/layout.hpp +++ b/gui/layout.hpp @@ -4,6 +4,7 @@ #include #include +namespace OEngine { namespace GUI { /** The Layout class is an utility class used to load MyGUI layouts @@ -114,5 +115,5 @@ namespace GUI std::string mLayoutName; MyGUI::VectorWidgetPtr mListWindowRoot; }; -} +}} #endif diff --git a/gui/manager.cpp b/gui/manager.cpp index e5e01e7d7..564a33cfe 100644 --- a/gui/manager.cpp +++ b/gui/manager.cpp @@ -4,7 +4,7 @@ #include "manager.hpp" -using namespace GUI; +using namespace OEngine::GUI; void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging) { diff --git a/gui/manager.hpp b/gui/manager.hpp index 3669c0cb2..5f67e9f91 100644 --- a/gui/manager.hpp +++ b/gui/manager.hpp @@ -13,6 +13,7 @@ namespace Ogre class SceneManager; } +namespace OEngine { namespace GUI { class MyGUIManager @@ -29,5 +30,5 @@ namespace GUI void setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging=false); void shutdown(); }; -} +}} #endif diff --git a/input/dispatch_map.hpp b/input/dispatch_map.hpp index a8e03e18d..f0d4cabe9 100644 --- a/input/dispatch_map.hpp +++ b/input/dispatch_map.hpp @@ -5,6 +5,7 @@ #include #include +namespace OEngine { namespace Input { /** @@ -70,6 +71,5 @@ struct DispatchMap return out; } }; - -} +}} #endif diff --git a/input/dispatcher.hpp b/input/dispatcher.hpp index 0a9cfd795..bba13893d 100644 --- a/input/dispatcher.hpp +++ b/input/dispatcher.hpp @@ -5,6 +5,7 @@ #include "func_binder.hpp" #include +namespace OEngine { namespace Input { struct Dispatcher : Mangle::Input::Event @@ -44,6 +45,5 @@ struct Dispatcher : Mangle::Input::Event funcs.call(*it, p); } }; - -} +}} #endif diff --git a/input/func_binder.hpp b/input/func_binder.hpp index 234971bae..d2bfd53e5 100644 --- a/input/func_binder.hpp +++ b/input/func_binder.hpp @@ -6,6 +6,7 @@ #include #include +namespace OEngine { namespace Input { /** @@ -99,6 +100,5 @@ public: return bindings[index].name; } }; - -} +}} #endif diff --git a/input/poller.hpp b/input/poller.hpp index 9c93fe1bf..c544aed52 100644 --- a/input/poller.hpp +++ b/input/poller.hpp @@ -4,6 +4,7 @@ #include "dispatch_map.hpp" #include +namespace OEngine { namespace Input { /** The poller is used to check (poll) for keys rather than waiting @@ -41,6 +42,5 @@ struct Poller return false; } }; - -} +}} #endif diff --git a/input/tests/dispatch_map_test.cpp b/input/tests/dispatch_map_test.cpp index 5cc7e1ef2..5f262494e 100644 --- a/input/tests/dispatch_map_test.cpp +++ b/input/tests/dispatch_map_test.cpp @@ -3,7 +3,7 @@ using namespace std; #include "../dispatch_map.hpp" -using namespace Input; +using namespace OEngine::Input; typedef DispatchMap::OutList OutList; typedef OutList::const_iterator Cit; diff --git a/input/tests/funcbind_test.cpp b/input/tests/funcbind_test.cpp index 4716f8b81..bb4ad34e1 100644 --- a/input/tests/funcbind_test.cpp +++ b/input/tests/funcbind_test.cpp @@ -17,7 +17,7 @@ void f2(int i, const void *p) cout << " F2 i=" << i << endl; } -using namespace Input; +using namespace OEngine::Input; int main() { diff --git a/input/tests/sdl_binder_test.cpp b/input/tests/sdl_binder_test.cpp index 715e797bb..7de5f5d4f 100644 --- a/input/tests/sdl_binder_test.cpp +++ b/input/tests/sdl_binder_test.cpp @@ -6,7 +6,7 @@ using namespace std; using namespace Mangle::Input; -using namespace Input; +using namespace OEngine::Input; enum Actions { @@ -34,17 +34,17 @@ int main(int argc, char** argv) SDL_Init(SDL_INIT_VIDEO); SDL_SetVideoMode(640, 480, 0, SDL_SWSURFACE); SDLDriver input; - Dispatcher disp(A_LAST); + Dispatcher *disp = new Dispatcher(A_LAST); Poller poll(input); - input.setEvent(&disp); + input.setEvent(EventPtr(disp)); - disp.funcs.bind(A_Quit, &doExit); - disp.funcs.bind(A_Left, &goLeft); + disp->funcs.bind(A_Quit, &doExit); + disp->funcs.bind(A_Left, &goLeft); - disp.bind(A_Quit, SDLK_q); - disp.bind(A_Left, SDLK_a); - disp.bind(A_Left, SDLK_LEFT); + disp->bind(A_Quit, SDLK_q); + disp->bind(A_Left, SDLK_a); + disp->bind(A_Left, SDLK_LEFT); poll.bind(A_Right, SDLK_d); poll.bind(A_Right, SDLK_RIGHT); diff --git a/ogre/exitlistener.hpp b/ogre/exitlistener.hpp index e1af9604f..ed07ee55c 100644 --- a/ogre/exitlistener.hpp +++ b/ogre/exitlistener.hpp @@ -10,6 +10,7 @@ #include #include +namespace OEngine { namespace Render { struct ExitListener : Ogre::FrameListener @@ -28,6 +29,5 @@ namespace Render return !exit; } }; -} - +}} #endif diff --git a/ogre/mouselook.cpp b/ogre/mouselook.cpp index d4d15cee9..84e6e0397 100644 --- a/ogre/mouselook.cpp +++ b/ogre/mouselook.cpp @@ -5,6 +5,7 @@ using namespace OIS; using namespace Ogre; +using namespace OEngine::Render; void MouseLookEvent::event(Type type, int index, const void *p) { diff --git a/ogre/mouselook.hpp b/ogre/mouselook.hpp index 0b11c0b79..b5c784945 100644 --- a/ogre/mouselook.hpp +++ b/ogre/mouselook.hpp @@ -23,6 +23,7 @@ namespace Ogre class Camera; } +namespace OEngine { namespace Render { class MouseLookEvent : public Mangle::Input::Event @@ -49,6 +50,5 @@ namespace Render void event(Type type, int index, const void *p); }; -} - +}} #endif diff --git a/ogre/renderer.cpp b/ogre/renderer.cpp index 86382127c..c60a29c77 100644 --- a/ogre/renderer.cpp +++ b/ogre/renderer.cpp @@ -8,7 +8,7 @@ #include using namespace Ogre; -using namespace Render; +using namespace OEngine::Render; void OgreRenderer::cleanup() { diff --git a/ogre/renderer.hpp b/ogre/renderer.hpp index ac44f5ee1..f706b16f7 100644 --- a/ogre/renderer.hpp +++ b/ogre/renderer.hpp @@ -16,6 +16,7 @@ namespace Ogre class Viewport; } +namespace OEngine { namespace Render { class OgreRenderer @@ -71,6 +72,5 @@ namespace Render /// Viewport Ogre::Viewport *getViewport() { return mView; } }; -} - +}} #endif From 0e30756ba17824df01ce53e7b5696a02972c6825 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Fri, 16 Jul 2010 14:25:19 +0200 Subject: [PATCH 07/56] Fixed for OpenMW compilation --- input/dispatcher.hpp | 9 +++++---- ogre/exitlistener.hpp | 6 +++++- ogre/mouselook.hpp | 4 +++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/input/dispatcher.hpp b/input/dispatcher.hpp index bba13893d..930195856 100644 --- a/input/dispatcher.hpp +++ b/input/dispatcher.hpp @@ -34,10 +34,6 @@ struct Dispatcher : Mangle::Input::Event if(!isBound(index)) return; - // Only treat key-down events for now - if(type != EV_KeyDown) - return; - // Get the mapped actions and execute them const _O &list = map.getList(index); _O::const_iterator it; @@ -45,5 +41,10 @@ struct Dispatcher : Mangle::Input::Event funcs.call(*it, p); } }; + +// This helps us play nice with Mangle's EventPtr, but it should +// really be defined for all the classes in OEngine. + typedef boost::shared_ptr DispatcherPtr; + }} #endif diff --git a/ogre/exitlistener.hpp b/ogre/exitlistener.hpp index ed07ee55c..5a9d1ff68 100644 --- a/ogre/exitlistener.hpp +++ b/ogre/exitlistener.hpp @@ -21,13 +21,17 @@ namespace Render ExitListener(Ogre::RenderWindow *wnd) : window(wnd), exit(false) {} - bool frameStarted(const FrameEvent &evt) + bool frameStarted(const Ogre::FrameEvent &evt) { if(window->isClosed()) exit = true; return !exit; } + + // Function equivalent of setting exit=true. Handy when you need a + // delegate to bind to an event. + void exitNow() { exit = true; } }; }} #endif diff --git a/ogre/mouselook.hpp b/ogre/mouselook.hpp index b5c784945..6e09ff4a1 100644 --- a/ogre/mouselook.hpp +++ b/ogre/mouselook.hpp @@ -38,7 +38,7 @@ namespace Render bool prot=true) : camera(cam) , sensX(sX) - , sensY(sy) + , sensY(sY) , flipProt(prot) {} @@ -50,5 +50,7 @@ namespace Render void event(Type type, int index, const void *p); }; + + typedef boost::shared_ptr MouseLookEventPtr; }} #endif From 69a56e867749944dc0e86b9ef5c54bac4339b454 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Fri, 16 Jul 2010 14:54:41 +0200 Subject: [PATCH 08/56] Added more safety asserts to input dispatcher --- input/dispatcher.hpp | 13 +++++++++++-- input/func_binder.hpp | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/input/dispatcher.hpp b/input/dispatcher.hpp index 930195856..dd6fb6bf6 100644 --- a/input/dispatcher.hpp +++ b/input/dispatcher.hpp @@ -4,6 +4,7 @@ #include "dispatch_map.hpp" #include "func_binder.hpp" #include +#include namespace OEngine { namespace Input { @@ -19,8 +20,16 @@ struct Dispatcher : Mangle::Input::Event */ Dispatcher(int actions) : funcs(actions) {} - void bind(int action, int key) { map.bind(key, action); } - void unbind(int action, int key) { map.unbind(key, action); } + void bind(unsigned int action, int key) + { + assert(action < funcs.getSize()); + map.bind(key, action); + } + void unbind(unsigned int action, int key) + { + assert(action < funcs.getSize()); + map.unbind(key, action); + } bool isBound(int key) const { return map.isBound(key); } /** diff --git a/input/func_binder.hpp b/input/func_binder.hpp index d2bfd53e5..7aa733edf 100644 --- a/input/func_binder.hpp +++ b/input/func_binder.hpp @@ -50,6 +50,8 @@ public: */ FuncBinder(int number) : bindings(number) {} + unsigned int getSize() { return bindings.size(); } + /** Bind an action to an index. */ From fedb1a80256a093511075aeb88408c7c56a136ce Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Fri, 16 Jul 2010 21:46:57 +0200 Subject: [PATCH 09/56] Fixed up the OIS->MyGUI event dispatcher --- gui/events.cpp | 57 +++++++++++++++++++++++++++++++++++++++---------- gui/events.hpp | 2 +- gui/manager.hpp | 2 ++ 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/gui/events.cpp b/gui/events.cpp index 146d3ea80..6e4d53309 100644 --- a/gui/events.cpp +++ b/gui/events.cpp @@ -3,24 +3,59 @@ #include "events.hpp" -using namespace MyGUI; using namespace OIS; using namespace OEngine::GUI; void EventInjector::event(Type type, int index, const void *p) { - if(enabled) return; + if(!enabled) return; - KeyEvent *key = (KeyEvent*)p; - MouseEvent *mouse = (MouseEvent*)p; - MouseButtonID id = (MouseButtonID)index; + if(type & EV_Keyboard) + { + KeyEvent *key = (KeyEvent*)p; + MyGUI::KeyCode code = MyGUI::KeyCode::Enum(key->key); + if(type == EV_KeyDown) + { + /* + This is just a first approximation. Apparently, OIS sucks + to such a degree that it's unable to provide any sort of + reliable unicode character on all platforms and for all + keys. At least that's what I surmise from the amount of + workaround that the MyGUI folks have put in place for + this. See Common/Input/OIS/InputManager.cpp in the MyGUI + sources for details. If this is indeed necessary (I + haven't tested that it is, although I have had dubious + experinces with OIS events in the past), then we should + probably adapt all that code here. Or even better, + directly into the OIS input manager in Mangle. - switch(type) + Note that all this only affects the 'text' field, and + should thus only affect typed text in input boxes (which + is still pretty significant.) + */ + MyGUI::Char text = (MyGUI::Char)key->text; + gui->injectKeyPress(code,text); + } + else + { + gui->injectKeyRelease(code); + } + } + else if(type & EV_Mouse) { - case EV_KeyDown: gui->injectKeyPress(key); break; - case EV_KeyUp: gui->injectKeyRelease(key); break; - case EV_MouseDown: gui->injectMousePress(mouse, id); break; - case EV_MouseUp: gui->injectMouseRelease(mouse, id); break; - case EV_MouseMove: gui->injectMouseMove(mouse); break; + MouseEvent *mouse = (MouseEvent*)p; + MyGUI::MouseButton id = MyGUI::MouseButton::Enum(index); + + // I'm not sure these should be used directly, MyGUI demo code + // use local mouse position variables. + int mouseX = mouse->state.X.abs; + int mouseY = mouse->state.Y.abs; + + if(type == EV_MouseDown) + gui->injectMousePress(mouseX, mouseY, id); + else if(type == EV_MouseUp) + gui->injectMouseRelease(mouseX, mouseY, id); + else + gui->injectMouseMove(mouseX, mouseY, mouse->state.Z.abs); } } diff --git a/gui/events.hpp b/gui/events.hpp index ec483536a..f43884845 100644 --- a/gui/events.hpp +++ b/gui/events.hpp @@ -13,7 +13,7 @@ namespace GUI { /** Event handler that injects OIS events into MyGUI */ - class EventInjector : Mangle::Input::Event + class EventInjector : public Mangle::Input::Event { MyGUI::Gui *gui; diff --git a/gui/manager.hpp b/gui/manager.hpp index 5f67e9f91..e59b4b54b 100644 --- a/gui/manager.hpp +++ b/gui/manager.hpp @@ -29,6 +29,8 @@ namespace GUI void setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging=false); void shutdown(); + + MyGUI::Gui *getGui() { return mGui; } }; }} #endif From 82a3c071e56f2df451618e1371424c39aa299690 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Sat, 17 Jul 2010 19:29:39 +0200 Subject: [PATCH 10/56] Added EventInjectorPtr definition --- gui/events.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gui/events.hpp b/gui/events.hpp index f43884845..17415906d 100644 --- a/gui/events.hpp +++ b/gui/events.hpp @@ -23,5 +23,7 @@ namespace GUI EventInjector(MyGUI::Gui *g) : gui(g), enabled(true) {} void event(Type type, int index, const void *p); }; + + typedef boost::shared_ptr EventInjectorPtr; }} #endif From c04d72cbe380217c2d1d60f8a2c6e4810fe4c050 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Tue, 20 Jul 2010 20:22:15 +0200 Subject: [PATCH 11/56] Let gui/events handle mouse position locally, makes it remember position when disabled and reenabled. --- gui/events.cpp | 39 +++++++++++++++++++++++++++++---------- gui/events.hpp | 4 +++- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/gui/events.cpp b/gui/events.cpp index 6e4d53309..73274ee50 100644 --- a/gui/events.cpp +++ b/gui/events.cpp @@ -1,11 +1,27 @@ #include #include +#include #include "events.hpp" using namespace OIS; using namespace OEngine::GUI; +EventInjector::EventInjector(MyGUI::Gui *g) + : gui(g), mouseX(0), mouseY(0), enabled(true) +{ + assert(gui); + maxX = gui->getViewWidth(); + maxY = gui->getViewHeight(); +} + +template +void setRange(X &x, X min, X max) +{ + if(x < min) x = min; + else if(x > max) x = max; +} + void EventInjector::event(Type type, int index, const void *p) { if(!enabled) return; @@ -17,13 +33,14 @@ void EventInjector::event(Type type, int index, const void *p) if(type == EV_KeyDown) { /* - This is just a first approximation. Apparently, OIS sucks - to such a degree that it's unable to provide any sort of - reliable unicode character on all platforms and for all - keys. At least that's what I surmise from the amount of - workaround that the MyGUI folks have put in place for + This is just a first approximation. Apparently, OIS is + unable to provide reliable unicode characters on all + platforms. At least that's what I surmise from the amount + of workaround that the MyGUI folks have put in place for this. See Common/Input/OIS/InputManager.cpp in the MyGUI - sources for details. If this is indeed necessary (I + sources for details. + + If the work they have done there is indeed necessary (I haven't tested that it is, although I have had dubious experinces with OIS events in the past), then we should probably adapt all that code here. Or even better, @@ -46,10 +63,12 @@ void EventInjector::event(Type type, int index, const void *p) MouseEvent *mouse = (MouseEvent*)p; MyGUI::MouseButton id = MyGUI::MouseButton::Enum(index); - // I'm not sure these should be used directly, MyGUI demo code - // use local mouse position variables. - int mouseX = mouse->state.X.abs; - int mouseY = mouse->state.Y.abs; + // Update mouse position + mouseX += mouse->state.X.rel; + mouseY += mouse->state.Y.rel; + + setRange(mouseX,0,maxX); + setRange(mouseY,0,maxY); if(type == EV_MouseDown) gui->injectMousePress(mouseX, mouseY, id); diff --git a/gui/events.hpp b/gui/events.hpp index 17415906d..6ca83cf75 100644 --- a/gui/events.hpp +++ b/gui/events.hpp @@ -16,11 +16,13 @@ namespace GUI class EventInjector : public Mangle::Input::Event { MyGUI::Gui *gui; + int mouseX, mouseY; + int maxX, maxY; public: bool enabled; - EventInjector(MyGUI::Gui *g) : gui(g), enabled(true) {} + EventInjector(MyGUI::Gui *g); void event(Type type, int index, const void *p); }; From a202371ef19b9740dc4ca86632af18ab0c614078 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Fri, 30 Jul 2010 22:25:06 +0200 Subject: [PATCH 12/56] mangle update --- mangle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mangle b/mangle index 18dc06571..469237549 160000 --- a/mangle +++ b/mangle @@ -1 +1 @@ -Subproject commit 18dc065715c12fd8793f8793c7bf834619527399 +Subproject commit 4692375491fb16da59642022c8d7c891d68ba665 From 6443c161464e8959d6ee0c28e1ccebf9a6f57af9 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Wed, 11 Aug 2010 14:16:56 +0200 Subject: [PATCH 13/56] Made SoundManager and test --- mangle | 2 +- misc/list.hpp | 110 +++++++++++++++ sound/sndmanager.cpp | 208 +++++++++++++++++++++++++++++ sound/sndmanager.hpp | 93 +++++++++++++ sound/tests/Makefile | 13 ++ sound/tests/sound_manager_test.cpp | 50 +++++++ sound/tests/test.sh | 18 +++ 7 files changed, 493 insertions(+), 1 deletion(-) create mode 100644 misc/list.hpp create mode 100644 sound/sndmanager.cpp create mode 100644 sound/sndmanager.hpp create mode 100644 sound/tests/Makefile create mode 100644 sound/tests/sound_manager_test.cpp create mode 100755 sound/tests/test.sh diff --git a/mangle b/mangle index 469237549..87f6e7397 160000 --- a/mangle +++ b/mangle @@ -1 +1 @@ -Subproject commit 4692375491fb16da59642022c8d7c891d68ba665 +Subproject commit 87f6e739759244cef8e9730b8f94e628b8d64681 diff --git a/misc/list.hpp b/misc/list.hpp new file mode 100644 index 000000000..07e5ddc8d --- /dev/null +++ b/misc/list.hpp @@ -0,0 +1,110 @@ +#ifndef MISC_LIST_H +#define MISC_LIST_H + +#include + +namespace Misc{ + +/* + This is just a suggested data structure for List. You can use + anything that has next and prev pointers. + */ +template +struct ListElem +{ + X data; + ListElem *next; + ListElem *prev; +}; + +/* + A generic class that contains a doubly linked list of elements. It + does not do any allocation of elements, it just keeps pointers to + them. +*/ +template +struct List +{ + List() : head(0), tail(0), totalNum(0) {} + + // Insert an element at the end of the list. The element cannot be + // part of any other list when this is called. + void insert(Elem *p) + { + if(tail) + { + // There are existing elements. Insert the node at the end of + // the list. + assert(head && totalNum > 0); + tail->next = p; + } + else + { + // This is the first element + assert(head == 0 && totalNum == 0); + head = p; + } + + // These have to be done in either case + p->prev = tail; + p->next = 0; + tail = p; + + totalNum++; + } + + // Remove element from the list. The element MUST be part of the + // list when this is called. + void remove(Elem *p) + { + assert(totalNum > 0); + + if(p->next) + { + // There's an element following us. Set it up correctly. + p->next->prev = p->prev; + assert(tail && tail != p); + } + else + { + // We're the tail + assert(tail == p); + tail = p->prev; + } + + // Now do exactly the same for the previous element + if(p->prev) + { + p->prev->next = p->next; + assert(head && head != p); + } + else + { + assert(head == p); + head = p->next; + } + + totalNum--; + } + + // Pop the first element off the list + Elem *pop() + { + Elem *res = getHead(); + if(res) remove(res); + return res; + } + + Elem* getHead() { return head; } + Elem* getTail() { return tail; } + unsigned int getNum() { return totalNum; } + +private: + + Elem *head; + Elem *tail; + unsigned int totalNum; +}; + +} +#endif diff --git a/sound/sndmanager.cpp b/sound/sndmanager.cpp new file mode 100644 index 000000000..d05dc1a49 --- /dev/null +++ b/sound/sndmanager.cpp @@ -0,0 +1,208 @@ +#include "sndmanager.hpp" + +#include +#include + +using namespace OEngine::Sound; +using namespace Mangle::Sound; + +/** This is our own internal implementation of the + Mangle::Sound::Sound interface. This class links a SoundPtr to + itself and prevents itself from being deleted as long as the sound + is playing. + */ +struct OEngine::Sound::ManagedSound : SoundFilter +{ +private: + /** Who's your daddy? This is set if and only if we are listed + internally in the given SoundManager. + + It may be NULL if the manager has been deleted but the user + keeps their own SoundPtrs to the object. + */ + SoundManager *mgr; + + /** Keep a weak pointer to ourselves, which we convert into a + 'strong' pointer when we are playing. When 'self' is pointing to + ourselves, the object will never be deleted. + + This is used to make sure the sound is not deleted while + playing, unless it is explicitly ordered to do so by the + manager. + + TODO: This kind of construct is useful. If we need it elsewhere + later, template it. It would be generally useful in any system + where we poll to check if a resource is still needed, but where + manual references are allowed. + */ + typedef boost::weak_ptr WSoundPtr; + WSoundPtr weak; + SoundPtr self; + + // Keep this object from being deleted + void lock() + { + self = SoundPtr(weak); + } + + // Release the lock. This may or may not delete the object. Never do + // anything after calling unlock()! + void unlock() + { + self.reset(); + } + +public: + // Used for putting ourselves in linked lists + ManagedSound *next, *prev; + + /** Detach this sound from its manager. This means that the manager + will no longer know we exist. Typically only called when either + the sound or the manager is about to get deleted. + + Since this means update() will no longer be called, we also have + to unlock the sound manually since it will no longer be able to + do that itself. This means that the sound may be deleted, even + if it is still playing, when the manager is deleted. + + However, you are still allowed to keep and manage your own + SoundPtr references, but the lock/unlock system is disabled + after the manager is gone. + */ + void detach() + { + if(mgr) + { + mgr->detach(this); + mgr = NULL; + } + + // Unlock must be last command. Object may get deleted at this + // point. + unlock(); + } + + ManagedSound(SoundPtr snd, SoundManager *mg) + : SoundFilter(snd), mgr(mg) + {} + ~ManagedSound() { detach(); } + + // Needed to set up the weak pointer + void setup(SoundPtr self) + { + weak = WSoundPtr(self); + } + + // Override play() to mark the object as locked + void play() + { + SoundFilter::play(); + + // Lock the object so that it is not deleted while playing. Only + // do this if we have a manager, otherwise the object will never + // get unlocked. + if(mgr) lock(); + } + + // Override stop() and pause() + + // Called regularly by the manager + void update() + { + // If we're no longer playing, don't force object retention. + if(!isPlaying()) + unlock(); + + // unlock() may delete the object, so don't do anything below this + // point. + } + + // Not implemented yet + SoundPtr clone() const + { return SoundPtr(); } +}; + +struct SoundManager::SoundManagerList +{ +private: + // A linked list of ManagedSound objects. + typedef Misc::List SoundList; + SoundList list; + +public: + // Add a new sound to the list + void addNew(ManagedSound* snd) + { + list.insert(snd); + } + + // Remove a sound from the list + void remove(ManagedSound *snd) + { + list.remove(snd); + } + + // Number of sounds in the list + int numSounds() { return list.getNum(); } + + // Update all sounds + void updateAll() + { + for(ManagedSound *s = list.getHead(); s != NULL; s=s->next) + s->update(); + } + + // Detach and unlock all sounds + void detachAll() + { + for(ManagedSound *s = list.getHead(); s != NULL; s=s->next) + s->detach(); + } +}; + +SoundManager::SoundManager(SoundFactoryPtr fact) + : FactoryFilter(fact) +{ + needsUpdate = true; + list = new SoundManagerList; +} + +SoundManager::~SoundManager() +{ + // Detach all sounds + list->detachAll(); +} + +SoundPtr SoundManager::wrap(SoundPtr client) +{ + // Create and set up the sound wrapper + ManagedSound *snd = new ManagedSound(client,this); + SoundPtr ptr(snd); + snd->setup(ptr); + + // Add ourselves to the list of all sounds + list->addNew(snd); + + return ptr; +} + +// Remove the sound from this manager. +void SoundManager::detach(ManagedSound *sound) +{ + list->remove(sound); +} + +int SoundManager::numSounds() +{ + return list->numSounds(); +} + +void SoundManager::update() +{ + // Update all the sounds we own + list->updateAll(); + + // Update the source if it needs it + if(client->needsUpdate) + client->update(); +} diff --git a/sound/sndmanager.hpp b/sound/sndmanager.hpp new file mode 100644 index 000000000..5ea0c4fc3 --- /dev/null +++ b/sound/sndmanager.hpp @@ -0,0 +1,93 @@ +#ifndef OENGINE_SOUND_MANAGER_H +#define OENGINE_SOUND_MANAGER_H + +#include + +namespace OEngine +{ + namespace Sound + { + using namespace Mangle::Sound; + + class ManagedSound; + + /** A manager of Mangle::Sounds. + + The sound manager is a wrapper around the more low-level + SoundFactory - although it is also itself an implementation of + SoundFactory. It will: + - keep a list of all created sounds + - let you iterate the list + - keep references to playing sounds so you don't have to + - auto-release references to sounds that are finished playing + (ie. deleting them if you're not referencing them) + */ + class SoundManager : public FactoryFilter + { + // Shove the implementation details into the cpp file. + struct SoundManagerList; + SoundManagerList *list; + + // Create a new sound wrapper based on the given source sound. + SoundPtr wrap(SoundPtr snd); + + /** Internal function. Will completely disconnect the given + sound from this manager. Called from ManagedSound. + */ + friend class ManagedSound; + void detach(ManagedSound *sound); + public: + SoundManager(SoundFactoryPtr fact); + ~SoundManager(); + void update(); + + /// Get number of sounds currently managed by this manager. + int numSounds(); + + SoundPtr loadRaw(SampleSourcePtr input) + { return wrap(client->loadRaw(input)); } + + SoundPtr load(Mangle::Stream::StreamPtr input) + { return wrap(client->load(input)); } + + SoundPtr load(const std::string &file) + { return wrap(client->load(file)); } + + // Play a sound immediately, and release when done unless you + // keep the returned SoundPtr. + SoundPtr play(Mangle::Stream::StreamPtr sound) + { + SoundPtr snd = load(sound); + snd->play(); + return snd; + } + + SoundPtr play(const std::string &sound) + { + SoundPtr snd = load(sound); + snd->play(); + return snd; + } + + // Ditto for 3D sounds + SoundPtr play3D(Mangle::Stream::StreamPtr sound, float x, float y, float z) + { + SoundPtr snd = load(sound); + snd->setPos(x,y,z); + snd->play(); + return snd; + } + + SoundPtr play3D(const std::string &sound, float x, float y, float z) + { + SoundPtr snd = load(sound); + snd->setPos(x,y,z); + snd->play(); + return snd; + } + }; + + typedef boost::shared_ptr SoundManagerPtr; + } +} +#endif diff --git a/sound/tests/Makefile b/sound/tests/Makefile new file mode 100644 index 000000000..9e84cb580 --- /dev/null +++ b/sound/tests/Makefile @@ -0,0 +1,13 @@ +GCC=g++ -I../ + +all: sound_manager_test + +L_FFMPEG=$(shell pkg-config --libs libavcodec libavformat) +L_OPENAL=$(shell pkg-config --libs openal) +L_AUDIERE=-laudiere + +sound_manager_test: sound_manager_test.cpp ../../mangle/sound/sources/audiere_source.cpp ../../mangle/sound/outputs/openal_out.cpp ../../mangle/stream/clients/audiere_file.cpp ../sndmanager.cpp + $(GCC) $^ -o $@ $(L_AUDIERE) $(L_OPENAL) -I../.. + +clean: + rm *_test diff --git a/sound/tests/sound_manager_test.cpp b/sound/tests/sound_manager_test.cpp new file mode 100644 index 000000000..7c09cd583 --- /dev/null +++ b/sound/tests/sound_manager_test.cpp @@ -0,0 +1,50 @@ +#include +#include +#include + +#include +#include + +#include + +using namespace std; +using namespace Mangle::Stream; +using namespace Mangle::Sound; +using namespace OEngine::Sound; + +const std::string sound = "../../mangle/sound/tests/cow.wav"; + +int main() +{ + SoundFactoryPtr oaf(new OpenAL_Audiere_Factory); + SoundManagerPtr mg(new SoundManager(oaf)); + + cout << "Playing " << sound << "\n"; + + assert(mg->numSounds() == 0); + + /** Start the sound playing, and then let the pointer go out of + scope. Lower-level players (like 'oaf' above) will immediately + delete the sound. SoundManager OTOH will keep it until it's + finished. + */ + mg->play(sound); + + assert(mg->numSounds() == 1); + + // Loop while there are still sounds to manage + int i=0; + while(mg->numSounds() != 0) + { + i++; + assert(mg->numSounds() == 1); + usleep(10000); + if(mg->needsUpdate) + mg->update(); + } + cout << "Done playing.\n"; + + assert(mg->numSounds() == 0); + + return 0; +} diff --git a/sound/tests/test.sh b/sound/tests/test.sh new file mode 100755 index 000000000..2d07708ad --- /dev/null +++ b/sound/tests/test.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +make || exit + +mkdir -p output + +PROGS=*_test + +for a in $PROGS; do + if [ -f "output/$a.out" ]; then + echo "Running $a:" + ./$a | diff output/$a.out - + else + echo "Creating $a.out" + ./$a > "output/$a.out" + git add "output/$a.out" + fi +done From e2e5a2138da72e63f8d7c7cd626cf4ffadad6888 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Wed, 11 Aug 2010 14:38:20 +0200 Subject: [PATCH 14/56] Added clone() to ManagedSound --- sound/sndmanager.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/sndmanager.cpp b/sound/sndmanager.cpp index d05dc1a49..3bf8555b3 100644 --- a/sound/sndmanager.cpp +++ b/sound/sndmanager.cpp @@ -104,8 +104,6 @@ public: if(mgr) lock(); } - // Override stop() and pause() - // Called regularly by the manager void update() { @@ -117,9 +115,12 @@ public: // point. } - // Not implemented yet SoundPtr clone() const - { return SoundPtr(); } + { + // Cloning only works when we have a manager. + assert(mgr); + return mgr->wrap(client->clone()); + } }; struct SoundManager::SoundManagerList From 2aa41dfffec4c84ff3a47208aaaa0bf425f417b2 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Thu, 12 Aug 2010 14:49:58 +0200 Subject: [PATCH 15/56] Added tests for 3d sound and pausing. --- sound/tests/Makefile | 5 ++- sound/tests/output/sound_3d_test.out | 3 ++ sound/tests/output/sound_manager_test.out | 5 +++ sound/tests/sound_3d_test.cpp | 46 +++++++++++++++++++++++ sound/tests/sound_manager_test.cpp | 27 ++++++++++++- 5 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 sound/tests/output/sound_3d_test.out create mode 100644 sound/tests/output/sound_manager_test.out create mode 100644 sound/tests/sound_3d_test.cpp diff --git a/sound/tests/Makefile b/sound/tests/Makefile index 9e84cb580..04952167f 100644 --- a/sound/tests/Makefile +++ b/sound/tests/Makefile @@ -1,6 +1,6 @@ GCC=g++ -I../ -all: sound_manager_test +all: sound_manager_test sound_3d_test L_FFMPEG=$(shell pkg-config --libs libavcodec libavformat) L_OPENAL=$(shell pkg-config --libs openal) @@ -9,5 +9,8 @@ L_AUDIERE=-laudiere sound_manager_test: sound_manager_test.cpp ../../mangle/sound/sources/audiere_source.cpp ../../mangle/sound/outputs/openal_out.cpp ../../mangle/stream/clients/audiere_file.cpp ../sndmanager.cpp $(GCC) $^ -o $@ $(L_AUDIERE) $(L_OPENAL) -I../.. +sound_3d_test: sound_3d_test.cpp ../../mangle/sound/sources/audiere_source.cpp ../../mangle/sound/outputs/openal_out.cpp ../../mangle/stream/clients/audiere_file.cpp ../sndmanager.cpp + $(GCC) $^ -o $@ $(L_AUDIERE) $(L_OPENAL) -I../.. + clean: rm *_test diff --git a/sound/tests/output/sound_3d_test.out b/sound/tests/output/sound_3d_test.out new file mode 100644 index 000000000..a443c84f0 --- /dev/null +++ b/sound/tests/output/sound_3d_test.out @@ -0,0 +1,3 @@ +Playing at 0,0,0 +Playing at 1,1,0 +Playing at -1,0,0 diff --git a/sound/tests/output/sound_manager_test.out b/sound/tests/output/sound_manager_test.out new file mode 100644 index 000000000..2b458493d --- /dev/null +++ b/sound/tests/output/sound_manager_test.out @@ -0,0 +1,5 @@ +Playing ../../mangle/sound/tests/cow.wav +Replaying +pause +restart +Done playing. diff --git a/sound/tests/sound_3d_test.cpp b/sound/tests/sound_3d_test.cpp new file mode 100644 index 000000000..f5b197fd0 --- /dev/null +++ b/sound/tests/sound_3d_test.cpp @@ -0,0 +1,46 @@ +#include +#include +#include + +#include +#include + +#include + +using namespace std; +using namespace Mangle::Stream; +using namespace Mangle::Sound; +using namespace OEngine::Sound; + +const std::string sound = "../../mangle/sound/tests/cow.wav"; + +SoundManagerPtr m; + +// Play and wait for finish +void play(float x, float y, float z) +{ + cout << "Playing at " << x << "," << y << "," << z << endl; + + SoundPtr snd = m->play3D(sound,x,y,z); + + while(snd->isPlaying()) + { + usleep(10000); + m->update(); + } +} + +int main() +{ + SoundFactoryPtr oaf(new OpenAL_Audiere_Factory); + SoundManagerPtr mg(new SoundManager(oaf)); + m = mg; + + mg->setListenerPos(0,0,0,0,1,0,0,0,1); + + play(0,0,0); + play(1,1,0); + play(-1,0,0); + + return 0; +} diff --git a/sound/tests/sound_manager_test.cpp b/sound/tests/sound_manager_test.cpp index 7c09cd583..3794c4a3c 100644 --- a/sound/tests/sound_manager_test.cpp +++ b/sound/tests/sound_manager_test.cpp @@ -33,15 +33,38 @@ int main() assert(mg->numSounds() == 1); // Loop while there are still sounds to manage - int i=0; while(mg->numSounds() != 0) { - i++; assert(mg->numSounds() == 1); usleep(10000); if(mg->needsUpdate) mg->update(); } + + SoundPtr snd = mg->play(sound); + cout << "Replaying\n"; + int i = 0; + while(mg->numSounds() != 0) + { + assert(mg->numSounds() == 1); + usleep(10000); + if(mg->needsUpdate) + mg->update(); + + if(i++ == 70) + { + cout << "pause\n"; + snd->pause(); + } + if(i == 130) + { + cout << "restart\n"; + snd->play(); + // Let the sound go out of scope + snd.reset(); + } + } + cout << "Done playing.\n"; assert(mg->numSounds() == 0); From b9d4dc448bc3be908653f9dea3c3450fb85ed107 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Thu, 12 Aug 2010 15:46:11 +0200 Subject: [PATCH 16/56] Switched to local include for OpenMW --- sound/sndmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/sndmanager.cpp b/sound/sndmanager.cpp index 3bf8555b3..391143236 100644 --- a/sound/sndmanager.cpp +++ b/sound/sndmanager.cpp @@ -1,6 +1,6 @@ #include "sndmanager.hpp" -#include +#include "../misc/list.hpp" #include using namespace OEngine::Sound; From 2e2f8e9725fd1a27a82d0ad5c6c0e296e715eb60 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Tue, 17 Aug 2010 11:27:06 +0200 Subject: [PATCH 17/56] Mangle update --- mangle | 2 +- sound/sndmanager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mangle b/mangle index 87f6e7397..932465442 160000 --- a/mangle +++ b/mangle @@ -1 +1 @@ -Subproject commit 87f6e739759244cef8e9730b8f94e628b8d64681 +Subproject commit 932465442bd97c3bcb3a8630414c16bdd887fa9f diff --git a/sound/sndmanager.cpp b/sound/sndmanager.cpp index 391143236..fe5ad8091 100644 --- a/sound/sndmanager.cpp +++ b/sound/sndmanager.cpp @@ -115,7 +115,7 @@ public: // point. } - SoundPtr clone() const + SoundPtr clone() { // Cloning only works when we have a manager. assert(mgr); From 4b2e2f7503dead8ccedeff48677ed563aa8aa202 Mon Sep 17 00:00:00 2001 From: athile Date: Mon, 30 Aug 2010 11:37:48 +0100 Subject: [PATCH 18/56] Windows fixes --- gui/events.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gui/events.cpp b/gui/events.cpp index 73274ee50..713db8585 100644 --- a/gui/events.cpp +++ b/gui/events.cpp @@ -11,8 +11,8 @@ EventInjector::EventInjector(MyGUI::Gui *g) : gui(g), mouseX(0), mouseY(0), enabled(true) { assert(gui); - maxX = gui->getViewWidth(); - maxY = gui->getViewHeight(); + maxX = gui->getViewSize().width; + maxY = gui->getViewSize().height; } template From 3df4362b33edc5d7f89dcd902c7f6194ab4bc048 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Mon, 30 Aug 2010 20:30:09 +0200 Subject: [PATCH 19/56] Various improvements to misc/list.hpp --- misc/list.hpp | 104 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 86 insertions(+), 18 deletions(-) diff --git a/misc/list.hpp b/misc/list.hpp index 07e5ddc8d..b08b57494 100644 --- a/misc/list.hpp +++ b/misc/list.hpp @@ -6,27 +6,23 @@ namespace Misc{ /* - This is just a suggested data structure for List. You can use - anything that has next and prev pointers. - */ -template -struct ListElem -{ - X data; - ListElem *next; - ListElem *prev; -}; - -/* - A generic class that contains a doubly linked list of elements. It - does not do any allocation of elements, it just keeps pointers to - them. + A simple and completely allocation-less doubly linked list. The + class only manages pointers to and between elements. It leaving all + memory management to the user. */ template struct List { List() : head(0), tail(0), totalNum(0) {} + // Empty the list. + void reset() + { + head = 0; + tail = 0; + totalNum = 0; + } + // Insert an element at the end of the list. The element cannot be // part of any other list when this is called. void insert(Elem *p) @@ -95,9 +91,81 @@ struct List return res; } - Elem* getHead() { return head; } - Elem* getTail() { return tail; } - unsigned int getNum() { return totalNum; } + // Swap the contents of this list with another of the same type + void swap(List &other) + { + Elem *tmp; + + tmp = head; + head = other.head; + other.head = tmp; + + tmp = tail; + tail = other.tail; + other.tail = tmp; + + unsigned int tmp2 = totalNum; + totalNum = other.totalNum; + other.totalNum = tmp2; + } + + /* Absorb the contents of another list. All the elements from the + list are moved to the end of this list, and the other list is + cleared. + */ + void absorb(List &other) + { + assert(&other != this); + if(other.totalNum) + { + absorb(other.head, other.tail, other.totalNum); + other.reset(); + } + assert(other.totalNum == 0); + } + + /* Absorb a range of elements, endpoints included. The elements are + assumed NOT to belong to any list, but they ARE assumed to be + connected with a chain between them. + + The connection MUST run all the way from 'first' to 'last' + through the ->next pointers, and vice versa through ->prev + pointers. + + The parameter 'num' must give the exact number of elements in the + chain. + + Passing first == last, num == 1 is allowed and is equivalent to + calling insert(). + */ + void absorb(Elem* first, Elem *last, int num) + { + assert(first && last && num>=1); + if(tail) + { + // There are existing elements. Insert the first node at the + // end of the list. + assert(head && totalNum > 0); + tail->next = first; + } + else + { + // This is the first element + assert(head == 0 && totalNum == 0); + head = first; + } + + // These have to be done in either case + first->prev = tail; + last->next = 0; + tail = last; + + totalNum += num; + } + + Elem* getHead() const { return head; } + Elem* getTail() const { return tail; } + unsigned int getNum() const { return totalNum; } private: From b486f12a5f1126457f375a5c7170164d7729cce5 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Mon, 30 Aug 2010 23:51:47 +0200 Subject: [PATCH 20/56] Fixed crash bug in sndmanager.cpp --- mangle | 2 +- sound/sndmanager.cpp | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/mangle b/mangle index 932465442..3324f6494 160000 --- a/mangle +++ b/mangle @@ -1 +1 @@ -Subproject commit 932465442bd97c3bcb3a8630414c16bdd887fa9f +Subproject commit 3324f6494c021e3dc69cd76ace5ff25a52e4bcce diff --git a/sound/sndmanager.cpp b/sound/sndmanager.cpp index fe5ad8091..10a503bf4 100644 --- a/sound/sndmanager.cpp +++ b/sound/sndmanager.cpp @@ -149,15 +149,26 @@ public: // Update all sounds void updateAll() { - for(ManagedSound *s = list.getHead(); s != NULL; s=s->next) - s->update(); + ManagedSound *s = list.getHead(); + while(s) + { + ManagedSound *cur = s; + // Propagate first, since update() may delete object + s = s->next; + cur->update(); + } } // Detach and unlock all sounds void detachAll() { - for(ManagedSound *s = list.getHead(); s != NULL; s=s->next) - s->detach(); + ManagedSound *s = list.getHead(); + while(s) + { + ManagedSound *cur = s; + s = s->next; + cur->detach(); + } } }; From bf32845d07fa5fd5f2af9747cc2ad51ed1b72cd3 Mon Sep 17 00:00:00 2001 From: athile Date: Tue, 31 Aug 2010 01:47:18 +0100 Subject: [PATCH 21/56] Workaround for sound crash --- sound/sndmanager.cpp | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/sound/sndmanager.cpp b/sound/sndmanager.cpp index fe5ad8091..12708f10c 100644 --- a/sound/sndmanager.cpp +++ b/sound/sndmanager.cpp @@ -1,6 +1,7 @@ #include "sndmanager.hpp" #include "../misc/list.hpp" +#include #include using namespace OEngine::Sound; @@ -126,8 +127,8 @@ public: struct SoundManager::SoundManagerList { private: - // A linked list of ManagedSound objects. - typedef Misc::List SoundList; + // A list of ManagedSound objects. + typedef std::set SoundList; SoundList list; public: @@ -140,24 +141,38 @@ public: // Remove a sound from the list void remove(ManagedSound *snd) { - list.remove(snd); + SoundList::iterator it = list.find(snd); + if (it != list.end()) + list.erase(it); } // Number of sounds in the list - int numSounds() { return list.getNum(); } + int numSounds() { return (int)list.size(); } // Update all sounds void updateAll() { - for(ManagedSound *s = list.getHead(); s != NULL; s=s->next) - s->update(); + // Iterate over a copy of the list since sounds may remove themselves + // from the master list during the iteration + SoundList tmp = list; + for (SoundList::iterator it = tmp.begin(); it != tmp.end(); ++it) + { + ManagedSound* pSound = *it; + pSound->update(); + } } // Detach and unlock all sounds void detachAll() { - for(ManagedSound *s = list.getHead(); s != NULL; s=s->next) - s->detach(); + // Iterate over a copy of the list since sounds may remove themselves + // from the master list during the iteration + SoundList tmp = list; + for (SoundList::iterator it = tmp.begin(); it != tmp.end(); ++it) + { + ManagedSound* pSound = *it; + pSound->detach(); + } } }; From 377e7d71ceea5a1ca166b8df9a03a5b68df83bc5 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Thu, 2 Sep 2010 12:52:33 +0200 Subject: [PATCH 22/56] Mangle update --- mangle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mangle b/mangle index 3324f6494..2407f21c4 160000 --- a/mangle +++ b/mangle @@ -1 +1 @@ -Subproject commit 3324f6494c021e3dc69cd76ace5ff25a52e4bcce +Subproject commit 2407f21c47abe218b9347df0fc9e8e9aebc02e3f From 3a17aaa6976cd4c3d57dfd236bbdf689bc60d770 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Mon, 27 Sep 2010 18:03:10 +0200 Subject: [PATCH 23/56] Another mangle update --- mangle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mangle b/mangle index 2407f21c4..a05046026 160000 --- a/mangle +++ b/mangle @@ -1 +1 @@ -Subproject commit 2407f21c47abe218b9347df0fc9e8e9aebc02e3f +Subproject commit a05046026ec9edb1e528fac2c70f887239302237 From 7185eab18c29a0a5e03e44690d6bd8ece7e3792b Mon Sep 17 00:00:00 2001 From: Jan-Peter Nilsson Date: Tue, 4 Jan 2011 01:03:05 +0100 Subject: [PATCH 24/56] Make configuration and log paths configurable --- gui/manager.cpp | 10 +++++++--- gui/manager.hpp | 6 +++--- ogre/renderer.cpp | 27 +++++++++++++++++++++++++-- ogre/renderer.hpp | 13 +++++++++++++ 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/gui/manager.cpp b/gui/manager.cpp index 564a33cfe..b606d7d16 100644 --- a/gui/manager.cpp +++ b/gui/manager.cpp @@ -6,7 +6,7 @@ using namespace OEngine::GUI; -void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging) +void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging, const std::string& logDir) { assert(wnd); assert(mgr); @@ -21,13 +21,17 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool LogManager::initialise(); LogManager::setSTDOutputEnabled(logging); + std::string theLogFile = std::string(MYGUI_PLATFORM_LOG_FILENAME); + if(!logDir.empty()) + theLogFile.insert(0, logDir); + // Set up OGRE platform. We might make this more generic later. mPlatform = new OgrePlatform(); - mPlatform->initialise(wnd, mgr); + mPlatform->initialise(wnd, mgr, "General", theLogFile); // Create GUI mGui = new Gui(); - mGui->initialise(); + mGui->initialise("core.xml", theLogFile); } void MyGUIManager::shutdown() diff --git a/gui/manager.hpp b/gui/manager.hpp index e59b4b54b..781685acf 100644 --- a/gui/manager.hpp +++ b/gui/manager.hpp @@ -23,11 +23,11 @@ namespace GUI public: MyGUIManager() : mPlatform(NULL), mGui(NULL) {} - MyGUIManager(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging=false) - { setup(wnd,mgr,logging); } + MyGUIManager(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging=false, const std::string& logDir = std::string("")) + { setup(wnd,mgr,logging, logDir); } ~MyGUIManager() { shutdown(); } - void setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging=false); + void setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging=false, const std::string& logDir = std::string("")); void shutdown(); MyGUI::Gui *getGui() { return mGui; } diff --git a/ogre/renderer.cpp b/ogre/renderer.cpp index c60a29c77..1773832d7 100644 --- a/ogre/renderer.cpp +++ b/ogre/renderer.cpp @@ -28,12 +28,20 @@ void OgreRenderer::screenshot(const std::string &file) } bool OgreRenderer::configure(bool showConfig, + const std::string &cfgPath, + const std::string &logPath, const std::string &pluginCfg, bool _logging) { + std::string theLogFile("Ogre.log"); + std::string theCfgFile("ogre.cfg"); + + theLogFile.insert(0, logPath); + theCfgFile.insert(0, cfgPath); + // Set up logging first new LogManager; - Log *log = LogManager::getSingleton().createLog("Ogre.log"); + Log *log = LogManager::getSingleton().createLog(theLogFile); logging = _logging; if(logging) @@ -43,7 +51,7 @@ bool OgreRenderer::configure(bool showConfig, // Disable logging log->setDebugOutputEnabled(false); - mRoot = new Root(pluginCfg, "ogre.cfg", ""); + mRoot = new Root(pluginCfg, theCfgFile, ""); // Show the configuration dialog and initialise the system, if the // showConfig parameter is specified. The settings are stored in @@ -58,6 +66,21 @@ bool OgreRenderer::configure(bool showConfig, return !result; } +bool OgreRenderer::configure(bool showConfig, + const std::string &cfgPath, + const std::string &pluginCfg, + bool _logging) +{ + return configure(showConfig, cfgPath, cfgPath, pluginCfg, _logging); +} + +bool OgreRenderer::configure(bool showConfig, + const std::string &pluginCfg, + bool _logging) +{ + return configure(showConfig, "", pluginCfg, _logging); +} + void OgreRenderer::createWindow(const std::string &title) { assert(mRoot); diff --git a/ogre/renderer.hpp b/ogre/renderer.hpp index f706b16f7..59b69f689 100644 --- a/ogre/renderer.hpp +++ b/ogre/renderer.hpp @@ -33,6 +33,19 @@ namespace Render : mRoot(NULL), mWindow(NULL), mScene(NULL) {} ~OgreRenderer() { cleanup(); } + /** Configure the renderer. This will load configuration files and + set up the Root and logging classes. */ + bool configure(bool showConfig, // Show config dialog box? + const std::string &cfgPath, // Path to directory where to store config files + const std::string &logPath, // Path to directory where to store log files + const std::string &pluginCfg, // plugin.cfg file + bool _logging); // Enable or disable logging + + bool configure(bool showConfig, // Show config dialog box? + const std::string &cfgPath, // Path to directory where to store config files + const std::string &pluginCfg, // plugin.cfg file + bool _logging); // Enable or disable logging + /** Configure the renderer. This will load configuration files and set up the Root and logging classes. */ bool configure(bool showConfig, // Show config dialog box? From c60a48b397b2077e9a81fdbf3fe31c83276f6ffa Mon Sep 17 00:00:00 2001 From: sergei Date: Sun, 13 Feb 2011 16:45:52 +0300 Subject: [PATCH 25/56] added getFPS() method to OgreRenderer Committer: sergoz --- ogre/renderer.cpp | 5 +++++ ogre/renderer.hpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/ogre/renderer.cpp b/ogre/renderer.cpp index 1773832d7..9ce7a053f 100644 --- a/ogre/renderer.cpp +++ b/ogre/renderer.cpp @@ -27,6 +27,11 @@ void OgreRenderer::screenshot(const std::string &file) mWindow->writeContentsToFile(file); } +float OgreRenderer::getFPS() +{ + return mWindow->getLastFPS(); +} + bool OgreRenderer::configure(bool showConfig, const std::string &cfgPath, const std::string &logPath, diff --git a/ogre/renderer.hpp b/ogre/renderer.hpp index 59b69f689..982534e6b 100644 --- a/ogre/renderer.hpp +++ b/ogre/renderer.hpp @@ -70,6 +70,8 @@ namespace Render /// Write a screenshot to file void screenshot(const std::string &file); + float getFPS(); + /// Get the Root Ogre::Root *getRoot() { return mRoot; } From adc1fa8e2ce1303a3fd612da77045cdcecf53587 Mon Sep 17 00:00:00 2001 From: gugus Date: Tue, 22 Feb 2011 14:02:50 +0100 Subject: [PATCH 26/56] add physic support --- bullet/CMotionState.cpp | 45 ++ bullet/CMotionState.h | 52 ++ bullet/btKinematicCharacterController.cpp | 629 ++++++++++++++++++++++ bullet/btKinematicCharacterController.h | 164 ++++++ bullet/physic.cpp | 275 ++++++++++ bullet/physic.hpp | 190 +++++++ 6 files changed, 1355 insertions(+) create mode 100644 bullet/CMotionState.cpp create mode 100644 bullet/CMotionState.h create mode 100644 bullet/btKinematicCharacterController.cpp create mode 100644 bullet/btKinematicCharacterController.h create mode 100644 bullet/physic.cpp create mode 100644 bullet/physic.hpp diff --git a/bullet/CMotionState.cpp b/bullet/CMotionState.cpp new file mode 100644 index 000000000..9cb662caa --- /dev/null +++ b/bullet/CMotionState.cpp @@ -0,0 +1,45 @@ +#include "CMotionState.h" +#include "physic.hpp" + +#include +#include +#include +//#include + +namespace OEngine { +namespace Physic +{ + + CMotionState::CMotionState(PhysicEngine* eng,std::string name) + { + pEng = eng; + tr.setIdentity(); + pName = name; + }; + + void CMotionState::getWorldTransform(btTransform &worldTrans) const + { + worldTrans = tr; + } + + void CMotionState::setWorldTransform(const btTransform &worldTrans) + { + tr = worldTrans; + + PhysicEvent evt; + evt.isNPC = isNPC; + evt.isPC = isPC; + evt.newTransform = tr; + evt.RigidBodyName = pName; + + if(isPC) + { + pEng->PEventList.push_back(evt); + } + else + { + pEng->NPEventList.push_back(evt); + } + } + +}} \ No newline at end of file diff --git a/bullet/CMotionState.h b/bullet/CMotionState.h new file mode 100644 index 000000000..9ccc35adb --- /dev/null +++ b/bullet/CMotionState.h @@ -0,0 +1,52 @@ +#ifndef OENGINE_CMOTIONSTATE_H +#define OENGINE_CMOTIONSTATE_H + +#include +#include + +namespace OEngine { +namespace Physic +{ + class PhysicEngine; + + /** + *A CMotionState is associated with a single RigidBody. + *When the RigidBody is moved by bullet, bullet will call the function setWorldTransform. + *for more info, see the bullet Wiki at btMotionState. + */ + class CMotionState:public btMotionState + { + public: + + CMotionState(PhysicEngine* eng,std::string name); + + /** + *Return the position of the RigidBody. + */ + virtual void getWorldTransform(btTransform &worldTrans) const; + + /** + *Function called by bullet when the RigidBody is moved. + *It add an event to the EventList of the PhysicEngine class. + */ + virtual void setWorldTransform(const btTransform &worldTrans); + + protected: + PhysicEngine* pEng; + btTransform tr; + bool isNPC; + bool isPC; + + std::string pName; + }; + + struct PhysicEvent + { + bool isNPC; + bool isPC; + btTransform newTransform; + std::string RigidBodyName; + }; + +}} +#endif \ No newline at end of file diff --git a/bullet/btKinematicCharacterController.cpp b/bullet/btKinematicCharacterController.cpp new file mode 100644 index 000000000..8c81d5a42 --- /dev/null +++ b/bullet/btKinematicCharacterController.cpp @@ -0,0 +1,629 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com + +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/btIDebugDraw.h" +#include "BulletCollision/CollisionDispatch/btGhostObject.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "LinearMath/btDefaultMotionState.h" +#include "btKinematicCharacterController.h" + +#include +///@todo Interact with dynamic objects, +///Ride kinematicly animated platforms properly +///Support ducking +class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback +{ +public: + btKinematicClosestNotMeRayResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) + { + m_me[0] = me; + count = 1; + } + + btKinematicClosestNotMeRayResultCallback (btCollisionObject* me[], int count_) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) + { + count = count_; + + for(int i = 0; i < count; i++) + m_me[i] = me[i]; + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) + { + for(int i = 0; i < count; i++) + if (rayResult.m_collisionObject == m_me[i]) + return 1.0; + + return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace); + } +protected: + btCollisionObject* m_me[10]; + int count; +}; + +class btKinematicClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback +{ +public: + btKinematicClosestNotMeConvexResultCallback( btCollisionObject* me, const btVector3& up, btScalar minSlopeDot ) + : btCollisionWorld::ClosestConvexResultCallback( btVector3( 0.0, 0.0, 0.0 ), btVector3( 0.0, 0.0, 0.0 ) ), + m_me( me ), m_up( up ), m_minSlopeDot( minSlopeDot ) + { + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace) + { + if( convexResult.m_hitCollisionObject == m_me ) + return btScalar( 1 ); + + btVector3 hitNormalWorld; + if( normalInWorldSpace ) + { + hitNormalWorld = convexResult.m_hitNormalLocal; + } + else + { + ///need to transform normal into worldspace + hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; + } + + // NOTE : m_hitNormalLocal is not always vertical on the ground with a capsule or a box... + + btScalar dotUp = m_up.dot(hitNormalWorld); + if( dotUp < m_minSlopeDot ) + return btScalar( 1 ); + + return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace); + } + +protected: + btCollisionObject* m_me; + const btVector3 m_up; + btScalar m_minSlopeDot; +}; + + + +btKinematicCharacterController::btKinematicCharacterController( btPairCachingGhostObject* externalGhostObject_, + btPairCachingGhostObject* internalGhostObject_, + btScalar stepHeight, + btScalar constantScale, + btScalar gravity, + btScalar fallVelocity, + btScalar jumpVelocity, + btScalar recoveringFactor ) +{ + m_upAxis = btKinematicCharacterController::Y_AXIS; + + m_walkDirection.setValue( btScalar( 0 ), btScalar( 0 ), btScalar( 0 ) ); + + m_useGhostObjectSweepTest = true; + + externalGhostObject = externalGhostObject_; + internalGhostObject = internalGhostObject_; + + m_recoveringFactor = recoveringFactor; + + m_stepHeight = stepHeight; + + m_useWalkDirection = true; // use walk direction by default, legacy behavior + m_velocityTimeInterval = btScalar( 0 ); + m_verticalVelocity = btScalar( 0 ); + m_verticalOffset = btScalar( 0 ); + + m_gravity = constantScale * gravity; + m_fallSpeed = constantScale * fallVelocity; // Terminal velocity of a sky diver in m/s. + + m_jumpSpeed = constantScale * jumpVelocity; // ? + m_wasJumping = false; + + setMaxSlope( btRadians( 45.0 ) ); +} + + +btKinematicCharacterController::~btKinematicCharacterController () +{ +} + + +bool btKinematicCharacterController::recoverFromPenetration( btCollisionWorld* collisionWorld ) +{ + //std::cout << "recover!!!!"; + bool penetration = false; + + collisionWorld->getDispatcher()->dispatchAllCollisionPairs( internalGhostObject->getOverlappingPairCache(), + collisionWorld->getDispatchInfo(), + collisionWorld->getDispatcher() ); + + btVector3 currentPosition = internalGhostObject->getWorldTransform().getOrigin(); + + btScalar maxPen = btScalar( 0 ); + + for( int i = 0; i < internalGhostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++ ) + { + m_manifoldArray.resize(0); + + btBroadphasePair* collisionPair = &internalGhostObject->getOverlappingPairCache()->getOverlappingPairArray()[i]; + + if( collisionPair->m_algorithm ) + collisionPair->m_algorithm->getAllContactManifolds( m_manifoldArray ); + + + for( int j = 0; j < m_manifoldArray.size(); j++ ) + { + btPersistentManifold* manifold = m_manifoldArray[j]; + + btScalar directionSign = manifold->getBody0() == internalGhostObject ? btScalar( -1.0 ) : btScalar( 1.0 ); + + for( int p = 0; p < manifold->getNumContacts(); p++ ) + { + const btManifoldPoint&pt = manifold->getContactPoint( p ); + if(manifold->getBody1() == externalGhostObject) std::cout << "external!!"; + if(manifold->getBody0() == externalGhostObject) std::cout << "external!!"; + if(manifold->getBody1() == internalGhostObject) std::cout << "internal!!"; + if(manifold->getBody0() == internalGhostObject) std::cout << "internal!!"; + if( (manifold->getBody1() == externalGhostObject && manifold->getBody0() == internalGhostObject) + ||(manifold->getBody0() == externalGhostObject && manifold->getBody1() == internalGhostObject) ) + { + } + else + { + btScalar dist = pt.getDistance(); + + if( dist < 0.0 ) + { + if( dist < maxPen ) + maxPen = dist; + + // NOTE : btScalar affects the stairs but the parkinson... + // 0.0 , the capsule can break the walls... + currentPosition += pt.m_normalWorldOnB * directionSign * dist * m_recoveringFactor; + + penetration = true; + std::cout << "recover!!!!"; + } + } + } + + // ??? + //manifold->clearManifold(); + } + } + + btTransform transform = internalGhostObject->getWorldTransform(); + + transform.setOrigin( currentPosition ); + + internalGhostObject->setWorldTransform( transform ); + externalGhostObject->setWorldTransform( transform ); + + return penetration; +} + + +btVector3 btKinematicCharacterController::stepUp( btCollisionWorld* world, const btVector3& currentPosition, btScalar& currentStepOffset ) +{ + btVector3 targetPosition = currentPosition + getUpAxisDirections()[ m_upAxis ] * ( m_stepHeight + ( m_verticalOffset > btScalar( 0.0 ) ? m_verticalOffset : 0.0 ) ); + + // Retrieve the collision shape + // + btCollisionShape* collisionShape = externalGhostObject->getCollisionShape(); + btAssert( collisionShape->isConvex() ); + + btConvexShape* convexShape = ( btConvexShape* )collisionShape; + + // FIXME: Handle penetration properly + // + btTransform start; + start.setIdentity(); + start.setOrigin( currentPosition + getUpAxisDirections()[ m_upAxis ] * ( convexShape->getMargin() ) ); + + btTransform end; + end.setIdentity(); + end.setOrigin( targetPosition ); + + btKinematicClosestNotMeConvexResultCallback callback( externalGhostObject, -getUpAxisDirections()[ m_upAxis ], m_maxSlopeCosine ); + callback.m_collisionFilterGroup = externalGhostObject->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = externalGhostObject->getBroadphaseHandle()->m_collisionFilterMask; + + // Sweep test + // + if( m_useGhostObjectSweepTest ) + externalGhostObject->convexSweepTest( convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration ); + + else + world->convexSweepTest( convexShape, start, end, callback ); + + if( callback.hasHit() ) + { + // Only modify the position if the hit was a slope and not a wall or ceiling. + // + if( callback.m_hitNormalWorld.dot(getUpAxisDirections()[m_upAxis]) > btScalar( 0.0 ) ) + { + // We moved up only a fraction of the step height + // + currentStepOffset = m_stepHeight * callback.m_closestHitFraction; + + return currentPosition.lerp( targetPosition, callback.m_closestHitFraction ); + } + + m_verticalVelocity = btScalar( 0.0 ); + m_verticalOffset = btScalar( 0.0 ); + + return currentPosition; + } + else + { + currentStepOffset = m_stepHeight; + return targetPosition; + } +} + + +///Reflect the vector d around the vector r +inline btVector3 reflect( const btVector3& d, const btVector3& r ) +{ + return d - ( btScalar( 2.0 ) * d.dot( r ) ) * r; +} + + +///Project a vector u on another vector v +inline btVector3 project( const btVector3& u, const btVector3& v ) +{ + return v * u.dot( v ); +} + + +///Helper for computing the character sliding +inline btVector3 slide( const btVector3& direction, const btVector3& planeNormal ) +{ + return direction - project( direction, planeNormal ); +} + + + +btVector3 slideOnCollision( const btVector3& fromPosition, const btVector3& toPosition, const btVector3& hitNormal ) +{ + btVector3 moveDirection = toPosition - fromPosition; + btScalar moveLength = moveDirection.length(); + + if( moveLength <= btScalar( SIMD_EPSILON ) ) + return toPosition; + + moveDirection.normalize(); + + btVector3 reflectDir = reflect( moveDirection, hitNormal ); + reflectDir.normalize(); + + return fromPosition + slide( reflectDir, hitNormal ) * moveLength; +} + + +btVector3 btKinematicCharacterController::stepForwardAndStrafe( btCollisionWorld* collisionWorld, const btVector3& currentPosition, const btVector3& walkMove ) +{ + // We go to ! + // + btVector3 targetPosition = currentPosition + walkMove; + + // Retrieve the collision shape + // + btCollisionShape* collisionShape = externalGhostObject->getCollisionShape(); + btAssert( collisionShape->isConvex() ); + + btConvexShape* convexShape = ( btConvexShape* )collisionShape; + + btTransform start; + start.setIdentity(); + + btTransform end; + end.setIdentity(); + + btScalar fraction = btScalar( 1.0 ); + + // This optimization scheme suffers in the corners. + // It basically jumps from a wall to another, then fails to find a new + // position (after 4 iterations here) and finally don't move at all. + // + // The stepping algorithm adds some problems with stairs. It seems + // the treads create some fake corner using capsules for collisions. + // + for( int i = 0; i < 4 && fraction > btScalar( 0.01 ); i++ ) + { + start.setOrigin( currentPosition ); + end.setOrigin( targetPosition ); + + btVector3 sweepDirNegative = currentPosition - targetPosition; + + btKinematicClosestNotMeConvexResultCallback callback( externalGhostObject, sweepDirNegative, btScalar( 0.0 ) ); + callback.m_collisionFilterGroup = externalGhostObject->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = externalGhostObject->getBroadphaseHandle()->m_collisionFilterMask; + + if( m_useGhostObjectSweepTest ) + externalGhostObject->convexSweepTest( convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration ); + + else + collisionWorld->convexSweepTest( convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration ); + + if( callback.hasHit() ) + { + // Try another target position + // + targetPosition = slideOnCollision( currentPosition, targetPosition, callback.m_hitNormalWorld ); + fraction = callback.m_closestHitFraction; + } + else + + // Move to the valid target position + // + return targetPosition; + } + + // Don't move if you can't find a valid target position... + // It prevents some flickering. + // + return currentPosition; +} + + +///Handle the gravity +btScalar btKinematicCharacterController::addFallOffset( bool wasOnGround, btScalar currentStepOffset, btScalar dt ) +{ + btScalar downVelocity = ( m_verticalVelocity < 0.0 ? -m_verticalVelocity : btScalar( 0.0 ) ) * dt; + + if( downVelocity > btScalar( 0.0 ) && downVelocity < m_stepHeight && ( wasOnGround || !m_wasJumping ) ) + downVelocity = m_stepHeight; + + return currentStepOffset + downVelocity; +} + + +btVector3 btKinematicCharacterController::stepDown( btCollisionWorld* collisionWorld, const btVector3& currentPosition, btScalar currentStepOffset ) +{ + btVector3 stepDrop = getUpAxisDirections()[ m_upAxis ] * currentStepOffset; + + // Be sure we are falling from the last m_currentPosition + // It prevents some flickering + // + btVector3 targetPosition = currentPosition - stepDrop; + + btTransform start; + start.setIdentity(); + start.setOrigin( currentPosition ); + + btTransform end; + end.setIdentity(); + end.setOrigin( targetPosition ); + + btKinematicClosestNotMeConvexResultCallback callback( internalGhostObject, getUpAxisDirections()[ m_upAxis ], m_maxSlopeCosine ); + callback.m_collisionFilterGroup = internalGhostObject->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = internalGhostObject->getBroadphaseHandle()->m_collisionFilterMask; + + // Retrieve the collision shape + // + btCollisionShape* collisionShape = internalGhostObject->getCollisionShape(); + btAssert( collisionShape->isConvex() ); + btConvexShape* convexShape = ( btConvexShape* )collisionShape; + + if( m_useGhostObjectSweepTest ) + externalGhostObject->convexSweepTest( convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration ); + + else + collisionWorld->convexSweepTest( convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration ); + + if( callback.hasHit() ) + { + m_verticalVelocity = btScalar( 0.0 ); + m_verticalOffset = btScalar( 0.0 ); + m_wasJumping = false; + + // We dropped a fraction of the height -> hit floor + // + return currentPosition.lerp( targetPosition, callback.m_closestHitFraction ); + } + else + + // We dropped the full height + // + return targetPosition; +} + + + +void btKinematicCharacterController::setWalkDirection( const btVector3& walkDirection ) +{ + m_useWalkDirection = true; + m_walkDirection = walkDirection; +} + + +void btKinematicCharacterController::setVelocityForTimeInterval( const btVector3& velocity, btScalar timeInterval ) +{ + m_useWalkDirection = false; + m_walkDirection = velocity; + m_velocityTimeInterval = timeInterval; +} + + +void btKinematicCharacterController::reset() +{ +} + + +void btKinematicCharacterController::warp( const btVector3& origin ) +{ + btTransform transform; + transform.setIdentity(); + transform.setOrigin( -origin ); + + externalGhostObject->setWorldTransform( transform ); + internalGhostObject->setWorldTransform( transform ); +} + + +void btKinematicCharacterController::preStep( btCollisionWorld* collisionWorld ) +{ + BT_PROFILE( "preStep" ); + + for( int i = 0; i < 4 && recoverFromPenetration ( collisionWorld ); i++ ); +} + + +void btKinematicCharacterController::playerStep( btCollisionWorld* collisionWorld, btScalar dt ) +{ + BT_PROFILE( "playerStep" ); + + if( !m_useWalkDirection && m_velocityTimeInterval <= btScalar( 0.0 ) ) + return; + + bool wasOnGround = onGround(); + + // Handle the gravity + // + m_verticalVelocity -= m_gravity * dt; + + if( m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed ) + m_verticalVelocity = m_jumpSpeed; + + if( m_verticalVelocity < 0.0 && btFabs( m_verticalVelocity ) > btFabs( m_fallSpeed ) ) + m_verticalVelocity = -btFabs( m_fallSpeed ); + + m_verticalOffset = m_verticalVelocity * dt; + + // This forced stepping up can cause problems when the character + // walks (jump in fact...) under too low ceilings. + // + btVector3 currentPosition = externalGhostObject->getWorldTransform().getOrigin(); + btScalar currentStepOffset; + + currentPosition = stepUp( collisionWorld, currentPosition, currentStepOffset ); + + // Move in the air and slide against the walls ignoring the stair steps. + // + if( m_useWalkDirection ) + currentPosition = stepForwardAndStrafe( collisionWorld, currentPosition, m_walkDirection ); + + else + { + btScalar dtMoving = ( dt < m_velocityTimeInterval ) ? dt : m_velocityTimeInterval; + m_velocityTimeInterval -= dt; + + // How far will we move while we are moving ? + // + btVector3 moveDirection = m_walkDirection * dtMoving; + + currentPosition = stepForwardAndStrafe( collisionWorld, currentPosition, moveDirection ); + } + + // Finally find the ground. + // + currentStepOffset = addFallOffset( wasOnGround, currentStepOffset, dt ); + + currentPosition = stepDown( collisionWorld, currentPosition, currentStepOffset ); + + // Apply the new position to the collision objects. + // + btTransform tranform; + tranform = externalGhostObject->getWorldTransform(); + tranform.setOrigin( currentPosition ); + + externalGhostObject->setWorldTransform( tranform ); + internalGhostObject->setWorldTransform( tranform ); +} + + +void btKinematicCharacterController::setFallSpeed( btScalar fallSpeed ) +{ + m_fallSpeed = fallSpeed; +} + + +void btKinematicCharacterController::setJumpSpeed( btScalar jumpSpeed ) +{ + m_jumpSpeed = jumpSpeed; +} + + +void btKinematicCharacterController::setMaxJumpHeight( btScalar maxJumpHeight ) +{ + m_maxJumpHeight = maxJumpHeight; +} + + +bool btKinematicCharacterController::canJump() const +{ + return onGround(); +} + + +void btKinematicCharacterController::jump() +{ + if( !canJump() ) + return; + + m_verticalVelocity = m_jumpSpeed; + m_wasJumping = true; +} + + +void btKinematicCharacterController::setGravity( btScalar gravity ) +{ + m_gravity = gravity; +} + + +btScalar btKinematicCharacterController::getGravity() const +{ + return m_gravity; +} + + +void btKinematicCharacterController::setMaxSlope( btScalar slopeRadians ) +{ + m_maxSlopeRadians = slopeRadians; + m_maxSlopeCosine = btCos( slopeRadians ); +} + + +btScalar btKinematicCharacterController::getMaxSlope() const +{ + return m_maxSlopeRadians; +} + + +bool btKinematicCharacterController::onGround() const +{ + return btFabs( m_verticalVelocity ) < btScalar( SIMD_EPSILON ) && + btFabs( m_verticalOffset ) < btScalar( SIMD_EPSILON ); +} + + +btVector3* btKinematicCharacterController::getUpAxisDirections() +{ + static btVector3 sUpAxisDirection[] = + { + btVector3( btScalar( 0.0 ), btScalar( 0.0 ), btScalar( 0.0 ) ), + btVector3( btScalar( 0.0 ), btScalar( 1.0 ), btScalar( 0.0 ) ), + btVector3( btScalar( 0.0 ), btScalar( 0.0 ), btScalar( 1.0 ) ) + }; + + return sUpAxisDirection; +} + + +void btKinematicCharacterController::debugDraw( btIDebugDraw* debugDrawer ) +{ +} diff --git a/bullet/btKinematicCharacterController.h b/bullet/btKinematicCharacterController.h new file mode 100644 index 000000000..8f32b32e9 --- /dev/null +++ b/bullet/btKinematicCharacterController.h @@ -0,0 +1,164 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com + +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 KINEMATIC_CHARACTER_CONTROLLER_H +#define KINEMATIC_CHARACTER_CONTROLLER_H + +#include "LinearMath/btVector3.h" +#include "LinearMath\btQuickprof.h" + +#include "BulletDynamics\Character\btCharacterControllerInterface.h" + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" + + +class btCollisionShape; +class btRigidBody; +class btCollisionWorld; +class btCollisionDispatcher; +class btPairCachingGhostObject; + +///btKinematicCharacterController is an object that supports a sliding motion in a world. +///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations. +///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user. +class btKinematicCharacterController : public btCharacterControllerInterface +{ +public: + enum UpAxis + { + X_AXIS = 0, + Y_AXIS = 1, + Z_AXIS = 2 + }; + +private: + btPairCachingGhostObject* externalGhostObject; // use this for querying collisions for sliding and move + btPairCachingGhostObject* internalGhostObject; // and this for recoreving from penetrations + + btScalar m_verticalVelocity; + btScalar m_verticalOffset; + btScalar m_fallSpeed; + btScalar m_jumpSpeed; + btScalar m_maxJumpHeight; + btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value) + btScalar m_maxSlopeCosine; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization) + btScalar m_gravity; + btScalar m_recoveringFactor; + + btScalar m_stepHeight; + + ///this is the desired walk direction, set by the user + btVector3 m_walkDirection; + + ///keep track of the contact manifolds + btManifoldArray m_manifoldArray; + + ///Gravity attributes + bool m_wasJumping; + + bool m_useGhostObjectSweepTest; + bool m_useWalkDirection; + btScalar m_velocityTimeInterval; + + UpAxis m_upAxis; + + static btVector3* getUpAxisDirections(); + + bool recoverFromPenetration ( btCollisionWorld* collisionWorld ); + + btVector3 stepUp( btCollisionWorld* collisionWorld, const btVector3& currentPosition, btScalar& currentStepOffset ); + btVector3 stepForwardAndStrafe( btCollisionWorld* collisionWorld, const btVector3& currentPosition, const btVector3& walkMove ); + btScalar addFallOffset( bool wasJumping, btScalar currentStepOffset, btScalar dt ); + btVector3 stepDown( btCollisionWorld* collisionWorld, const btVector3& currentPosition, btScalar currentStepOffset ); + +public: + /// externalGhostObject is used for querying the collisions for sliding along the wall, + /// and internalGhostObject is used for querying the collisions for recovering from large penetrations. + /// These parameters can point on the same object. + /// Using a smaller internalGhostObject can help for removing some flickering but create some + /// stopping artefacts when sliding along stairs or small walls. + /// Don't forget to scale gravity and fallSpeed if you scale the world. + btKinematicCharacterController( btPairCachingGhostObject* externalGhostObject, + btPairCachingGhostObject* internalGhostObject, + btScalar stepHeight, + btScalar constantScale = btScalar( 1.0 ), + btScalar gravity = btScalar( 9.8 ), + btScalar fallVelocity = btScalar( 55.0 ), + btScalar jumpVelocity = btScalar( 9.8 ), + btScalar recoveringFactor = btScalar( 0.2 ) ); + + ~btKinematicCharacterController (); + + + ///btActionInterface interface + virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTime ) + { + preStep( collisionWorld ); + playerStep( collisionWorld, deltaTime ); + } + + ///btActionInterface interface + void debugDraw( btIDebugDraw* debugDrawer ); + + void setUpAxis( UpAxis axis ) + { + m_upAxis = axis; + } + + /// This should probably be called setPositionIncrementPerSimulatorStep. + /// This is neither a direction nor a velocity, but the amount to + /// increment the position each simulation iteration, regardless + /// of dt. + /// This call will reset any velocity set by setVelocityForTimeInterval(). + virtual void setWalkDirection(const btVector3& walkDirection); + + /// Caller provides a velocity with which the character should move for + /// the given time period. After the time period, velocity is reset + /// to zero. + /// This call will reset any walk direction set by setWalkDirection(). + /// Negative time intervals will result in no motion. + virtual void setVelocityForTimeInterval(const btVector3& velocity, + btScalar timeInterval); + + void reset(); + void warp( const btVector3& origin ); + + void preStep( btCollisionWorld* collisionWorld ); + void playerStep( btCollisionWorld* collisionWorld, btScalar dt ); + + void setFallSpeed( btScalar fallSpeed ); + void setJumpSpeed( btScalar jumpSpeed ); + void setMaxJumpHeight( btScalar maxJumpHeight ); + bool canJump() const; + + void jump(); + + void setGravity( btScalar gravity ); + btScalar getGravity() const; + + /// The max slope determines the maximum angle that the controller can walk up. + /// The slope angle is measured in radians. + void setMaxSlope( btScalar slopeRadians ); + btScalar getMaxSlope() const; + + void setUseGhostSweepTest( bool useGhostObjectSweepTest ) + { + m_useGhostObjectSweepTest = useGhostObjectSweepTest; + } + + bool onGround() const; +}; + +#endif // KINEMATIC_CHARACTER_CONTROLLER_H diff --git a/bullet/physic.cpp b/bullet/physic.cpp new file mode 100644 index 000000000..d5c504cfd --- /dev/null +++ b/bullet/physic.cpp @@ -0,0 +1,275 @@ +#include "physic.hpp" +#include +#include +#include +//#include +#include "CMotionState.h" +#include "OgreRoot.h" +#include "btKinematicCharacterController.h" +#include "BtOgrePG.h" +#include "BtOgreGP.h" +#include "BtOgreExtras.h" + +#define BIT(x) (1<<(x)) + +namespace OEngine { +namespace Physic +{ + enum collisiontypes { + COL_NOTHING = 0, //setWorldTransform( transform ); + + btScalar externalCapsuleHeight = 50; + btScalar externalCapsuleWidth = 20; + + externalCollisionShape = new btCapsuleShapeZ( externalCapsuleWidth, externalCapsuleHeight ); + externalCollisionShape->setMargin( 1 ); + + externalGhostObject->setCollisionShape( externalCollisionShape ); + externalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); + + // Internal capsule + internalGhostObject = new btPairCachingGhostObject(); + internalGhostObject->setWorldTransform( transform ); + //internalGhostObject->getBroadphaseHandle()->s + btScalar internalCapsuleHeight = 20; + btScalar internalCapsuleWidth = 5; + + internalCollisionShape = new btCapsuleShapeZ( internalCapsuleWidth, internalCapsuleHeight ); + internalCollisionShape->setMargin( 1 ); + + internalGhostObject->setCollisionShape( internalCollisionShape ); + internalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); + + mCharacter = new btKinematicCharacterController( externalGhostObject,internalGhostObject,btScalar( 0.4 ),1,0 ); + mCharacter->setUpAxis(btKinematicCharacterController::UpAxis::Z_AXIS); + } + + PhysicActor::~PhysicActor() + { + delete mCharacter; + delete internalGhostObject; + delete internalCollisionShape; + delete externalGhostObject; + delete externalCollisionShape; + } + + void PhysicActor::setWalkDirection(btVector3& mvt) + { + mCharacter->setWalkDirection( mvt ); + } + + void PhysicActor::Rotate(btQuaternion& quat) + { + externalGhostObject->getWorldTransform().setRotation( externalGhostObject->getWorldTransform().getRotation() * quat ); + internalGhostObject->getWorldTransform().setRotation( internalGhostObject->getWorldTransform().getRotation() * quat ); + } + + void PhysicActor::setRotation(btQuaternion& quat) + { + externalGhostObject->getWorldTransform().setRotation( quat ); + internalGhostObject->getWorldTransform().setRotation( quat ); + } + + btVector3 PhysicActor::getPosition(void) + { + return internalGhostObject->getWorldTransform().getOrigin(); + } + + btQuaternion PhysicActor::getRotation(void) + { + return internalGhostObject->getWorldTransform().getRotation(); + } + + void PhysicActor::setPosition(btVector3& pos) + { + internalGhostObject->getWorldTransform().setOrigin(pos); + externalGhostObject->getWorldTransform().setOrigin(pos); + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + RigidBody::RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name) + :btRigidBody(CI),mName(name) + { + + }; + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////////////////// + + + + PhysicEngine::PhysicEngine() + { + // Set up the collision configuration and dispatcher + collisionConfiguration = new btDefaultCollisionConfiguration(); + dispatcher = new btCollisionDispatcher(collisionConfiguration); + + // The actual physics solver + solver = new btSequentialImpulseConstraintSolver; + + //TODO: memory leak? + btOverlappingPairCache* pairCache = new btSortedOverlappingPairCache(); + pairCache->setInternalGhostPairCallback( new btGhostPairCallback() ); + + broadphase = new btDbvtBroadphase(pairCache); + + // The world. + dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration); + dynamicsWorld->setGravity(btVector3(0,0,-10)); + + if(BulletShapeManager::getSingletonPtr() == NULL) + { + new BulletShapeManager(); + } + //TODO:singleton? + ShapeLoader = new ManualBulletShapeLoader(); + + isDebugCreated = false; + } + + void PhysicEngine::createDebugRendering() + { + if(!isDebugCreated) + { + Ogre::SceneManagerEnumerator::SceneManagerIterator iter = Ogre::Root::getSingleton().getSceneManagerIterator(); + iter.begin(); + Ogre::SceneManager* scn = iter.getNext(); + Ogre::SceneNode* node = scn->getRootSceneNode()->createChildSceneNode(); + node->pitch(Ogre::Degree(-90)); + mDebugDrawer = new BtOgre::DebugDrawer(node, dynamicsWorld); + dynamicsWorld->setDebugDrawer(mDebugDrawer); + isDebugCreated = true; + dynamicsWorld->debugDrawWorld(); + } + } + + void PhysicEngine::setDebugRenderingMode(int mode) + { + if(!isDebugCreated) + { + createDebugRendering(); + } + mDebugDrawer->setDebugMode(mode); + } + + PhysicEngine::~PhysicEngine() + { + delete dynamicsWorld; + delete solver; + delete collisionConfiguration; + delete dispatcher; + delete broadphase; + delete ShapeLoader; + } + + RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name) + { + //get the shape from the .nif + ShapeLoader->load(mesh,"General"); + BulletShapeManager::getSingletonPtr()->load(mesh,"General"); + BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(mesh,"General"); + + //create the motionState + CMotionState* newMotionState = new CMotionState(this,name); + + //create the real body + btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,shape->Shape); + RigidBody* body = new RigidBody(CI,name); + + return body; + } + + void PhysicEngine::addRigidBody(RigidBody* body) + { + dynamicsWorld->addRigidBody(body,COL_WORLD,COL_WORLD|COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL); + body->setActivationState(DISABLE_DEACTIVATION); + RigidBodyMap[body->mName] = body; + } + + void PhysicEngine::removeRigidBody(std::string name) + { + RigidBody* body = RigidBodyMap[name]; + if(body != NULL) + { + dynamicsWorld->removeRigidBody(RigidBodyMap[name]); + } + } + + void PhysicEngine::deleteRigidBody(std::string name) + { + RigidBody* body = RigidBodyMap[name]; + if(body != NULL) + { + delete body; + RigidBodyMap[name] = NULL; + } + } + + RigidBody* PhysicEngine::getRigidBody(std::string name) + { + RigidBody* body = RigidBodyMap[name]; + return body; + } + + void PhysicEngine::stepSimulation(double deltaT) + { + dynamicsWorld->stepSimulation(deltaT,1,1/30.); + if(isDebugCreated) + { + mDebugDrawer->step(); + } + } + + void PhysicEngine::addCharacter(std::string name) + { + PhysicActor* newActor = new PhysicActor(name); + dynamicsWorld->addCollisionObject( newActor->externalGhostObject, COL_ACTOR_EXTERNAL, COL_WORLD |COL_ACTOR_EXTERNAL ); + dynamicsWorld->addCollisionObject( newActor->internalGhostObject, COL_ACTOR_INTERNAL, COL_WORLD |COL_ACTOR_INTERNAL ); + dynamicsWorld->addAction( newActor->mCharacter ); + PhysicActorMap[name] = newActor; + } + + void PhysicEngine::removeCharacter(std::string name) + { + PhysicActor* act = PhysicActorMap[name]; + if(act != NULL) + { + dynamicsWorld->removeCollisionObject(act->externalGhostObject); + dynamicsWorld->removeCollisionObject(act->internalGhostObject); + dynamicsWorld->removeAction(act->mCharacter); + delete act; + PhysicActorMap[name] = NULL; + } + } + + PhysicActor* PhysicEngine::getCharacter(std::string name) + { + PhysicActor* act = PhysicActorMap[name]; + return act; + } + + void PhysicEngine::emptyEventLists(void) + { + } +}}; \ No newline at end of file diff --git a/bullet/physic.hpp b/bullet/physic.hpp new file mode 100644 index 000000000..5fdc03e7d --- /dev/null +++ b/bullet/physic.hpp @@ -0,0 +1,190 @@ +#ifndef OENGINE_BULLET_PHYSIC_H +#define OENGINE_BULLET_PHYSIC_H + +#include +#include "BulletCollision/CollisionDispatch/btGhostObject.h" +#include +#include +#include + +class btRigidBody; +class btBroadphaseInterface; +class btDefaultCollisionConfiguration; +class btSequentialImpulseConstraintSolver; +class btCollisionDispatcher; +class btDiscreteDynamicsWorld; +class btKinematicCharacterController; + +namespace BtOgre +{ + class DebugDrawer; +} + +class BulletShapeManager; +class ManualBulletShapeLoader; + +namespace MWWorld +{ + class World; +} + +namespace OEngine { +namespace Physic +{ + class CMotionState; + struct PhysicEvent; + + /** + *A physic Actor use a modifed KinematicCharacterController taken in the bullet forum. + */ + class PhysicActor + { + public: + PhysicActor(std::string name); + + ~PhysicActor(); + + /** + *This function set the walkDirection. This is not relative to the actor orientation. + *I think it's also needed to take time into account. A typical call should look like this: + *setWalkDirection( mvt * orientation * dt) + */ + void setWalkDirection(btVector3& mvt); + + void Rotate(btQuaternion& quat); + + void setRotation(btQuaternion& quat); + + btVector3 getPosition(void); + + btQuaternion getRotation(void); + + void setPosition(btVector3& pos); + + btKinematicCharacterController* mCharacter; + + btPairCachingGhostObject* internalGhostObject; + btCollisionShape* internalCollisionShape; + + btPairCachingGhostObject* externalGhostObject; + btCollisionShape* externalCollisionShape; + + std::string mName; + }; + + /** + *This class is just an extension of normal btRigidBody in order to add extra info. + *When bullet give back a btRigidBody, you can just do a static_cast to RigidBody, + *so one never should use btRigidBody directly! + */ + class RigidBody: public btRigidBody + { + public: + RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name); + std::string mName; + }; + + /** + *The PhysicEngine class contain everything which is needed for Physic. + *It's needed that Ogre Resources are set up before the PhysicEngine is created. + *Note:deleting it WILL NOT delete the RigidBody! + *TODO:unload unused resources? + */ + class PhysicEngine + { + public: + PhysicEngine(); + ~PhysicEngine(); + + /** + *create a RigidBody.It does not add it to the simulation, but it does add it to the rigidBody Map, + *so you can get it with the getRigidBody function. + */ + RigidBody* createRigidBody(std::string mesh,std::string name); + + /** + *Add a RigidBody to the simulation + */ + void addRigidBody(RigidBody* body); + + /** + *Remove a RigidBody from the simulation. It does not delete it, and does not remove it from the RigidBodyMap. + */ + void removeRigidBody(std::string name); + + /** + *delete a RigidBody, and remove it from RigidBodyMap. + */ + void deleteRigidBody(std::string name); + + /** + *Return a pointer to a given rigid body. + *TODO:check if exist + */ + RigidBody* getRigidBody(std::string name); + + /** + *Create and add a character to the scene, and add it to the ActorMap. + */ + void addCharacter(std::string name); + + /** + *Remove a character from the scene. TODO:delete it! for now, a small memory leak^^ done? + */ + void removeCharacter(std::string name); + + /** + *return a pointer to a character + *TODO:check if the actor exist... + */ + PhysicActor* getCharacter(std::string name); + + /** + *This step the simulation of a given time. + */ + void stepSimulation(double deltaT); + + /** + *Empty events lists + */ + void emptyEventLists(void); + + /** + *Create a debug rendering. It is called by setDebgRenderingMode if it's not created yet. + *Important Note: this will crash if the Render is not yet initialise! + */ + void createDebugRendering(); + + /** + *Set the debug rendering mode. 0 to turn it off. + *Important Note: this will crash if the Render is not yet initialise! + */ + void setDebugRenderingMode(int mode); + + //event list of non player object + std::list NPEventList; + + //event list affecting the player + std::list PEventList; + + //Bullet Stuff + btBroadphaseInterface* broadphase; + btDefaultCollisionConfiguration* collisionConfiguration; + btSequentialImpulseConstraintSolver* solver; + btCollisionDispatcher* dispatcher; + btDiscreteDynamicsWorld* dynamicsWorld; + + //the NIF file loader. + ManualBulletShapeLoader* ShapeLoader; + + std::map RigidBodyMap; + std::map PhysicActorMap; + + //debug rendering + BtOgre::DebugDrawer* mDebugDrawer; + bool isDebugCreated; + }; + +}} + +#endif \ No newline at end of file From f071328d5535bfa061359d6e233c2a8c2fdb6d3b Mon Sep 17 00:00:00 2001 From: gugus Date: Tue, 22 Feb 2011 14:04:12 +0100 Subject: [PATCH 27/56] add debug rendering --- bullet/BtOgre.cpp | 1044 +++++++++++++++++++++++++++++++++++++++++ bullet/BtOgreExtras.h | 280 +++++++++++ bullet/BtOgrePG.h | 81 ++++ 3 files changed, 1405 insertions(+) create mode 100644 bullet/BtOgre.cpp create mode 100644 bullet/BtOgreExtras.h create mode 100644 bullet/BtOgrePG.h diff --git a/bullet/BtOgre.cpp b/bullet/BtOgre.cpp new file mode 100644 index 000000000..82ed2cbc2 --- /dev/null +++ b/bullet/BtOgre.cpp @@ -0,0 +1,1044 @@ +/* + * ============================================================================================= + * + * Filename: BtOgre.cpp + * + * Description: BtOgre implementation. + * + * Version: 1.0 + * Created: 27/12/2008 01:47:56 PM + * + * Author: Nikhilesh (nikki) + * + * ============================================================================================= + */ + +#include "BtOgrePG.h" +#include "BtOgreGP.h" +#include "BtOgreExtras.h" + +using namespace Ogre; + +namespace BtOgre { + +/* + * ============================================================================================= + * BtOgre::VertexIndexToShape + * ============================================================================================= + */ + + void VertexIndexToShape::addStaticVertexData(const VertexData *vertex_data) + { + if (!vertex_data) + return; + + const VertexData *data = vertex_data; + + const unsigned int prev_size = mVertexCount; + mVertexCount += (unsigned int)data->vertexCount; + + Ogre::Vector3* tmp_vert = new Ogre::Vector3[mVertexCount]; + if (mVertexBuffer) + { + memcpy(tmp_vert, mVertexBuffer, sizeof(Vector3) * prev_size); + delete[] mVertexBuffer; + } + mVertexBuffer = tmp_vert; + + // Get the positional buffer element + { + const Ogre::VertexElement* posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); + Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource()); + const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); + + unsigned char* vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); + float* pReal; + Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size]; + const unsigned int vertexCount = (unsigned int)data->vertexCount; + for(unsigned int j = 0; j < vertexCount; ++j) + { + posElem->baseVertexPointerToElement(vertex, &pReal); + vertex += vSize; + + curVertices->x = (*pReal++); + curVertices->y = (*pReal++); + curVertices->z = (*pReal++); + + *curVertices = mTransform * (*curVertices); + + curVertices++; + } + vbuf->unlock(); + } + } + //------------------------------------------------------------------------------------------------ + void VertexIndexToShape::addAnimatedVertexData(const Ogre::VertexData *vertex_data, + const Ogre::VertexData *blend_data, + const Ogre::Mesh::IndexMap *indexMap) + { + // Get the bone index element + assert(vertex_data); + + const VertexData *data = blend_data; + const unsigned int prev_size = mVertexCount; + mVertexCount += (unsigned int)data->vertexCount; + Ogre::Vector3* tmp_vert = new Ogre::Vector3[mVertexCount]; + if (mVertexBuffer) + { + memcpy(tmp_vert, mVertexBuffer, sizeof(Vector3) * prev_size); + delete[] mVertexBuffer; + } + mVertexBuffer = tmp_vert; + + // Get the positional buffer element + { + const Ogre::VertexElement* posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); + assert (posElem); + Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource()); + const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); + + unsigned char* vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); + float* pReal; + Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size]; + const unsigned int vertexCount = (unsigned int)data->vertexCount; + for(unsigned int j = 0; j < vertexCount; ++j) + { + posElem->baseVertexPointerToElement(vertex, &pReal); + vertex += vSize; + + curVertices->x = (*pReal++); + curVertices->y = (*pReal++); + curVertices->z = (*pReal++); + + *curVertices = mTransform * (*curVertices); + + curVertices++; + } + vbuf->unlock(); + } + { + const Ogre::VertexElement* bneElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_BLEND_INDICES); + assert (bneElem); + + Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(bneElem->getSource()); + const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); + unsigned char* vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); + + unsigned char* pBone; + + if (!mBoneIndex) + mBoneIndex = new BoneIndex(); + BoneIndex::iterator i; + + Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size]; + + const unsigned int vertexCount = (unsigned int)vertex_data->vertexCount; + for(unsigned int j = 0; j < vertexCount; ++j) + { + bneElem->baseVertexPointerToElement(vertex, &pBone); + vertex += vSize; + + const unsigned char currBone = (indexMap) ? (*indexMap)[*pBone] : *pBone; + i = mBoneIndex->find (currBone); + Vector3Array* l = 0; + if (i == mBoneIndex->end()) + { + l = new Vector3Array; + mBoneIndex->insert(BoneKeyIndex(currBone, l)); + } + else + { + l = i->second; + } + + l->push_back(*curVertices); + + curVertices++; + } + vbuf->unlock(); + } + } + //------------------------------------------------------------------------------------------------ + void VertexIndexToShape::addIndexData(IndexData *data, const unsigned int offset) + { + const unsigned int prev_size = mIndexCount; + mIndexCount += (unsigned int)data->indexCount; + + unsigned int* tmp_ind = new unsigned int[mIndexCount]; + if (mIndexBuffer) + { + memcpy (tmp_ind, mIndexBuffer, sizeof(unsigned int) * prev_size); + delete[] mIndexBuffer; + } + mIndexBuffer = tmp_ind; + + const unsigned int numTris = (unsigned int) data->indexCount / 3; + HardwareIndexBufferSharedPtr ibuf = data->indexBuffer; + const bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT); + unsigned int index_offset = prev_size; + + if (use32bitindexes) + { + const unsigned int* pInt = static_cast(ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); + for(unsigned int k = 0; k < numTris; ++k) + { + mIndexBuffer[index_offset ++] = offset + *pInt++; + mIndexBuffer[index_offset ++] = offset + *pInt++; + mIndexBuffer[index_offset ++] = offset + *pInt++; + } + ibuf->unlock(); + } + else + { + const unsigned short* pShort = static_cast(ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); + for(unsigned int k = 0; k < numTris; ++k) + { + mIndexBuffer[index_offset ++] = offset + static_cast (*pShort++); + mIndexBuffer[index_offset ++] = offset + static_cast (*pShort++); + mIndexBuffer[index_offset ++] = offset + static_cast (*pShort++); + } + ibuf->unlock(); + } + + } + //------------------------------------------------------------------------------------------------ + Real VertexIndexToShape::getRadius() + { + if (mBoundRadius == (-1)) + { + getSize(); + mBoundRadius = (std::max(mBounds.x,std::max(mBounds.y,mBounds.z)) * 0.5); + } + return mBoundRadius; + } + //------------------------------------------------------------------------------------------------ + Vector3 VertexIndexToShape::getSize() + { + const unsigned int vCount = getVertexCount(); + if (mBounds == Ogre::Vector3(-1,-1,-1) && vCount > 0) + { + + const Ogre::Vector3 * const v = getVertices(); + + Ogre::Vector3 vmin(v[0]); + Ogre::Vector3 vmax(v[0]); + + for(unsigned int j = 1; j < vCount; j++) + { + vmin.x = std::min(vmin.x, v[j].x); + vmin.y = std::min(vmin.y, v[j].y); + vmin.z = std::min(vmin.z, v[j].z); + + vmax.x = std::max(vmax.x, v[j].x); + vmax.y = std::max(vmax.y, v[j].y); + vmax.z = std::max(vmax.z, v[j].z); + } + + mBounds.x = vmax.x - vmin.x; + mBounds.y = vmax.y - vmin.y; + mBounds.z = vmax.z - vmin.z; + } + + return mBounds; + } + //------------------------------------------------------------------------------------------------ + const Ogre::Vector3* VertexIndexToShape::getVertices() + { + return mVertexBuffer; + } + //------------------------------------------------------------------------------------------------ + unsigned int VertexIndexToShape::getVertexCount() + { + return mVertexCount; + } + //------------------------------------------------------------------------------------------------ + const unsigned int* VertexIndexToShape::getIndices() + { + return mIndexBuffer; + } + //------------------------------------------------------------------------------------------------ + unsigned int VertexIndexToShape::getIndexCount() + { + return mIndexCount; + } + + //------------------------------------------------------------------------------------------------ + btSphereShape* VertexIndexToShape::createSphere() + { + const Ogre::Real rad = getRadius(); + assert((rad > 0.0) && + ("Sphere radius must be greater than zero")); + btSphereShape* shape = new btSphereShape(rad); + + shape->setLocalScaling(Convert::toBullet(mScale)); + + return shape; + } + //------------------------------------------------------------------------------------------------ + btBoxShape* VertexIndexToShape::createBox() + { + const Ogre::Vector3 sz = getSize(); + + assert((sz.x > 0.0) && (sz.y > 0.0) && (sz.y > 0.0) && + ("Size of box must be greater than zero on all axes")); + + btBoxShape* shape = new btBoxShape(Convert::toBullet(sz * 0.5)); + + shape->setLocalScaling(Convert::toBullet(mScale)); + + return shape; + } + //------------------------------------------------------------------------------------------------ + btCylinderShape* VertexIndexToShape::createCylinder() + { + const Ogre::Vector3 sz = getSize(); + + assert((sz.x > 0.0) && (sz.y > 0.0) && (sz.y > 0.0) && + ("Size of Cylinder must be greater than zero on all axes")); + + btCylinderShape* shape = new btCylinderShapeX(Convert::toBullet(sz * 0.5)); + + shape->setLocalScaling(Convert::toBullet(mScale)); + + return shape; + } + //------------------------------------------------------------------------------------------------ + btConvexHullShape* VertexIndexToShape::createConvex() + { + assert(mVertexCount && (mIndexCount >= 6) && + ("Mesh must have some vertices and at least 6 indices (2 triangles)")); + + return new btConvexHullShape((btScalar*) &mVertexBuffer[0].x, mVertexCount, sizeof(Vector3)); + } + //------------------------------------------------------------------------------------------------ + btBvhTriangleMeshShape* VertexIndexToShape::createTrimesh() + { + assert(mVertexCount && (mIndexCount >= 6) && + ("Mesh must have some vertices and at least 6 indices (2 triangles)")); + + unsigned int numFaces = mIndexCount / 3; + + btTriangleMesh *trimesh = new btTriangleMesh(); + unsigned int *indices = mIndexBuffer; + Vector3 *vertices = mVertexBuffer; + + btVector3 vertexPos[3]; + for (unsigned int n = 0; n < numFaces; ++n) + { + { + const Vector3 &vec = vertices[*indices]; + vertexPos[0][0] = vec.x; + vertexPos[0][1] = vec.y; + vertexPos[0][2] = vec.z; + } + { + const Vector3 &vec = vertices[*(indices + 1)]; + vertexPos[1][0] = vec.x; + vertexPos[1][1] = vec.y; + vertexPos[1][2] = vec.z; + } + { + const Vector3 &vec = vertices[*(indices + 2)]; + vertexPos[2][0] = vec.x; + vertexPos[2][1] = vec.y; + vertexPos[2][2] = vec.z; + } + + indices += 3; + + trimesh->addTriangle(vertexPos[0], vertexPos[1], vertexPos[2]); + } + + const bool useQuantizedAABB = true; + btBvhTriangleMeshShape *shape = new btBvhTriangleMeshShape(trimesh, useQuantizedAABB); + + shape->setLocalScaling(Convert::toBullet(mScale)); + + return shape; + } + //------------------------------------------------------------------------------------------------ + VertexIndexToShape::~VertexIndexToShape() + { + delete[] mVertexBuffer; + delete[] mIndexBuffer; + + if (mBoneIndex) + { + for(BoneIndex::iterator i = mBoneIndex->begin(); + i != mBoneIndex->end(); + ++i) + { + delete i->second; + } + delete mBoneIndex; + } + } + //------------------------------------------------------------------------------------------------ + VertexIndexToShape::VertexIndexToShape(const Matrix4 &transform) : + mVertexBuffer (0), + mIndexBuffer (0), + mVertexCount (0), + mIndexCount (0), + mBounds (Vector3(-1,-1,-1)), + mBoundRadius (-1), + mBoneIndex (0), + mTransform (transform), + mScale(1) + { + } + +/* + * ============================================================================================= + * BtOgre::StaticMeshToShapeConverter + * ============================================================================================= + */ + + StaticMeshToShapeConverter::StaticMeshToShapeConverter() : + VertexIndexToShape(), + mEntity (0), + mNode (0) + { + } + //------------------------------------------------------------------------------------------------ + StaticMeshToShapeConverter::~StaticMeshToShapeConverter() + { + } + //------------------------------------------------------------------------------------------------ + StaticMeshToShapeConverter::StaticMeshToShapeConverter(Entity *entity, const Matrix4 &transform) : + VertexIndexToShape(transform), + mEntity (0), + mNode (0) + { + addEntity(entity, transform); + } + //------------------------------------------------------------------------------------------------ + StaticMeshToShapeConverter::StaticMeshToShapeConverter(Renderable *rend, const Matrix4 &transform) : + VertexIndexToShape(transform), + mEntity (0), + mNode (0) + { + RenderOperation op; + rend->getRenderOperation(op); + VertexIndexToShape::addStaticVertexData(op.vertexData); + if(op.useIndexes) + VertexIndexToShape::addIndexData(op.indexData); + + } + //------------------------------------------------------------------------------------------------ + void StaticMeshToShapeConverter::addEntity(Entity *entity,const Matrix4 &transform) + { + // Each entity added need to reset size and radius + // next time getRadius and getSize are asked, they're computed. + mBounds = Ogre::Vector3(-1,-1,-1); + mBoundRadius = -1; + + mEntity = entity; + mNode = (SceneNode*)(mEntity->getParentNode()); + mTransform = transform; + mScale = mNode->getScale(); + + if (mEntity->getMesh()->sharedVertexData) + { + VertexIndexToShape::addStaticVertexData (mEntity->getMesh()->sharedVertexData); + } + + for (unsigned int i = 0;i < mEntity->getNumSubEntities();++i) + { + SubMesh *sub_mesh = mEntity->getSubEntity(i)->getSubMesh(); + + if (!sub_mesh->useSharedVertices) + { + VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount); + VertexIndexToShape::addStaticVertexData (sub_mesh->vertexData); + } + else + { + VertexIndexToShape::addIndexData (sub_mesh->indexData); + } + + } + } + //------------------------------------------------------------------------------------------------ + void StaticMeshToShapeConverter::addMesh(const MeshPtr &mesh, const Matrix4 &transform) + { + // Each entity added need to reset size and radius + // next time getRadius and getSize are asked, they're computed. + mBounds = Ogre::Vector3(-1,-1,-1); + mBoundRadius = -1; + + //_entity = entity; + //_node = (SceneNode*)(_entity->getParentNode()); + mTransform = transform; + + if (mesh->hasSkeleton ()) + Ogre::LogManager::getSingleton().logMessage("MeshToShapeConverter::addMesh : Mesh " + mesh->getName () + " as skeleton but added to trimesh non animated"); + + if (mesh->sharedVertexData) + { + VertexIndexToShape::addStaticVertexData (mesh->sharedVertexData); + } + + for(unsigned int i = 0;i < mesh->getNumSubMeshes();++i) + { + SubMesh *sub_mesh = mesh->getSubMesh(i); + + if (!sub_mesh->useSharedVertices) + { + VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount); + VertexIndexToShape::addStaticVertexData (sub_mesh->vertexData); + } + else + { + VertexIndexToShape::addIndexData (sub_mesh->indexData); + } + + } + } + +/* + * ============================================================================================= + * BtOgre::AnimatedMeshToShapeConverter + * ============================================================================================= + */ + + AnimatedMeshToShapeConverter::AnimatedMeshToShapeConverter(Entity *entity,const Matrix4 &transform) : + VertexIndexToShape(transform), + mEntity (0), + mNode (0), + mTransformedVerticesTemp(0), + mTransformedVerticesTempSize(0) + { + addEntity(entity, transform); + } + //------------------------------------------------------------------------------------------------ + AnimatedMeshToShapeConverter::AnimatedMeshToShapeConverter() : + VertexIndexToShape(), + mEntity (0), + mNode (0), + mTransformedVerticesTemp(0), + mTransformedVerticesTempSize(0) + { + } + //------------------------------------------------------------------------------------------------ + AnimatedMeshToShapeConverter::~AnimatedMeshToShapeConverter() + { + delete[] mTransformedVerticesTemp; + } + //------------------------------------------------------------------------------------------------ + void AnimatedMeshToShapeConverter::addEntity(Entity *entity,const Matrix4 &transform) + { + // Each entity added need to reset size and radius + // next time getRadius and getSize are asked, they're computed. + mBounds = Ogre::Vector3(-1,-1,-1); + mBoundRadius = -1; + + mEntity = entity; + mNode = (SceneNode*)(mEntity->getParentNode()); + mTransform = transform; + + assert (entity->getMesh()->hasSkeleton ()); + + mEntity->addSoftwareAnimationRequest(false); + mEntity->_updateAnimation(); + + if (mEntity->getMesh()->sharedVertexData) + { + VertexIndexToShape::addAnimatedVertexData (mEntity->getMesh()->sharedVertexData, + mEntity->_getSkelAnimVertexData(), + &mEntity->getMesh()->sharedBlendIndexToBoneIndexMap); + } + + for (unsigned int i = 0;i < mEntity->getNumSubEntities();++i) + { + SubMesh *sub_mesh = mEntity->getSubEntity(i)->getSubMesh(); + + if (!sub_mesh->useSharedVertices) + { + VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount); + + VertexIndexToShape::addAnimatedVertexData (sub_mesh->vertexData, + mEntity->getSubEntity(i)->_getSkelAnimVertexData(), + &sub_mesh->blendIndexToBoneIndexMap); + } + else + { + VertexIndexToShape::addIndexData (sub_mesh->indexData); + } + + } + + mEntity->removeSoftwareAnimationRequest(false); + } + //------------------------------------------------------------------------------------------------ + void AnimatedMeshToShapeConverter::addMesh(const MeshPtr &mesh, const Matrix4 &transform) + { + // Each entity added need to reset size and radius + // next time getRadius and getSize are asked, they're computed. + mBounds = Ogre::Vector3(-1,-1,-1); + mBoundRadius = -1; + + //_entity = entity; + //_node = (SceneNode*)(_entity->getParentNode()); + mTransform = transform; + + assert (mesh->hasSkeleton ()); + + if (mesh->sharedVertexData) + { + VertexIndexToShape::addAnimatedVertexData (mesh->sharedVertexData, + 0, + &mesh->sharedBlendIndexToBoneIndexMap); + } + + for(unsigned int i = 0;i < mesh->getNumSubMeshes();++i) + { + SubMesh *sub_mesh = mesh->getSubMesh(i); + + if (!sub_mesh->useSharedVertices) + { + VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount); + + VertexIndexToShape::addAnimatedVertexData (sub_mesh->vertexData, + 0, + &sub_mesh->blendIndexToBoneIndexMap); + } + else + { + VertexIndexToShape::addIndexData (sub_mesh->indexData); + } + + } + } + //------------------------------------------------------------------------------------------------ + bool AnimatedMeshToShapeConverter::getBoneVertices(unsigned char bone, + unsigned int &vertex_count, + Ogre::Vector3* &vertices, + const Vector3 &bonePosition) + { + BoneIndex::iterator i = mBoneIndex->find(bone); + + if (i == mBoneIndex->end()) + return false; + + if (i->second->empty()) + return false; + + vertex_count = (unsigned int) i->second->size() + 1; + if (vertex_count > mTransformedVerticesTempSize) + { + if (mTransformedVerticesTemp) + delete[] mTransformedVerticesTemp; + + mTransformedVerticesTemp = new Ogre::Vector3[vertex_count]; + + } + + vertices = mTransformedVerticesTemp; + vertices[0] = bonePosition; + //mEntity->_getParentNodeFullTransform() * + // mEntity->getSkeleton()->getBone(bone)->_getDerivedPosition(); + + //mEntity->getSkeleton()->getBone(bone)->_getDerivedOrientation() + unsigned int currBoneVertex = 1; + Vector3Array::iterator j = i->second->begin(); + while(j != i->second->end()) + { + vertices[currBoneVertex] = (*j); + ++j; + ++currBoneVertex; + } + return true; + } + //------------------------------------------------------------------------------------------------ + btBoxShape* AnimatedMeshToShapeConverter::createAlignedBox(unsigned char bone, + const Vector3 &bonePosition, + const Quaternion &boneOrientation) + { + unsigned int vertex_count; + Vector3* vertices; + + if (!getBoneVertices(bone, vertex_count, vertices, bonePosition)) + return 0; + + Vector3 min_vec(vertices[0]); + Vector3 max_vec(vertices[0]); + + for(unsigned int j = 1; j < vertex_count ;j++) + { + min_vec.x = std::min(min_vec.x,vertices[j].x); + min_vec.y = std::min(min_vec.y,vertices[j].y); + min_vec.z = std::min(min_vec.z,vertices[j].z); + + max_vec.x = std::max(max_vec.x,vertices[j].x); + max_vec.y = std::max(max_vec.y,vertices[j].y); + max_vec.z = std::max(max_vec.z,vertices[j].z); + } + const Ogre::Vector3 maxMinusMin(max_vec - min_vec); + btBoxShape* box = new btBoxShape(Convert::toBullet(maxMinusMin)); + + /*const Ogre::Vector3 pos + (min_vec.x + (maxMinusMin.x * 0.5), + min_vec.y + (maxMinusMin.y * 0.5), + min_vec.z + (maxMinusMin.z * 0.5));*/ + + //box->setPosition(pos); + + return box; + } + //------------------------------------------------------------------------------------------------ + bool AnimatedMeshToShapeConverter::getOrientedBox(unsigned char bone, + const Vector3 &bonePosition, + const Quaternion &boneOrientation, + Vector3 &box_afExtent, + Vector3 *box_akAxis, + Vector3 &box_kCenter) + { + unsigned int vertex_count; + Vector3* vertices; + + if (!getBoneVertices(bone, vertex_count, vertices, bonePosition)) + return false; + + box_kCenter = Vector3::ZERO; + + { + for(unsigned int c = 0 ;c < vertex_count;c++) + { + box_kCenter += vertices[c]; + } + const Ogre::Real invVertexCount = 1.0 / vertex_count; + box_kCenter *= invVertexCount; + } + Quaternion orient = boneOrientation; + orient.ToAxes(box_akAxis); + + // Let C be the box center and let U0, U1, and U2 be the box axes. Each + // input point is of the form X = C + y0*U0 + y1*U1 + y2*U2. The + // following code computes min(y0), max(y0), min(y1), max(y1), min(y2), + // and max(y2). The box center is then adjusted to be + // C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1 + + // 0.5*(min(y2)+max(y2))*U2 + + Ogre::Vector3 kDiff (vertices[1] - box_kCenter); + Ogre::Real fY0Min = kDiff.dotProduct(box_akAxis[0]), fY0Max = fY0Min; + Ogre::Real fY1Min = kDiff.dotProduct(box_akAxis[1]), fY1Max = fY1Min; + Ogre::Real fY2Min = kDiff.dotProduct(box_akAxis[2]), fY2Max = fY2Min; + + for (unsigned int i = 2; i < vertex_count; i++) + { + kDiff = vertices[i] - box_kCenter; + + const Ogre::Real fY0 = kDiff.dotProduct(box_akAxis[0]); + if ( fY0 < fY0Min ) + fY0Min = fY0; + else if ( fY0 > fY0Max ) + fY0Max = fY0; + + const Ogre::Real fY1 = kDiff.dotProduct(box_akAxis[1]); + if ( fY1 < fY1Min ) + fY1Min = fY1; + else if ( fY1 > fY1Max ) + fY1Max = fY1; + + const Ogre::Real fY2 = kDiff.dotProduct(box_akAxis[2]); + if ( fY2 < fY2Min ) + fY2Min = fY2; + else if ( fY2 > fY2Max ) + fY2Max = fY2; + } + + box_afExtent.x = ((Real)0.5)*(fY0Max - fY0Min); + box_afExtent.y = ((Real)0.5)*(fY1Max - fY1Min); + box_afExtent.z = ((Real)0.5)*(fY2Max - fY2Min); + + box_kCenter += (0.5*(fY0Max+fY0Min))*box_akAxis[0] + + (0.5*(fY1Max+fY1Min))*box_akAxis[1] + + (0.5*(fY2Max+fY2Min))*box_akAxis[2]; + + box_afExtent *= 2.0; + + return true; + } + //------------------------------------------------------------------------------------------------ + btBoxShape *AnimatedMeshToShapeConverter::createOrientedBox(unsigned char bone, + const Vector3 &bonePosition, + const Quaternion &boneOrientation) + { + Ogre::Vector3 box_akAxis[3]; + Ogre::Vector3 box_afExtent; + Ogre::Vector3 box_afCenter; + + if (!getOrientedBox(bone, bonePosition, boneOrientation, + box_afExtent, + box_akAxis, + box_afCenter)) + return 0; + + btBoxShape *geom = new btBoxShape(Convert::toBullet(box_afExtent)); + //geom->setOrientation(Quaternion(box_akAxis[0],box_akAxis[1],box_akAxis[2])); + //geom->setPosition(box_afCenter); + return geom; + } + +/* + * ============================================================================================= + * BtOgre::DynamicRenderable + * ============================================================================================= + */ + + DynamicRenderable::DynamicRenderable() + { + } + //------------------------------------------------------------------------------------------------ + DynamicRenderable::~DynamicRenderable() + { + delete mRenderOp.vertexData; + delete mRenderOp.indexData; + } + //------------------------------------------------------------------------------------------------ + void DynamicRenderable::initialize(RenderOperation::OperationType operationType, + bool useIndices) + { + // Initialize render operation + mRenderOp.operationType = operationType; + mRenderOp.useIndexes = useIndices; + mRenderOp.vertexData = new VertexData; + if (mRenderOp.useIndexes) + mRenderOp.indexData = new IndexData; + + // Reset buffer capacities + mVertexBufferCapacity = 0; + mIndexBufferCapacity = 0; + + // Create vertex declaration + createVertexDeclaration(); + } + //------------------------------------------------------------------------------------------------ + void DynamicRenderable::prepareHardwareBuffers(size_t vertexCount, + size_t indexCount) + { + // Prepare vertex buffer + size_t newVertCapacity = mVertexBufferCapacity; + if ((vertexCount > mVertexBufferCapacity) || + (!mVertexBufferCapacity)) + { + // vertexCount exceeds current capacity! + // It is necessary to reallocate the buffer. + + // Check if this is the first call + if (!newVertCapacity) + newVertCapacity = 1; + + // Make capacity the next power of two + while (newVertCapacity < vertexCount) + newVertCapacity <<= 1; + } + else if (vertexCount < mVertexBufferCapacity>>1) { + // Make capacity the previous power of two + while (vertexCount < newVertCapacity>>1) + newVertCapacity >>= 1; + } + if (newVertCapacity != mVertexBufferCapacity) + { + mVertexBufferCapacity = newVertCapacity; + // Create new vertex buffer + HardwareVertexBufferSharedPtr vbuf = + HardwareBufferManager::getSingleton().createVertexBuffer( + mRenderOp.vertexData->vertexDeclaration->getVertexSize(0), + mVertexBufferCapacity, + HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // TODO: Custom HBU_? + + // Bind buffer + mRenderOp.vertexData->vertexBufferBinding->setBinding(0, vbuf); + } + // Update vertex count in the render operation + mRenderOp.vertexData->vertexCount = vertexCount; + + if (mRenderOp.useIndexes) + { + OgreAssert(indexCount <= std::numeric_limits::max(), "indexCount exceeds 16 bit"); + + size_t newIndexCapacity = mIndexBufferCapacity; + // Prepare index buffer + if ((indexCount > newIndexCapacity) || + (!newIndexCapacity)) + { + // indexCount exceeds current capacity! + // It is necessary to reallocate the buffer. + + // Check if this is the first call + if (!newIndexCapacity) + newIndexCapacity = 1; + + // Make capacity the next power of two + while (newIndexCapacity < indexCount) + newIndexCapacity <<= 1; + + } + else if (indexCount < newIndexCapacity>>1) + { + // Make capacity the previous power of two + while (indexCount < newIndexCapacity>>1) + newIndexCapacity >>= 1; + } + + if (newIndexCapacity != mIndexBufferCapacity) + { + mIndexBufferCapacity = newIndexCapacity; + // Create new index buffer + mRenderOp.indexData->indexBuffer = + HardwareBufferManager::getSingleton().createIndexBuffer( + HardwareIndexBuffer::IT_16BIT, + mIndexBufferCapacity, + HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // TODO: Custom HBU_? + } + + // Update index count in the render operation + mRenderOp.indexData->indexCount = indexCount; + } + } + //------------------------------------------------------------------------------------------------ + Real DynamicRenderable::getBoundingRadius(void) const + { + return Math::Sqrt(std::max(mBox.getMaximum().squaredLength(), mBox.getMinimum().squaredLength())); + } + //------------------------------------------------------------------------------------------------ + Real DynamicRenderable::getSquaredViewDepth(const Camera* cam) const + { + Vector3 vMin, vMax, vMid, vDist; + vMin = mBox.getMinimum(); + vMax = mBox.getMaximum(); + vMid = ((vMax - vMin) * 0.5) + vMin; + vDist = cam->getDerivedPosition() - vMid; + + return vDist.squaredLength(); + } + +/* + * ============================================================================================= + * BtOgre::DynamicLines + * ============================================================================================= + */ + + enum { + POSITION_BINDING, + TEXCOORD_BINDING + }; + //------------------------------------------------------------------------------------------------ + DynamicLines::DynamicLines(OperationType opType) + { + initialize(opType,false); + setMaterial("BaseWhiteNoLighting"); + mDirty = true; + } + //------------------------------------------------------------------------------------------------ + DynamicLines::~DynamicLines() + { + } + //------------------------------------------------------------------------------------------------ + void DynamicLines::setOperationType(OperationType opType) + { + mRenderOp.operationType = opType; + } + //------------------------------------------------------------------------------------------------ + RenderOperation::OperationType DynamicLines::getOperationType() const + { + return mRenderOp.operationType; + } + //------------------------------------------------------------------------------------------------ + void DynamicLines::addPoint(const Vector3 &p) + { + mPoints.push_back(p); + mDirty = true; + } + //------------------------------------------------------------------------------------------------ + void DynamicLines::addPoint(Real x, Real y, Real z) + { + mPoints.push_back(Vector3(x,y,z)); + mDirty = true; + } + //------------------------------------------------------------------------------------------------ + const Vector3& DynamicLines::getPoint(unsigned short index) const + { + assert(index < mPoints.size() && "Point index is out of bounds!!"); + return mPoints[index]; + } + //------------------------------------------------------------------------------------------------ + unsigned short DynamicLines::getNumPoints(void) const + { + return (unsigned short)mPoints.size(); + } + //------------------------------------------------------------------------------------------------ + void DynamicLines::setPoint(unsigned short index, const Vector3 &value) + { + assert(index < mPoints.size() && "Point index is out of bounds!!"); + + mPoints[index] = value; + mDirty = true; + } + //------------------------------------------------------------------------------------------------ + void DynamicLines::clear() + { + mPoints.clear(); + mDirty = true; + } + //------------------------------------------------------------------------------------------------ + void DynamicLines::update() + { + if (mDirty) fillHardwareBuffers(); + } + //------------------------------------------------------------------------------------------------ + void DynamicLines::createVertexDeclaration() + { + VertexDeclaration *decl = mRenderOp.vertexData->vertexDeclaration; + decl->addElement(POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION); + } + //------------------------------------------------------------------------------------------------ + void DynamicLines::fillHardwareBuffers() + { + int size = mPoints.size(); + + prepareHardwareBuffers(size,0); + + if (!size) { + mBox.setExtents(Vector3::ZERO,Vector3::ZERO); + mDirty=false; + return; + } + + Vector3 vaabMin = mPoints[0]; + Vector3 vaabMax = mPoints[0]; + + HardwareVertexBufferSharedPtr vbuf = + mRenderOp.vertexData->vertexBufferBinding->getBuffer(0); + + Real *prPos = static_cast(vbuf->lock(HardwareBuffer::HBL_DISCARD)); + { + for(int i = 0; i < size; i++) + { + *prPos++ = mPoints[i].x; + *prPos++ = mPoints[i].y; + *prPos++ = mPoints[i].z; + + if(mPoints[i].x < vaabMin.x) + vaabMin.x = mPoints[i].x; + if(mPoints[i].y < vaabMin.y) + vaabMin.y = mPoints[i].y; + if(mPoints[i].z < vaabMin.z) + vaabMin.z = mPoints[i].z; + + if(mPoints[i].x > vaabMax.x) + vaabMax.x = mPoints[i].x; + if(mPoints[i].y > vaabMax.y) + vaabMax.y = mPoints[i].y; + if(mPoints[i].z > vaabMax.z) + vaabMax.z = mPoints[i].z; + } + } + vbuf->unlock(); + + mBox.setExtents(vaabMin, vaabMax); + + mDirty = false; + } +} diff --git a/bullet/BtOgreExtras.h b/bullet/BtOgreExtras.h new file mode 100644 index 000000000..f95943377 --- /dev/null +++ b/bullet/BtOgreExtras.h @@ -0,0 +1,280 @@ +/* + * ===================================================================================== + * + * Filename: BtOgreExtras.h + * + * Description: Contains the Ogre Mesh to Bullet Shape converters. + * + * Version: 1.0 + * Created: 27/12/2008 01:45:56 PM + * + * Author: Nikhilesh (nikki) + * + * ===================================================================================== + */ + +#ifndef _BtOgreShapes_H_ +#define _BtOgreShapes_H_ + +#include "btBulletDynamicsCommon.h" +#include "OgreSimpleRenderable.h" +#include "OgreCamera.h" +#include "OgreHardwareBufferManager.h" +#include "OgreMaterialManager.h" +#include "OgreTechnique.h" +#include "OgrePass.h" + +#include "OgreLogManager.h" + +namespace BtOgre +{ + +typedef std::vector Vector3Array; + +//Converts from and to Bullet and Ogre stuff. Pretty self-explanatory. +class Convert +{ +public: + Convert() {}; + ~Convert() {}; + + static btQuaternion toBullet(const Ogre::Quaternion &q) + { + return btQuaternion(q.x, q.y, q.z, q.w); + } + static btVector3 toBullet(const Ogre::Vector3 &v) + { + return btVector3(v.x, v.y, v.z); + } + + static Ogre::Quaternion toOgre(const btQuaternion &q) + { + return Ogre::Quaternion(q.w(), q.x(), q.y(), q.z()); + } + static Ogre::Vector3 toOgre(const btVector3 &v) + { + return Ogre::Vector3(v.x(), v.y(), v.z()); + } +}; + +//From here on its debug-drawing stuff. ------------------------------------------------------------------ + +class DynamicRenderable : public Ogre::SimpleRenderable +{ +public: + /// Constructor + DynamicRenderable(); + /// Virtual destructor + virtual ~DynamicRenderable(); + + /** Initializes the dynamic renderable. + @remarks + This function should only be called once. It initializes the + render operation, and calls the abstract function + createVertexDeclaration(). + @param operationType The type of render operation to perform. + @param useIndices Specifies whether to use indices to determine the + vertices to use as input. */ + void initialize(Ogre::RenderOperation::OperationType operationType, + bool useIndices); + + /// Implementation of Ogre::SimpleRenderable + virtual Ogre::Real getBoundingRadius(void) const; + /// Implementation of Ogre::SimpleRenderable + virtual Ogre::Real getSquaredViewDepth(const Ogre::Camera* cam) const; + +protected: + /// Maximum capacity of the currently allocated vertex buffer. + size_t mVertexBufferCapacity; + /// Maximum capacity of the currently allocated index buffer. + size_t mIndexBufferCapacity; + + /** Creates the vertex declaration. + @remarks + Override and set mRenderOp.vertexData->vertexDeclaration here. + mRenderOp.vertexData will be created for you before this method + is called. */ + virtual void createVertexDeclaration() = 0; + + /** Prepares the hardware buffers for the requested vertex and index counts. + @remarks + This function must be called before locking the buffers in + fillHardwareBuffers(). It guarantees that the hardware buffers + are large enough to hold at least the requested number of + vertices and indices (if using indices). The buffers are + possibly reallocated to achieve this. + @par + The vertex and index count in the render operation are set to + the values of vertexCount and indexCount respectively. + @param vertexCount The number of vertices the buffer must hold. + + @param indexCount The number of indices the buffer must hold. This + parameter is ignored if not using indices. */ + void prepareHardwareBuffers(size_t vertexCount, size_t indexCount); + + /** Fills the hardware vertex and index buffers with data. + @remarks + This function must call prepareHardwareBuffers() before locking + the buffers to ensure the they are large enough for the data to + be written. Afterwards the vertex and index buffers (if using + indices) can be locked, and data can be written to them. */ + virtual void fillHardwareBuffers() = 0; +}; + +class DynamicLines : public DynamicRenderable +{ + typedef Ogre::Vector3 Vector3; + typedef Ogre::Quaternion Quaternion; + typedef Ogre::Camera Camera; + typedef Ogre::Real Real; + typedef Ogre::RenderOperation::OperationType OperationType; + +public: + /// Constructor - see setOperationType() for description of argument. + DynamicLines(OperationType opType=Ogre::RenderOperation::OT_LINE_STRIP); + virtual ~DynamicLines(); + + /// Add a point to the point list + void addPoint(const Ogre::Vector3 &p); + /// Add a point to the point list + void addPoint(Real x, Real y, Real z); + + /// Change the location of an existing point in the point list + void setPoint(unsigned short index, const Vector3 &value); + + /// Return the location of an existing point in the point list + const Vector3& getPoint(unsigned short index) const; + + /// Return the total number of points in the point list + unsigned short getNumPoints(void) const; + + /// Remove all points from the point list + void clear(); + + /// Call this to update the hardware buffer after making changes. + void update(); + + /** Set the type of operation to draw with. + * @param opType Can be one of + * - RenderOperation::OT_LINE_STRIP + * - RenderOperation::OT_LINE_LIST + * - RenderOperation::OT_POINT_LIST + * - RenderOperation::OT_TRIANGLE_LIST + * - RenderOperation::OT_TRIANGLE_STRIP + * - RenderOperation::OT_TRIANGLE_FAN + * The default is OT_LINE_STRIP. + */ + void setOperationType(OperationType opType); + OperationType getOperationType() const; + +protected: + /// Implementation DynamicRenderable, creates a simple vertex-only decl + virtual void createVertexDeclaration(); + /// Implementation DynamicRenderable, pushes point list out to hardware memory + virtual void fillHardwareBuffers(); + +private: + std::vector mPoints; + bool mDirty; +}; + +class DebugDrawer : public btIDebugDraw +{ +protected: + Ogre::SceneNode *mNode; + btDynamicsWorld *mWorld; + DynamicLines *mLineDrawer; + bool mDebugOn; + +public: + + DebugDrawer(Ogre::SceneNode *node, btDynamicsWorld *world) + : mNode(node), + mWorld(world), + mDebugOn(true) + { + mLineDrawer = new DynamicLines(Ogre::RenderOperation::OT_LINE_LIST); + mNode->attachObject(mLineDrawer); + + if (!Ogre::ResourceGroupManager::getSingleton().resourceGroupExists("BtOgre")) + Ogre::ResourceGroupManager::getSingleton().createResourceGroup("BtOgre"); + if (!Ogre::MaterialManager::getSingleton().resourceExists("BtOgre/DebugLines")) + { + Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create("BtOgre/DebugLines", "BtOgre"); + mat->setReceiveShadows(false); + mat->setSelfIllumination(1,1,1); + } + + mLineDrawer->setMaterial("BtOgre/DebugLines"); + } + + ~DebugDrawer() + { + Ogre::MaterialManager::getSingleton().remove("BtOgre/DebugLines"); + Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("BtOgre"); + delete mLineDrawer; + } + + void step() + { + if (mDebugOn) + { + mWorld->debugDrawWorld(); + mLineDrawer->update(); + mNode->needUpdate(); + mLineDrawer->clear(); + } + else + { + mLineDrawer->clear(); + mLineDrawer->update(); + mNode->needUpdate(); + } + } + + void drawLine(const btVector3& from,const btVector3& to,const btVector3& color) + { + mLineDrawer->addPoint(Convert::toOgre(from)); + mLineDrawer->addPoint(Convert::toOgre(to)); + } + + void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color) + { + mLineDrawer->addPoint(Convert::toOgre(PointOnB)); + mLineDrawer->addPoint(Convert::toOgre(PointOnB) + (Convert::toOgre(normalOnB) * distance * 20)); + } + + void reportErrorWarning(const char* warningString) + { + Ogre::LogManager::getSingleton().logMessage(warningString); + } + + void draw3dText(const btVector3& location,const char* textString) + { + } + + //0 for off, anything else for on. + void setDebugMode(int isOn) + { + mDebugOn = (isOn == 0) ? false : true; + + if (!mDebugOn) + mLineDrawer->clear(); + } + + //0 for off, anything else for on. + int getDebugMode() const + { + return mDebugOn; + } + +}; + +} + +#endif + + + + + diff --git a/bullet/BtOgrePG.h b/bullet/BtOgrePG.h new file mode 100644 index 000000000..b1d271540 --- /dev/null +++ b/bullet/BtOgrePG.h @@ -0,0 +1,81 @@ +/* + * ===================================================================================== + * + * Filename: BtOgrePG.h + * + * Description: The part of BtOgre that handles information transfer from Bullet to + * Ogre (like updating graphics object positions). + * + * Version: 1.0 + * Created: 27/12/2008 03:40:56 AM + * + * Author: Nikhilesh (nikki) + * + * ===================================================================================== + */ + +#ifndef _BtOgreGP_H_ +#define _BtOgreGP_H_ + +#include "btBulletDynamicsCommon.h" +#include "OgreSceneNode.h" +#include "BtOgreExtras.h" + +namespace BtOgre { + +//A MotionState is Bullet's way of informing you about updates to an object. +//Pass this MotionState to a btRigidBody to have your SceneNode updated automaticaly. +class RigidBodyState : public btMotionState +{ + protected: + btTransform mTransform; + btTransform mCenterOfMassOffset; + + Ogre::SceneNode *mNode; + + public: + RigidBodyState(Ogre::SceneNode *node, const btTransform &transform, const btTransform &offset = btTransform::getIdentity()) + : mTransform(transform), + mCenterOfMassOffset(offset), + mNode(node) + { + } + + RigidBodyState(Ogre::SceneNode *node) + : mTransform(((node != NULL) ? BtOgre::Convert::toBullet(node->getOrientation()) : btQuaternion(0,0,0,1)), + ((node != NULL) ? BtOgre::Convert::toBullet(node->getPosition()) : btVector3(0,0,0))), + mCenterOfMassOffset(btTransform::getIdentity()), + mNode(node) + { + } + + virtual void getWorldTransform(btTransform &ret) const + { + ret = mCenterOfMassOffset.inverse() * mTransform; + } + + virtual void setWorldTransform(const btTransform &in) + { + if (mNode == NULL) + return; + + mTransform = in; + btTransform transform = in * mCenterOfMassOffset; + + btQuaternion rot = transform.getRotation(); + btVector3 pos = transform.getOrigin(); + mNode->setOrientation(rot.w(), rot.x(), rot.y(), rot.z()); + mNode->setPosition(pos.x(), pos.y(), pos.z()); + } + + void setNode(Ogre::SceneNode *node) + { + mNode = node; + } +}; + +//Softbody-Ogre connection goes here! + +} + +#endif From e84a02546ed38e0070dd688fc54695b43a359fa1 Mon Sep 17 00:00:00 2001 From: gugus Date: Tue, 22 Feb 2011 14:04:30 +0100 Subject: [PATCH 28/56] add debug rendering --- bullet/BtOgreGP.h | 143 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 bullet/BtOgreGP.h diff --git a/bullet/BtOgreGP.h b/bullet/BtOgreGP.h new file mode 100644 index 000000000..1894a79b3 --- /dev/null +++ b/bullet/BtOgreGP.h @@ -0,0 +1,143 @@ +/* + * ===================================================================================== + * + * Filename: BtOgreGP.h + * + * Description: The part of BtOgre that handles information transfer from Ogre to + * Bullet (like mesh data for making trimeshes). + * + * Version: 1.0 + * Created: 27/12/2008 03:29:56 AM + * + * Author: Nikhilesh (nikki) + * + * ===================================================================================== + */ + +#ifndef _BtOgrePG_H_ +#define _BtOgrePG_H_ + +#include "btBulletDynamicsCommon.h" +#include "BtOgreExtras.h" +#include "Ogre.h" + +namespace BtOgre { + +typedef std::map BoneIndex; +typedef std::pair BoneKeyIndex; + +class VertexIndexToShape +{ +public: + VertexIndexToShape(const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); + ~VertexIndexToShape(); + + Ogre::Real getRadius(); + Ogre::Vector3 getSize(); + + + btSphereShape* createSphere(); + btBoxShape* createBox(); + btBvhTriangleMeshShape* createTrimesh(); + btCylinderShape* createCylinder(); + btConvexHullShape* createConvex(); + + const Ogre::Vector3* getVertices(); + unsigned int getVertexCount(); + const unsigned int* getIndices(); + unsigned int getIndexCount(); + +protected: + + void addStaticVertexData(const Ogre::VertexData *vertex_data); + + void addAnimatedVertexData(const Ogre::VertexData *vertex_data, + const Ogre::VertexData *blended_data, + const Ogre::Mesh::IndexMap *indexMap); + + void addIndexData(Ogre::IndexData *data, const unsigned int offset = 0); + + +protected: + Ogre::Vector3* mVertexBuffer; + unsigned int* mIndexBuffer; + unsigned int mVertexCount; + unsigned int mIndexCount; + + Ogre::Matrix4 mTransform; + + Ogre::Real mBoundRadius; + Ogre::Vector3 mBounds; + + BoneIndex *mBoneIndex; + + Ogre::Vector3 mScale; +}; + +//For static (non-animated) meshes. +class StaticMeshToShapeConverter : public VertexIndexToShape +{ +public: + + StaticMeshToShapeConverter(Ogre::Renderable *rend, const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); + StaticMeshToShapeConverter(Ogre::Entity *entity, const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); + StaticMeshToShapeConverter(); + + ~StaticMeshToShapeConverter(); + + void addEntity(Ogre::Entity *entity,const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); + + void addMesh(const Ogre::MeshPtr &mesh, const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); + + +protected: + + Ogre::Entity* mEntity; + Ogre::SceneNode* mNode; +}; + +//For animated meshes. +class AnimatedMeshToShapeConverter : public VertexIndexToShape +{ +public: + + AnimatedMeshToShapeConverter(Ogre::Entity *entity, const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); + AnimatedMeshToShapeConverter(); + ~AnimatedMeshToShapeConverter(); + + void addEntity(Ogre::Entity *entity,const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); + void addMesh(const Ogre::MeshPtr &mesh, const Ogre::Matrix4 &transform); + + btBoxShape* createAlignedBox(unsigned char bone, + const Ogre::Vector3 &bonePosition, + const Ogre::Quaternion &boneOrientation); + + btBoxShape* createOrientedBox(unsigned char bone, + const Ogre::Vector3 &bonePosition, + const Ogre::Quaternion &boneOrientation); + +protected: + + bool getBoneVertices(unsigned char bone, + unsigned int &vertex_count, + Ogre::Vector3* &vertices, + const Ogre::Vector3 &bonePosition); + + bool getOrientedBox(unsigned char bone, + const Ogre::Vector3 &bonePosition, + const Ogre::Quaternion &boneOrientation, + Ogre::Vector3 &extents, + Ogre::Vector3 *axis, + Ogre::Vector3 ¢er); + + + Ogre::Entity* mEntity; + Ogre::SceneNode* mNode; + + Ogre::Vector3 *mTransformedVerticesTemp; + size_t mTransformedVerticesTempSize; +}; + +} + +#endif \ No newline at end of file From ada4616fd3932ee6e8883d420108a203014573f3 Mon Sep 17 00:00:00 2001 From: gugus Date: Tue, 22 Feb 2011 20:53:02 +0100 Subject: [PATCH 29/56] add raycasting --- bullet/physic.cpp | 37 +++++++++++++++++++++++++++++++++---- bullet/physic.hpp | 25 +++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/bullet/physic.cpp b/bullet/physic.cpp index d5c504cfd..76dabce5d 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -31,7 +31,7 @@ namespace Physic transform.setIdentity(); // External capsule - externalGhostObject = new btPairCachingGhostObject(); + externalGhostObject = new PairCachingGhostObject(name); externalGhostObject->setWorldTransform( transform ); btScalar externalCapsuleHeight = 50; @@ -44,7 +44,7 @@ namespace Physic externalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); // Internal capsule - internalGhostObject = new btPairCachingGhostObject(); + internalGhostObject = new PairCachingGhostObject(name); internalGhostObject->setWorldTransform( transform ); //internalGhostObject->getBroadphaseHandle()->s btScalar internalCapsuleHeight = 20; @@ -196,13 +196,20 @@ namespace Physic //create the real body btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,shape->Shape); RigidBody* body = new RigidBody(CI,name); - + body->collide = shape->collide; return body; } void PhysicEngine::addRigidBody(RigidBody* body) { - dynamicsWorld->addRigidBody(body,COL_WORLD,COL_WORLD|COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL); + if(body->collide) + { + dynamicsWorld->addRigidBody(body,COL_WORLD,COL_WORLD|COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL); + } + else + { + dynamicsWorld->addRigidBody(body,COL_WORLD,COL_NOTHING); + } body->setActivationState(DISABLE_DEACTIVATION); RigidBodyMap[body->mName] = body; } @@ -272,4 +279,26 @@ namespace Physic void PhysicEngine::emptyEventLists(void) { } + + std::pair PhysicEngine::rayTest(btVector3& from,btVector3& to) + { + std::string name = ""; + float d = -1.; + btCollisionWorld::ClosestRayResultCallback resultCallback(from, to); + dynamicsWorld->rayTest(from, to, resultCallback); + + if (resultCallback.hasHit()) + { + if(resultCallback.m_collisionFilterGroup == COL_WORLD) + { + name = static_cast(resultCallback.m_collisionObject)->mName; + } + if(resultCallback.m_collisionFilterGroup == COL_ACTOR_EXTERNAL || resultCallback.m_collisionFilterGroup == COL_ACTOR_INTERNAL) + { + name = static_cast(resultCallback.m_collisionObject)->mName; + } + d = resultCallback.m_closestHitFraction; + } + return std::pair(name,d); + } }}; \ No newline at end of file diff --git a/bullet/physic.hpp b/bullet/physic.hpp index 5fdc03e7d..062e69e02 100644 --- a/bullet/physic.hpp +++ b/bullet/physic.hpp @@ -34,6 +34,19 @@ namespace Physic class CMotionState; struct PhysicEvent; + /** + *This is just used to be able to name objects. + */ + class PairCachingGhostObject : public btPairCachingGhostObject + { + public: + PairCachingGhostObject(std::string name) + :btPairCachingGhostObject(),mName(name) + { + } + std::string mName; + }; + /** *A physic Actor use a modifed KinematicCharacterController taken in the bullet forum. */ @@ -63,10 +76,10 @@ namespace Physic btKinematicCharacterController* mCharacter; - btPairCachingGhostObject* internalGhostObject; + PairCachingGhostObject* internalGhostObject; btCollisionShape* internalCollisionShape; - btPairCachingGhostObject* externalGhostObject; + PairCachingGhostObject* externalGhostObject; btCollisionShape* externalCollisionShape; std::string mName; @@ -82,6 +95,9 @@ namespace Physic public: RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name); std::string mName; + + //is this body used for raycasting only? + bool collide; }; /** @@ -161,6 +177,11 @@ namespace Physic */ void setDebugRenderingMode(int mode); + /** + *Return the closest object hit by a ray. If there are no objects, it will return ("",-1). + */ + std::pair rayTest(btVector3& from,btVector3& to); + //event list of non player object std::list NPEventList; From ab1fa41c240b6e8626ffa4bff1ac3479eda593fb Mon Sep 17 00:00:00 2001 From: gugus Date: Wed, 23 Feb 2011 12:28:46 +0100 Subject: [PATCH 30/56] fix camera bug --- ogre/mouselook.cpp | 70 +++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/ogre/mouselook.cpp b/ogre/mouselook.cpp index 84e6e0397..c74f5365c 100644 --- a/ogre/mouselook.cpp +++ b/ogre/mouselook.cpp @@ -2,6 +2,7 @@ #include #include +#include using namespace OIS; using namespace Ogre; @@ -9,29 +10,48 @@ using namespace OEngine::Render; void MouseLookEvent::event(Type type, int index, const void *p) { - if(type != EV_MouseMove || camera == NULL) return; - - MouseEvent *arg = (MouseEvent*)(p); - - float x = arg->state.X.rel * sensX; - float y = arg->state.Y.rel * sensY; - - camera->yaw(Degree(-x)); - - if(flipProt) - { - // The camera before pitching - Quaternion nopitch = camera->getOrientation(); - - camera->pitch(Degree(-y)); - - // Apply some failsafe measures against the camera flipping - // upside down. Is the camera close to pointing straight up or - // down? - if(camera->getUp()[1] <= 0.1) - // If so, undo the last pitch - camera->setOrientation(nopitch); - } - else - camera->pitch(Degree(-y)); + if(type != EV_MouseMove || camera == NULL) return; + + MouseEvent *arg = (MouseEvent*)(p); + + float x = arg->state.X.rel * sensX; + float y = arg->state.Y.rel * sensY; + + camera->getParentSceneNode()->getParentSceneNode()->yaw(Degree(-x)); + camera->getParentSceneNode()->pitch(Degree(-y)); + if(flipProt) + { + // The camera before pitching + /*Quaternion nopitch = camera->getParentSceneNode()->getOrientation(); + + camera->getParentSceneNode()->pitch(Degree(-y)); + + // Apply some failsafe measures against the camera flipping + // upside down. Is the camera close to pointing straight up or + // down? + if(Ogre::Vector3(camera->getParentSceneNode()->getOrientation()*Ogre::Vector3::UNIT_Y)[1] <= 0.1) + // If so, undo the last pitch + camera->getParentSceneNode()->setOrientation(nopitch);*/ + //camera->getU + + // Angle of rotation around the X-axis. + float pitchAngle = (2 * Ogre::Degree(Ogre::Math::ACos(camera->getParentSceneNode()->getOrientation().w)).valueDegrees()); + + // Just to determine the sign of the angle we pick up above, the + // value itself does not interest us. + float pitchAngleSign = camera->getParentSceneNode()->getOrientation().x; + + // Limit the pitch between -90 degress and +90 degrees, Quake3-style. + if (pitchAngle > 90.0f) + { + if (pitchAngleSign > 0) + // Set orientation to 90 degrees on X-axis. + camera->getParentSceneNode()->setOrientation(Ogre::Quaternion(Ogre::Math::Sqrt(0.5f), + Ogre::Math::Sqrt(0.5f), 0, 0)); + else if (pitchAngleSign < 0) + // Sets orientation to -90 degrees on X-axis. + camera->getParentSceneNode()->setOrientation(Ogre::Quaternion(Ogre::Math::Sqrt(0.5f), + -Ogre::Math::Sqrt(0.5f), 0, 0)); + } + } } From 6c1338821e6bf640a0d54f36effc943aa4d86c6a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 Feb 2011 16:34:43 +0100 Subject: [PATCH 31/56] de-Windonizing --- bullet/CMotionState.cpp | 4 ++-- bullet/CMotionState.h | 4 ++-- bullet/btKinematicCharacterController.h | 16 ++++++++-------- bullet/physic.cpp | 18 +++++++++--------- bullet/physic.hpp | 14 +++++++------- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/bullet/CMotionState.cpp b/bullet/CMotionState.cpp index 9cb662caa..3725fd77a 100644 --- a/bullet/CMotionState.cpp +++ b/bullet/CMotionState.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include //#include namespace OEngine { @@ -42,4 +42,4 @@ namespace Physic } } -}} \ No newline at end of file +}} diff --git a/bullet/CMotionState.h b/bullet/CMotionState.h index 9ccc35adb..3dfb3a05c 100644 --- a/bullet/CMotionState.h +++ b/bullet/CMotionState.h @@ -1,7 +1,7 @@ #ifndef OENGINE_CMOTIONSTATE_H #define OENGINE_CMOTIONSTATE_H -#include +#include #include namespace OEngine { @@ -49,4 +49,4 @@ namespace Physic }; }} -#endif \ No newline at end of file +#endif diff --git a/bullet/btKinematicCharacterController.h b/bullet/btKinematicCharacterController.h index 8f32b32e9..96720dd7d 100644 --- a/bullet/btKinematicCharacterController.h +++ b/bullet/btKinematicCharacterController.h @@ -4,8 +4,8 @@ Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com 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, +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. @@ -17,9 +17,9 @@ subject to the following restrictions: #define KINEMATIC_CHARACTER_CONTROLLER_H #include "LinearMath/btVector3.h" -#include "LinearMath\btQuickprof.h" +#include "LinearMath/btQuickprof.h" -#include "BulletDynamics\Character\btCharacterControllerInterface.h" +#include "BulletDynamics/Character/btCharacterControllerInterface.h" #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" @@ -46,7 +46,7 @@ public: private: btPairCachingGhostObject* externalGhostObject; // use this for querying collisions for sliding and move btPairCachingGhostObject* internalGhostObject; // and this for recoreving from penetrations - + btScalar m_verticalVelocity; btScalar m_verticalOffset; btScalar m_fallSpeed; @@ -100,15 +100,15 @@ public: btScalar recoveringFactor = btScalar( 0.2 ) ); ~btKinematicCharacterController (); - + ///btActionInterface interface virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTime ) { preStep( collisionWorld ); - playerStep( collisionWorld, deltaTime ); + playerStep( collisionWorld, deltaTime ); } - + ///btActionInterface interface void debugDraw( btIDebugDraw* debugDrawer ); diff --git a/bullet/physic.cpp b/bullet/physic.cpp index 76dabce5d..2375d19e7 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -1,7 +1,7 @@ #include "physic.hpp" #include #include -#include +#include //#include #include "CMotionState.h" #include "OgreRoot.h" @@ -18,7 +18,7 @@ namespace Physic enum collisiontypes { COL_NOTHING = 0, //setWalkDirection( mvt ); } - void PhysicActor::Rotate(btQuaternion& quat) + void PhysicActor::Rotate(const btQuaternion& quat) { externalGhostObject->getWorldTransform().setRotation( externalGhostObject->getWorldTransform().getRotation() * quat ); internalGhostObject->getWorldTransform().setRotation( internalGhostObject->getWorldTransform().getRotation() * quat ); } - void PhysicActor::setRotation(btQuaternion& quat) + void PhysicActor::setRotation(const btQuaternion& quat) { externalGhostObject->getWorldTransform().setRotation( quat ); internalGhostObject->getWorldTransform().setRotation( quat ); @@ -96,7 +96,7 @@ namespace Physic return internalGhostObject->getWorldTransform().getRotation(); } - void PhysicActor::setPosition(btVector3& pos) + void PhysicActor::setPosition(const btVector3& pos) { internalGhostObject->getWorldTransform().setOrigin(pos); externalGhostObject->getWorldTransform().setOrigin(pos); @@ -179,7 +179,7 @@ namespace Physic delete solver; delete collisionConfiguration; delete dispatcher; - delete broadphase; + delete broadphase; delete ShapeLoader; } @@ -232,7 +232,7 @@ namespace Physic RigidBodyMap[name] = NULL; } } - + RigidBody* PhysicEngine::getRigidBody(std::string name) { RigidBody* body = RigidBodyMap[name]; @@ -301,4 +301,4 @@ namespace Physic } return std::pair(name,d); } -}}; \ No newline at end of file +}}; diff --git a/bullet/physic.hpp b/bullet/physic.hpp index 062e69e02..bc3314374 100644 --- a/bullet/physic.hpp +++ b/bullet/physic.hpp @@ -1,7 +1,7 @@ #ifndef OENGINE_BULLET_PHYSIC_H #define OENGINE_BULLET_PHYSIC_H -#include +#include #include "BulletCollision/CollisionDispatch/btGhostObject.h" #include #include @@ -35,7 +35,7 @@ namespace Physic struct PhysicEvent; /** - *This is just used to be able to name objects. + *This is just used to be able to name objects. */ class PairCachingGhostObject : public btPairCachingGhostObject { @@ -62,17 +62,17 @@ namespace Physic *I think it's also needed to take time into account. A typical call should look like this: *setWalkDirection( mvt * orientation * dt) */ - void setWalkDirection(btVector3& mvt); + void setWalkDirection(const btVector3& mvt); - void Rotate(btQuaternion& quat); + void Rotate(const btQuaternion& quat); - void setRotation(btQuaternion& quat); + void setRotation(const btQuaternion& quat); btVector3 getPosition(void); btQuaternion getRotation(void); - void setPosition(btVector3& pos); + void setPosition(const btVector3& pos); btKinematicCharacterController* mCharacter; @@ -208,4 +208,4 @@ namespace Physic }} -#endif \ No newline at end of file +#endif From aa0100bc08b59b27a681e872f6318c404e21edd4 Mon Sep 17 00:00:00 2001 From: Jan-Peter Nilsson Date: Sun, 27 Feb 2011 00:44:52 +0100 Subject: [PATCH 32/56] Don't mix the enum type name in there --- bullet/physic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bullet/physic.cpp b/bullet/physic.cpp index 2375d19e7..d09d29926 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -57,7 +57,7 @@ namespace Physic internalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); mCharacter = new btKinematicCharacterController( externalGhostObject,internalGhostObject,btScalar( 0.4 ),1,0 ); - mCharacter->setUpAxis(btKinematicCharacterController::UpAxis::Z_AXIS); + mCharacter->setUpAxis(btKinematicCharacterController::Z_AXIS); } PhysicActor::~PhysicActor() From 21295664507cca03068f9c2e9878603e2245f5af Mon Sep 17 00:00:00 2001 From: gugus Date: Mon, 28 Feb 2011 19:43:11 +0100 Subject: [PATCH 33/56] fix coc bug --- bullet/physic.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bullet/physic.cpp b/bullet/physic.cpp index 76dabce5d..733216cc1 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -219,6 +219,13 @@ namespace Physic RigidBody* body = RigidBodyMap[name]; if(body != NULL) { + broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + std::map::iterator it = PhysicActorMap.begin(); + for(;it!=PhysicActorMap.end();it++) + { + it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + } dynamicsWorld->removeRigidBody(RigidBodyMap[name]); } } From 3f0b610f2c5331fbc01617f993b77ead7e5261e8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 7 Mar 2011 14:55:18 +0100 Subject: [PATCH 34/56] throw an exception instead of crashing (ray test bug) --- bullet/physic.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/bullet/physic.cpp b/bullet/physic.cpp index d09d29926..597441771 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -219,6 +219,13 @@ namespace Physic RigidBody* body = RigidBodyMap[name]; if(body != NULL) { + broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + std::map::iterator it = PhysicActorMap.begin(); + for(;it!=PhysicActorMap.end();it++) + { + it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + } dynamicsWorld->removeRigidBody(RigidBodyMap[name]); } } @@ -291,11 +298,11 @@ namespace Physic { if(resultCallback.m_collisionFilterGroup == COL_WORLD) { - name = static_cast(resultCallback.m_collisionObject)->mName; + name = dynamic_cast(*resultCallback.m_collisionObject).mName; } if(resultCallback.m_collisionFilterGroup == COL_ACTOR_EXTERNAL || resultCallback.m_collisionFilterGroup == COL_ACTOR_INTERNAL) { - name = static_cast(resultCallback.m_collisionObject)->mName; + name = dynamic_cast(*resultCallback.m_collisionObject).mName; } d = resultCallback.m_closestHitFraction; } From 79fba7e77ed81f0e814d603315b1b4e5a1f4f309 Mon Sep 17 00:00:00 2001 From: gugus Date: Wed, 9 Mar 2011 18:23:13 +0100 Subject: [PATCH 35/56] add gravity --- bullet/physic.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bullet/physic.cpp b/bullet/physic.cpp index 597441771..a8425857f 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -34,11 +34,11 @@ namespace Physic externalGhostObject = new PairCachingGhostObject(name); externalGhostObject->setWorldTransform( transform ); - btScalar externalCapsuleHeight = 50; - btScalar externalCapsuleWidth = 20; + btScalar externalCapsuleHeight = 90; + btScalar externalCapsuleWidth = 16; externalCollisionShape = new btCapsuleShapeZ( externalCapsuleWidth, externalCapsuleHeight ); - externalCollisionShape->setMargin( 1 ); + externalCollisionShape->setMargin( 0.05 ); externalGhostObject->setCollisionShape( externalCollisionShape ); externalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); @@ -47,16 +47,16 @@ namespace Physic internalGhostObject = new PairCachingGhostObject(name); internalGhostObject->setWorldTransform( transform ); //internalGhostObject->getBroadphaseHandle()->s - btScalar internalCapsuleHeight = 20; - btScalar internalCapsuleWidth = 5; + btScalar internalCapsuleHeight = 88; + btScalar internalCapsuleWidth = 15; internalCollisionShape = new btCapsuleShapeZ( internalCapsuleWidth, internalCapsuleHeight ); - internalCollisionShape->setMargin( 1 ); + internalCollisionShape->setMargin( 0.05 ); internalGhostObject->setCollisionShape( internalCollisionShape ); internalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); - mCharacter = new btKinematicCharacterController( externalGhostObject,internalGhostObject,btScalar( 0.4 ),1,0 ); + mCharacter = new btKinematicCharacterController( externalGhostObject,internalGhostObject,btScalar( 10 ),1,20,20,9.8,0.2 ); mCharacter->setUpAxis(btKinematicCharacterController::Z_AXIS); } From d872d09081a61345dbfcfc51f349c457a1b89a22 Mon Sep 17 00:00:00 2001 From: gugus Date: Thu, 17 Mar 2011 11:00:46 +0100 Subject: [PATCH 36/56] add no gravity, no collision and remove debug messages. --- bullet/btKinematicCharacterController.cpp | 24 ++++++++++++++++------- bullet/btKinematicCharacterController.h | 3 +++ bullet/physic.cpp | 20 ++++++++++++++++--- bullet/physic.hpp | 4 ++++ 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/bullet/btKinematicCharacterController.cpp b/bullet/btKinematicCharacterController.cpp index 8c81d5a42..e2bd63ebf 100644 --- a/bullet/btKinematicCharacterController.cpp +++ b/bullet/btKinematicCharacterController.cpp @@ -22,7 +22,6 @@ subject to the following restrictions: #include "LinearMath/btDefaultMotionState.h" #include "btKinematicCharacterController.h" -#include ///@todo Interact with dynamic objects, ///Ride kinematicly animated platforms properly ///Support ducking @@ -132,6 +131,8 @@ btKinematicCharacterController::btKinematicCharacterController( btPairCachingGho m_wasJumping = false; setMaxSlope( btRadians( 45.0 ) ); + + mCollision = true; } @@ -142,9 +143,10 @@ btKinematicCharacterController::~btKinematicCharacterController () bool btKinematicCharacterController::recoverFromPenetration( btCollisionWorld* collisionWorld ) { - //std::cout << "recover!!!!"; bool penetration = false; + if(!mCollision) return penetration; + collisionWorld->getDispatcher()->dispatchAllCollisionPairs( internalGhostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher() ); @@ -172,10 +174,6 @@ bool btKinematicCharacterController::recoverFromPenetration( btCollisionWorld* c for( int p = 0; p < manifold->getNumContacts(); p++ ) { const btManifoldPoint&pt = manifold->getContactPoint( p ); - if(manifold->getBody1() == externalGhostObject) std::cout << "external!!"; - if(manifold->getBody0() == externalGhostObject) std::cout << "external!!"; - if(manifold->getBody1() == internalGhostObject) std::cout << "internal!!"; - if(manifold->getBody0() == internalGhostObject) std::cout << "internal!!"; if( (manifold->getBody1() == externalGhostObject && manifold->getBody0() == internalGhostObject) ||(manifold->getBody0() == externalGhostObject && manifold->getBody1() == internalGhostObject) ) { @@ -194,7 +192,6 @@ bool btKinematicCharacterController::recoverFromPenetration( btCollisionWorld* c currentPosition += pt.m_normalWorldOnB * directionSign * dist * m_recoveringFactor; penetration = true; - std::cout << "recover!!!!"; } } } @@ -219,6 +216,13 @@ btVector3 btKinematicCharacterController::stepUp( btCollisionWorld* world, const { btVector3 targetPosition = currentPosition + getUpAxisDirections()[ m_upAxis ] * ( m_stepHeight + ( m_verticalOffset > btScalar( 0.0 ) ? m_verticalOffset : 0.0 ) ); + //if the no collisions mode is on, no need to go any further + if(!mCollision) + { + currentStepOffset = m_stepHeight; + return targetPosition; + } + // Retrieve the collision shape // btCollisionShape* collisionShape = externalGhostObject->getCollisionShape(); @@ -319,6 +323,9 @@ btVector3 btKinematicCharacterController::stepForwardAndStrafe( btCollisionWorld // btVector3 targetPosition = currentPosition + walkMove; + //if the no collisions mode is on, no need to go any further + if(!mCollision) return targetPosition; + // Retrieve the collision shape // btCollisionShape* collisionShape = externalGhostObject->getCollisionShape(); @@ -400,6 +407,9 @@ btVector3 btKinematicCharacterController::stepDown( btCollisionWorld* collisionW // btVector3 targetPosition = currentPosition - stepDrop; + //if the no collisions mode is on, no need to go any further + if(!mCollision) return targetPosition; + btTransform start; start.setIdentity(); start.setOrigin( currentPosition ); diff --git a/bullet/btKinematicCharacterController.h b/bullet/btKinematicCharacterController.h index 96720dd7d..e851e1cb8 100644 --- a/bullet/btKinematicCharacterController.h +++ b/bullet/btKinematicCharacterController.h @@ -159,6 +159,9 @@ public: } bool onGround() const; + + //if set to false, there will be no collision. + bool mCollision; }; #endif // KINEMATIC_CHARACTER_CONTROLLER_H diff --git a/bullet/physic.cpp b/bullet/physic.cpp index a8425857f..fe491f6c6 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -34,7 +34,7 @@ namespace Physic externalGhostObject = new PairCachingGhostObject(name); externalGhostObject->setWorldTransform( transform ); - btScalar externalCapsuleHeight = 90; + btScalar externalCapsuleHeight = 130; btScalar externalCapsuleWidth = 16; externalCollisionShape = new btCapsuleShapeZ( externalCapsuleWidth, externalCapsuleHeight ); @@ -47,7 +47,7 @@ namespace Physic internalGhostObject = new PairCachingGhostObject(name); internalGhostObject->setWorldTransform( transform ); //internalGhostObject->getBroadphaseHandle()->s - btScalar internalCapsuleHeight = 88; + btScalar internalCapsuleHeight = 120; btScalar internalCapsuleWidth = 15; internalCollisionShape = new btCapsuleShapeZ( internalCapsuleWidth, internalCapsuleHeight ); @@ -56,8 +56,12 @@ namespace Physic internalGhostObject->setCollisionShape( internalCollisionShape ); internalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); - mCharacter = new btKinematicCharacterController( externalGhostObject,internalGhostObject,btScalar( 10 ),1,20,20,9.8,0.2 ); + mCharacter = new btKinematicCharacterController( externalGhostObject,internalGhostObject,btScalar( 10 ),1,9.8,20,9.8,0.2 ); mCharacter->setUpAxis(btKinematicCharacterController::Z_AXIS); + mCharacter->setUseGhostSweepTest(false); + + mCharacter->mCollision = false; + setGravity(0); } PhysicActor::~PhysicActor() @@ -69,6 +73,16 @@ namespace Physic delete externalCollisionShape; } + void PhysicActor::setGravity(float gravity) + { + mCharacter->setGravity(gravity); + } + + void PhysicActor::enableCollisions(bool collision) + { + mCharacter->mCollision = collision; + } + void PhysicActor::setWalkDirection(const btVector3& mvt) { mCharacter->setWalkDirection( mvt ); diff --git a/bullet/physic.hpp b/bullet/physic.hpp index bc3314374..6115628fa 100644 --- a/bullet/physic.hpp +++ b/bullet/physic.hpp @@ -68,6 +68,10 @@ namespace Physic void setRotation(const btQuaternion& quat); + void setGravity(float gravity); + + void enableCollisions(bool collision); + btVector3 getPosition(void); btQuaternion getRotation(void); From 25b3cf935967beb5011419b6d3911fca05863743 Mon Sep 17 00:00:00 2001 From: gugus Date: Fri, 18 Mar 2011 13:24:47 +0100 Subject: [PATCH 37/56] OEngine doesn't rely anymore on OpenMW+ some change for the toggleCollisionMode function. --- bullet/BulletShapeLoader.cpp | 124 +++++++++++++++++++++++++++++++ bullet/BulletShapeLoader.h | 138 +++++++++++++++++++++++++++++++++++ bullet/physic.cpp | 29 +++++--- bullet/physic.hpp | 17 +++-- 4 files changed, 291 insertions(+), 17 deletions(-) create mode 100644 bullet/BulletShapeLoader.cpp create mode 100644 bullet/BulletShapeLoader.h diff --git a/bullet/BulletShapeLoader.cpp b/bullet/BulletShapeLoader.cpp new file mode 100644 index 000000000..927ec6a27 --- /dev/null +++ b/bullet/BulletShapeLoader.cpp @@ -0,0 +1,124 @@ +#include "BulletShapeLoader.h" + + + +BulletShape::BulletShape(Ogre::ResourceManager* creator, const Ogre::String &name, + Ogre::ResourceHandle handle, const Ogre::String &group, bool isManual, + Ogre::ManualResourceLoader *loader) : +Ogre::Resource(creator, name, handle, group, isManual, loader) +{ + /* If you were storing a pointer to an object, then you would set that pointer to NULL here. + */ + + /* For consistency with StringInterface, but we don't add any parameters here + That's because the Resource implementation of StringInterface is to + list all the options that need to be set before loading, of which + we have none as such. Full details can be set through scripts. + */ + Shape = NULL; + collide = true; + createParamDictionary("BulletShape"); +} + +BulletShape::~BulletShape() +{ +} + +// farm out to BulletShapeLoader +void BulletShape::loadImpl() +{ + mLoader->loadResource(this); +} + +void BulletShape::deleteShape(btCollisionShape* mShape) +{ + if(mShape!=NULL) + { + if(mShape->isCompound()) + { + btCompoundShape* ms = static_cast(Shape); + int a = ms->getNumChildShapes(); + for(int i=0; i getChildShape(i)); + } + } + delete mShape; + } + mShape = NULL; +} + +void BulletShape::unloadImpl() +{ + deleteShape(Shape); +} + +//TODO:change this? +size_t BulletShape::calculateSize() const +{ + return 1; +} + + + +//============================================================================================================= +template<> BulletShapeManager *Ogre::Singleton::ms_Singleton = 0; + +BulletShapeManager *BulletShapeManager::getSingletonPtr() +{ + return ms_Singleton; +} + +BulletShapeManager &BulletShapeManager::getSingleton() +{ + assert(ms_Singleton); + return(*ms_Singleton); +} + +BulletShapeManager::BulletShapeManager() +{ + mResourceType = "BulletShape"; + + // low, because it will likely reference other resources + mLoadOrder = 30.0f; + + // this is how we register the ResourceManager with OGRE + Ogre::ResourceGroupManager::getSingleton()._registerResourceManager(mResourceType, this); +} + +BulletShapeManager::~BulletShapeManager() +{ + // and this is how we unregister it + Ogre::ResourceGroupManager::getSingleton()._unregisterResourceManager(mResourceType); +} + +BulletShapePtr BulletShapeManager::load(const Ogre::String &name, const Ogre::String &group) +{ + BulletShapePtr textf = getByName(name); + + if (textf.isNull()) + textf = create(name, group); + + textf->load(); + return textf; +} + +Ogre::Resource *BulletShapeManager::createImpl(const Ogre::String &name, Ogre::ResourceHandle handle, + const Ogre::String &group, bool isManual, Ogre::ManualResourceLoader *loader, + const Ogre::NameValuePairList *createParams) +{ + BulletShape* res = new BulletShape(this, name, handle, group, isManual, loader); + //if(isManual) + //{ + //loader->loadResource(res); + //} + return res; +} + + +//==================================================================== +void BulletShapeLoader::loadResource(Ogre::Resource *resource) +{} + +void BulletShapeLoader::load(const std::string &name,const std::string &group) +{} \ No newline at end of file diff --git a/bullet/BulletShapeLoader.h b/bullet/BulletShapeLoader.h new file mode 100644 index 000000000..e28a7175e --- /dev/null +++ b/bullet/BulletShapeLoader.h @@ -0,0 +1,138 @@ +#ifndef _BULLET_SHAPE_LOADER_H_ +#define _BULLET_SHAPE_LOADER_H_ + +#include +#include +#include + +//For some reason, Ogre Singleton cannot be used in another namespace, that's why there is no namespace here. +//But the risk of name collision seems pretty low here. + +/** +*Define a new resource which describe a Shape usable by bullet.See BulletShapeManager for how to get/use them. +*/ +class BulletShape : public Ogre::Resource +{ + Ogre::String mString; + +protected: + void loadImpl(); + void unloadImpl(); + size_t calculateSize() const; + + void deleteShape(btCollisionShape* mShape); + +public: + + BulletShape(Ogre::ResourceManager *creator, const Ogre::String &name, + Ogre::ResourceHandle handle, const Ogre::String &group, bool isManual = false, + Ogre::ManualResourceLoader *loader = 0); + + virtual ~BulletShape(); + + btCollisionShape* Shape; + //this flag indicate if the shape is used for collision or if it's for raycasting only. + bool collide; +}; + +/** +* +*/ +class BulletShapePtr : public Ogre::SharedPtr +{ +public: + BulletShapePtr() : Ogre::SharedPtr() {} + explicit BulletShapePtr(BulletShape *rep) : Ogre::SharedPtr(rep) {} + BulletShapePtr(const BulletShapePtr &r) : Ogre::SharedPtr(r) {} + BulletShapePtr(const Ogre::ResourcePtr &r) : Ogre::SharedPtr() + { + if( r.isNull() ) + return; + // lock & copy other mutex pointer + OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME) + OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME) + pRep = static_cast(r.getPointer()); + pUseCount = r.useCountPointer(); + useFreeMethod = r.freeMethod(); + if (pUseCount) + { + ++(*pUseCount); + } + } + + /// Operator used to convert a ResourcePtr to a BulletShapePtr + BulletShapePtr& operator=(const Ogre::ResourcePtr& r) + { + if(pRep == static_cast(r.getPointer())) + return *this; + release(); + if( r.isNull() ) + return *this; // resource ptr is null, so the call to release above has done all we need to do. + // lock & copy other mutex pointer + OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME) + OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME) + pRep = static_cast(r.getPointer()); + pUseCount = r.useCountPointer(); + useFreeMethod = r.freeMethod(); + if (pUseCount) + { + ++(*pUseCount); + } + return *this; + } +}; + + + + +/** +*Hold any BulletShape that was created by the ManualBulletShapeLoader. +* +*To get a bulletShape, you must load it first. +*First, create a manualBulletShapeLoader. Then call ManualBulletShapeManager->load(). This create an "empty" resource. +*Then use BulletShapeManager->load(). This will fill the resource with the required info. +*To get the resource,use BulletShapeManager::getByName. +*When you use the resource no more, just use BulletShapeManager->unload(). It won't completly delete the resource, but it will +*"empty" it.This allow a better management of memory: when you are leaving a cell, just unload every useless shape. +* +*Alternatively, you can call BulletShape->load() in order to actually load the resource. +*When you are finished with it, just call BulletShape->unload(). +* +*IMO: prefere the first methode, i am not completly sure about the 2nd. +* +*Important Note: i have no idea of what happen if you try to load two time the same resource without unloading. +*It won't crash, but it might lead to memory leaks(I don't know how Ogre handle this). So don't do it! +*/ +class BulletShapeManager : public Ogre::ResourceManager, public Ogre::Singleton +{ +protected: + + // must implement this from ResourceManager's interface + Ogre::Resource *createImpl(const Ogre::String &name, Ogre::ResourceHandle handle, + const Ogre::String &group, bool isManual, Ogre::ManualResourceLoader *loader, + const Ogre::NameValuePairList *createParams); + +public: + + BulletShapeManager(); + virtual ~BulletShapeManager(); + + virtual BulletShapePtr load(const Ogre::String &name, const Ogre::String &group); + + static BulletShapeManager &getSingleton(); + static BulletShapeManager *getSingletonPtr(); +}; + +class BulletShapeLoader : public Ogre::ManualResourceLoader +{ +public: + + BulletShapeLoader(){}; + virtual ~BulletShapeLoader() {} + + virtual void loadResource(Ogre::Resource *resource); + + virtual void load(const std::string &name,const std::string &group); +}; + +#endif \ No newline at end of file diff --git a/bullet/physic.cpp b/bullet/physic.cpp index fe491f6c6..d0be072f3 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -83,6 +83,11 @@ namespace Physic mCharacter->mCollision = collision; } + bool PhysicActor::getCollisionMode() + { + return mCharacter->mCollision; + } + void PhysicActor::setWalkDirection(const btVector3& mvt) { mCharacter->setWalkDirection( mvt ); @@ -133,7 +138,7 @@ namespace Physic - PhysicEngine::PhysicEngine() + PhysicEngine::PhysicEngine(BulletShapeLoader* shapeLoader) { // Set up the collision configuration and dispatcher collisionConfiguration = new btDefaultCollisionConfiguration(); @@ -157,7 +162,7 @@ namespace Physic new BulletShapeManager(); } //TODO:singleton? - ShapeLoader = new ManualBulletShapeLoader(); + mShapeLoader = shapeLoader; isDebugCreated = false; } @@ -178,14 +183,14 @@ namespace Physic } } - void PhysicEngine::setDebugRenderingMode(int mode) - { - if(!isDebugCreated) - { - createDebugRendering(); - } - mDebugDrawer->setDebugMode(mode); - } + void PhysicEngine::setDebugRenderingMode(int mode) + { + if(!isDebugCreated) + { + createDebugRendering(); + } + mDebugDrawer->setDebugMode(mode); + } PhysicEngine::~PhysicEngine() { @@ -194,13 +199,13 @@ namespace Physic delete collisionConfiguration; delete dispatcher; delete broadphase; - delete ShapeLoader; + delete mShapeLoader; } RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name) { //get the shape from the .nif - ShapeLoader->load(mesh,"General"); + mShapeLoader->load(mesh,"General"); BulletShapeManager::getSingletonPtr()->load(mesh,"General"); BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(mesh,"General"); diff --git a/bullet/physic.hpp b/bullet/physic.hpp index 6115628fa..9178a5779 100644 --- a/bullet/physic.hpp +++ b/bullet/physic.hpp @@ -6,6 +6,7 @@ #include #include #include +#include "BulletShapeLoader.h" class btRigidBody; class btBroadphaseInterface; @@ -20,9 +21,6 @@ namespace BtOgre class DebugDrawer; } -class BulletShapeManager; -class ManualBulletShapeLoader; - namespace MWWorld { class World; @@ -72,6 +70,8 @@ namespace Physic void enableCollisions(bool collision); + bool getCollisionMode(); + btVector3 getPosition(void); btQuaternion getRotation(void); @@ -113,7 +113,14 @@ namespace Physic class PhysicEngine { public: - PhysicEngine(); + /** + *Note that the shapeLoader IS destroyed by the phyic Engine!! + */ + PhysicEngine(BulletShapeLoader* shapeLoader); + + /** + *It DOES destroy the shape loader! + */ ~PhysicEngine(); /** @@ -200,7 +207,7 @@ namespace Physic btDiscreteDynamicsWorld* dynamicsWorld; //the NIF file loader. - ManualBulletShapeLoader* ShapeLoader; + BulletShapeLoader* mShapeLoader; std::map RigidBodyMap; std::map PhysicActorMap; From 8f9b8749d4b9e8c8c1093258a619997d704c6f76 Mon Sep 17 00:00:00 2001 From: gugus Date: Sun, 20 Mar 2011 21:51:40 +0100 Subject: [PATCH 38/56] fix the fall bug when using ToggleCollision --- bullet/btKinematicCharacterController.cpp | 4 ++++ bullet/btKinematicCharacterController.h | 1 + bullet/physic.cpp | 6 ++++++ bullet/physic.hpp | 2 ++ 4 files changed, 13 insertions(+) diff --git a/bullet/btKinematicCharacterController.cpp b/bullet/btKinematicCharacterController.cpp index e2bd63ebf..d93034985 100644 --- a/bullet/btKinematicCharacterController.cpp +++ b/bullet/btKinematicCharacterController.cpp @@ -140,6 +140,10 @@ btKinematicCharacterController::~btKinematicCharacterController () { } +void btKinematicCharacterController::setVerticalVelocity(float z) +{ + m_verticalVelocity = z; +} bool btKinematicCharacterController::recoverFromPenetration( btCollisionWorld* collisionWorld ) { diff --git a/bullet/btKinematicCharacterController.h b/bullet/btKinematicCharacterController.h index e851e1cb8..d58e242ad 100644 --- a/bullet/btKinematicCharacterController.h +++ b/bullet/btKinematicCharacterController.h @@ -101,6 +101,7 @@ public: ~btKinematicCharacterController (); + void setVerticalVelocity(float z); ///btActionInterface interface virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTime ) diff --git a/bullet/physic.cpp b/bullet/physic.cpp index d0be072f3..742f99436 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -76,6 +76,7 @@ namespace Physic void PhysicActor::setGravity(float gravity) { mCharacter->setGravity(gravity); + //mCharacter-> } void PhysicActor::enableCollisions(bool collision) @@ -83,6 +84,11 @@ namespace Physic mCharacter->mCollision = collision; } + void PhysicActor::setVerticalVelocity(float z) + { + mCharacter->setVerticalVelocity(z); + } + bool PhysicActor::getCollisionMode() { return mCharacter->mCollision; diff --git a/bullet/physic.hpp b/bullet/physic.hpp index 9178a5779..0cf6abd4f 100644 --- a/bullet/physic.hpp +++ b/bullet/physic.hpp @@ -67,6 +67,8 @@ namespace Physic void setRotation(const btQuaternion& quat); void setGravity(float gravity); + + void setVerticalVelocity(float z); void enableCollisions(bool collision); From 1ce6405e2bf5388a05a5cc0a60d1c5fe3dcadbfb Mon Sep 17 00:00:00 2001 From: gugus Date: Tue, 22 Mar 2011 21:28:18 +0100 Subject: [PATCH 39/56] fix the raycasting bug --- bullet/physic.cpp | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/bullet/physic.cpp b/bullet/physic.cpp index 742f99436..254e3db7d 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -38,7 +38,7 @@ namespace Physic btScalar externalCapsuleWidth = 16; externalCollisionShape = new btCapsuleShapeZ( externalCapsuleWidth, externalCapsuleHeight ); - externalCollisionShape->setMargin( 0.05 ); + externalCollisionShape->setMargin( 0.1 ); externalGhostObject->setCollisionShape( externalCollisionShape ); externalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); @@ -51,12 +51,12 @@ namespace Physic btScalar internalCapsuleWidth = 15; internalCollisionShape = new btCapsuleShapeZ( internalCapsuleWidth, internalCapsuleHeight ); - internalCollisionShape->setMargin( 0.05 ); + internalCollisionShape->setMargin( 0.1 ); internalGhostObject->setCollisionShape( internalCollisionShape ); internalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); - mCharacter = new btKinematicCharacterController( externalGhostObject,internalGhostObject,btScalar( 10 ),1,9.8,20,9.8,0.2 ); + mCharacter = new btKinematicCharacterController( externalGhostObject,internalGhostObject,btScalar( 40 ),1,4,20,9.8,0.2 ); mCharacter->setUpAxis(btKinematicCharacterController::Z_AXIS); mCharacter->setUseGhostSweepTest(false); @@ -273,7 +273,7 @@ namespace Physic void PhysicEngine::stepSimulation(double deltaT) { - dynamicsWorld->stepSimulation(deltaT,1,1/30.); + dynamicsWorld->stepSimulation(deltaT,1,1/50.); if(isDebugCreated) { mDebugDrawer->step(); @@ -315,22 +315,33 @@ namespace Physic std::pair PhysicEngine::rayTest(btVector3& from,btVector3& to) { std::string name = ""; - float d = -1.; - btCollisionWorld::ClosestRayResultCallback resultCallback(from, to); - dynamicsWorld->rayTest(from, to, resultCallback); + float d = -1; - if (resultCallback.hasHit()) + float d1 = 10000.; + btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to); + resultCallback1.m_collisionFilterMask = COL_WORLD; + dynamicsWorld->rayTest(from, to, resultCallback1); + if (resultCallback1.hasHit()) { - if(resultCallback.m_collisionFilterGroup == COL_WORLD) - { - name = dynamic_cast(*resultCallback.m_collisionObject).mName; - } - if(resultCallback.m_collisionFilterGroup == COL_ACTOR_EXTERNAL || resultCallback.m_collisionFilterGroup == COL_ACTOR_INTERNAL) + name = static_cast(*resultCallback1.m_collisionObject).mName; + d1 = resultCallback1.m_closestHitFraction; + d = d1; + } + + btCollisionWorld::ClosestRayResultCallback resultCallback2(from, to); + resultCallback2.m_collisionFilterMask = COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL; + dynamicsWorld->rayTest(from, to, resultCallback2); + float d2 = 10000.; + if (resultCallback2.hasHit()) + { + d2 = resultCallback1.m_closestHitFraction; + if(d2<=d1) { - name = dynamic_cast(*resultCallback.m_collisionObject).mName; + name = static_cast(*resultCallback2.m_collisionObject).mName; + d = d2; } - d = resultCallback.m_closestHitFraction; } + return std::pair(name,d); } }}; From 1cada5032ec06e3dd6c0ff8ece49aa588667bd0f Mon Sep 17 00:00:00 2001 From: gugus Date: Wed, 23 Mar 2011 19:17:45 +0100 Subject: [PATCH 40/56] fix delete actor --- bullet/physic.cpp | 77 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/bullet/physic.cpp b/bullet/physic.cpp index 254e3db7d..070f31779 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -241,28 +241,37 @@ namespace Physic void PhysicEngine::removeRigidBody(std::string name) { - RigidBody* body = RigidBodyMap[name]; - if(body != NULL) - { - broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); - std::map::iterator it = PhysicActorMap.begin(); - for(;it!=PhysicActorMap.end();it++) + std::map::iterator it = RigidBodyMap.find(name); + if (it != RigidBodyMap.end() ) + { + RigidBody* body = it->second; + if(body != NULL) { - it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); - it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + std::map::iterator it = PhysicActorMap.begin(); + for(;it!=PhysicActorMap.end();it++) + { + it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + } + dynamicsWorld->removeRigidBody(RigidBodyMap[name]); } - dynamicsWorld->removeRigidBody(RigidBodyMap[name]); - } + } } void PhysicEngine::deleteRigidBody(std::string name) { - RigidBody* body = RigidBodyMap[name]; - if(body != NULL) - { - delete body; - RigidBodyMap[name] = NULL; - } + std::map::iterator it = RigidBodyMap.find(name); + if (it != RigidBodyMap.end() ) + { + RigidBody* body = it->second; + if(body != NULL) + { + delete body; + RigidBodyMap[name] = NULL; + RigidBodyMap.erase(it); + } + } } RigidBody* PhysicEngine::getRigidBody(std::string name) @@ -291,15 +300,33 @@ namespace Physic void PhysicEngine::removeCharacter(std::string name) { - PhysicActor* act = PhysicActorMap[name]; - if(act != NULL) - { - dynamicsWorld->removeCollisionObject(act->externalGhostObject); - dynamicsWorld->removeCollisionObject(act->internalGhostObject); - dynamicsWorld->removeAction(act->mCharacter); - delete act; - PhysicActorMap[name] = NULL; - } + //std::cout << "remove"; + std::map::iterator it = PhysicActorMap.find(name); + if (it != PhysicActorMap.end() ) + { + PhysicActor* act = it->second; + if(act != NULL) + { + /*broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->externalGhostObject->getBroadphaseHandle(),dispatcher); + broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher); + std::map::iterator it2 = PhysicActorMap.begin(); + for(;it2!=PhysicActorMap.end();it++) + { + it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->externalGhostObject->getBroadphaseHandle(),dispatcher); + it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->externalGhostObject->getBroadphaseHandle(),dispatcher); + it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher); + it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher); + }*/ + //act->externalGhostObject-> + dynamicsWorld->removeCollisionObject(act->externalGhostObject); + dynamicsWorld->removeCollisionObject(act->internalGhostObject); + dynamicsWorld->removeAction(act->mCharacter); + delete act; + PhysicActorMap[name] = NULL; + PhysicActorMap.erase(it); + } + } + //std::cout << "ok"; } PhysicActor* PhysicEngine::getCharacter(std::string name) From 32b475432f3e1c8d7275d17da0d692c173f30478 Mon Sep 17 00:00:00 2001 From: gugus Date: Wed, 23 Mar 2011 22:49:23 +0100 Subject: [PATCH 41/56] fix the bug when changing cell. --- bullet/physic.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/bullet/physic.cpp b/bullet/physic.cpp index 070f31779..986b57be5 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -247,13 +247,13 @@ namespace Physic RigidBody* body = it->second; if(body != NULL) { - broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); - std::map::iterator it = PhysicActorMap.begin(); - for(;it!=PhysicActorMap.end();it++) + // broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + /*std::map::iterator it2 = PhysicActorMap.begin(); + for(;it2!=PhysicActorMap.end();it++) { - it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); - it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); - } + it2->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + it2->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + }*/ dynamicsWorld->removeRigidBody(RigidBodyMap[name]); } } @@ -268,9 +268,8 @@ namespace Physic if(body != NULL) { delete body; - RigidBodyMap[name] = NULL; - RigidBodyMap.erase(it); } + RigidBodyMap.erase(it); } } @@ -322,9 +321,8 @@ namespace Physic dynamicsWorld->removeCollisionObject(act->internalGhostObject); dynamicsWorld->removeAction(act->mCharacter); delete act; - PhysicActorMap[name] = NULL; - PhysicActorMap.erase(it); } + PhysicActorMap.erase(it); } //std::cout << "ok"; } From c78e61c96ff5bdbb8e0deac4ef80f4064e58c837 Mon Sep 17 00:00:00 2001 From: Jan-Peter Nilsson Date: Sat, 2 Apr 2011 13:06:05 +0200 Subject: [PATCH 42/56] Initialize member variables in the same order they are defined to avoid compiler warning --- bullet/BtOgre.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bullet/BtOgre.cpp b/bullet/BtOgre.cpp index 82ed2cbc2..5dca915b6 100644 --- a/bullet/BtOgre.cpp +++ b/bullet/BtOgre.cpp @@ -379,10 +379,10 @@ namespace BtOgre { mIndexBuffer (0), mVertexCount (0), mIndexCount (0), - mBounds (Vector3(-1,-1,-1)), + mTransform (transform), mBoundRadius (-1), + mBounds (Vector3(-1,-1,-1)), mBoneIndex (0), - mTransform (transform), mScale(1) { } From 0f7d59b4fb742c6479d988f6fc4ec9cdb4330b53 Mon Sep 17 00:00:00 2001 From: Jan-Peter Nilsson Date: Sun, 3 Apr 2011 13:12:12 +0200 Subject: [PATCH 43/56] Whitespace changes only (including new mangle with whitespace changes as well) --- bullet/BtOgre.cpp | 2020 +++++++++++---------- bullet/BtOgreExtras.h | 184 +- bullet/BtOgreGP.h | 127 +- bullet/BtOgrePG.h | 12 +- bullet/BulletShapeLoader.cpp | 18 +- bullet/BulletShapeLoader.h | 8 +- bullet/CMotionState.cpp | 62 +- bullet/CMotionState.h | 80 +- bullet/btKinematicCharacterController.cpp | 752 ++++---- bullet/btKinematicCharacterController.h | 158 +- bullet/physic.cpp | 406 ++--- bullet/physic.hpp | 296 +-- mangle | 2 +- ogre/mouselook.cpp | 88 +- ogre/renderer.cpp | 2 +- 15 files changed, 2130 insertions(+), 2085 deletions(-) diff --git a/bullet/BtOgre.cpp b/bullet/BtOgre.cpp index 5dca915b6..618739083 100644 --- a/bullet/BtOgre.cpp +++ b/bullet/BtOgre.cpp @@ -27,365 +27,380 @@ namespace BtOgre { * ============================================================================================= */ - void VertexIndexToShape::addStaticVertexData(const VertexData *vertex_data) - { - if (!vertex_data) - return; - - const VertexData *data = vertex_data; - - const unsigned int prev_size = mVertexCount; - mVertexCount += (unsigned int)data->vertexCount; - - Ogre::Vector3* tmp_vert = new Ogre::Vector3[mVertexCount]; - if (mVertexBuffer) - { - memcpy(tmp_vert, mVertexBuffer, sizeof(Vector3) * prev_size); - delete[] mVertexBuffer; - } - mVertexBuffer = tmp_vert; - - // Get the positional buffer element - { - const Ogre::VertexElement* posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); - Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource()); - const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); - - unsigned char* vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); - float* pReal; - Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size]; - const unsigned int vertexCount = (unsigned int)data->vertexCount; - for(unsigned int j = 0; j < vertexCount; ++j) - { - posElem->baseVertexPointerToElement(vertex, &pReal); - vertex += vSize; - - curVertices->x = (*pReal++); - curVertices->y = (*pReal++); - curVertices->z = (*pReal++); - - *curVertices = mTransform * (*curVertices); - - curVertices++; - } - vbuf->unlock(); - } - } - //------------------------------------------------------------------------------------------------ - void VertexIndexToShape::addAnimatedVertexData(const Ogre::VertexData *vertex_data, - const Ogre::VertexData *blend_data, - const Ogre::Mesh::IndexMap *indexMap) - { - // Get the bone index element - assert(vertex_data); - - const VertexData *data = blend_data; - const unsigned int prev_size = mVertexCount; - mVertexCount += (unsigned int)data->vertexCount; - Ogre::Vector3* tmp_vert = new Ogre::Vector3[mVertexCount]; - if (mVertexBuffer) - { - memcpy(tmp_vert, mVertexBuffer, sizeof(Vector3) * prev_size); - delete[] mVertexBuffer; - } - mVertexBuffer = tmp_vert; - - // Get the positional buffer element - { - const Ogre::VertexElement* posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); - assert (posElem); - Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource()); - const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); - - unsigned char* vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); - float* pReal; - Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size]; - const unsigned int vertexCount = (unsigned int)data->vertexCount; - for(unsigned int j = 0; j < vertexCount; ++j) - { - posElem->baseVertexPointerToElement(vertex, &pReal); - vertex += vSize; - - curVertices->x = (*pReal++); - curVertices->y = (*pReal++); - curVertices->z = (*pReal++); - - *curVertices = mTransform * (*curVertices); - - curVertices++; - } - vbuf->unlock(); - } - { - const Ogre::VertexElement* bneElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_BLEND_INDICES); - assert (bneElem); - - Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(bneElem->getSource()); - const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); - unsigned char* vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); - - unsigned char* pBone; - - if (!mBoneIndex) - mBoneIndex = new BoneIndex(); - BoneIndex::iterator i; - - Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size]; - - const unsigned int vertexCount = (unsigned int)vertex_data->vertexCount; - for(unsigned int j = 0; j < vertexCount; ++j) - { - bneElem->baseVertexPointerToElement(vertex, &pBone); - vertex += vSize; - - const unsigned char currBone = (indexMap) ? (*indexMap)[*pBone] : *pBone; - i = mBoneIndex->find (currBone); - Vector3Array* l = 0; - if (i == mBoneIndex->end()) - { - l = new Vector3Array; - mBoneIndex->insert(BoneKeyIndex(currBone, l)); - } - else - { - l = i->second; - } - - l->push_back(*curVertices); - - curVertices++; - } - vbuf->unlock(); - } - } - //------------------------------------------------------------------------------------------------ - void VertexIndexToShape::addIndexData(IndexData *data, const unsigned int offset) - { - const unsigned int prev_size = mIndexCount; - mIndexCount += (unsigned int)data->indexCount; - - unsigned int* tmp_ind = new unsigned int[mIndexCount]; - if (mIndexBuffer) - { - memcpy (tmp_ind, mIndexBuffer, sizeof(unsigned int) * prev_size); - delete[] mIndexBuffer; - } - mIndexBuffer = tmp_ind; - - const unsigned int numTris = (unsigned int) data->indexCount / 3; - HardwareIndexBufferSharedPtr ibuf = data->indexBuffer; - const bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT); - unsigned int index_offset = prev_size; - - if (use32bitindexes) - { - const unsigned int* pInt = static_cast(ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); - for(unsigned int k = 0; k < numTris; ++k) - { - mIndexBuffer[index_offset ++] = offset + *pInt++; - mIndexBuffer[index_offset ++] = offset + *pInt++; - mIndexBuffer[index_offset ++] = offset + *pInt++; - } - ibuf->unlock(); - } - else - { - const unsigned short* pShort = static_cast(ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); - for(unsigned int k = 0; k < numTris; ++k) - { - mIndexBuffer[index_offset ++] = offset + static_cast (*pShort++); - mIndexBuffer[index_offset ++] = offset + static_cast (*pShort++); - mIndexBuffer[index_offset ++] = offset + static_cast (*pShort++); - } - ibuf->unlock(); - } - - } - //------------------------------------------------------------------------------------------------ - Real VertexIndexToShape::getRadius() - { - if (mBoundRadius == (-1)) - { - getSize(); - mBoundRadius = (std::max(mBounds.x,std::max(mBounds.y,mBounds.z)) * 0.5); - } - return mBoundRadius; - } - //------------------------------------------------------------------------------------------------ - Vector3 VertexIndexToShape::getSize() - { - const unsigned int vCount = getVertexCount(); - if (mBounds == Ogre::Vector3(-1,-1,-1) && vCount > 0) - { - - const Ogre::Vector3 * const v = getVertices(); - - Ogre::Vector3 vmin(v[0]); - Ogre::Vector3 vmax(v[0]); - - for(unsigned int j = 1; j < vCount; j++) - { - vmin.x = std::min(vmin.x, v[j].x); - vmin.y = std::min(vmin.y, v[j].y); - vmin.z = std::min(vmin.z, v[j].z); - - vmax.x = std::max(vmax.x, v[j].x); - vmax.y = std::max(vmax.y, v[j].y); - vmax.z = std::max(vmax.z, v[j].z); - } - - mBounds.x = vmax.x - vmin.x; - mBounds.y = vmax.y - vmin.y; - mBounds.z = vmax.z - vmin.z; - } - - return mBounds; - } - //------------------------------------------------------------------------------------------------ - const Ogre::Vector3* VertexIndexToShape::getVertices() - { - return mVertexBuffer; - } - //------------------------------------------------------------------------------------------------ - unsigned int VertexIndexToShape::getVertexCount() - { - return mVertexCount; - } - //------------------------------------------------------------------------------------------------ - const unsigned int* VertexIndexToShape::getIndices() - { - return mIndexBuffer; - } - //------------------------------------------------------------------------------------------------ - unsigned int VertexIndexToShape::getIndexCount() - { - return mIndexCount; - } - - //------------------------------------------------------------------------------------------------ - btSphereShape* VertexIndexToShape::createSphere() - { - const Ogre::Real rad = getRadius(); - assert((rad > 0.0) && - ("Sphere radius must be greater than zero")); - btSphereShape* shape = new btSphereShape(rad); - - shape->setLocalScaling(Convert::toBullet(mScale)); - - return shape; - } - //------------------------------------------------------------------------------------------------ - btBoxShape* VertexIndexToShape::createBox() - { - const Ogre::Vector3 sz = getSize(); - - assert((sz.x > 0.0) && (sz.y > 0.0) && (sz.y > 0.0) && - ("Size of box must be greater than zero on all axes")); - - btBoxShape* shape = new btBoxShape(Convert::toBullet(sz * 0.5)); - - shape->setLocalScaling(Convert::toBullet(mScale)); - - return shape; - } - //------------------------------------------------------------------------------------------------ - btCylinderShape* VertexIndexToShape::createCylinder() - { - const Ogre::Vector3 sz = getSize(); - - assert((sz.x > 0.0) && (sz.y > 0.0) && (sz.y > 0.0) && - ("Size of Cylinder must be greater than zero on all axes")); - - btCylinderShape* shape = new btCylinderShapeX(Convert::toBullet(sz * 0.5)); - - shape->setLocalScaling(Convert::toBullet(mScale)); - - return shape; - } - //------------------------------------------------------------------------------------------------ - btConvexHullShape* VertexIndexToShape::createConvex() - { - assert(mVertexCount && (mIndexCount >= 6) && - ("Mesh must have some vertices and at least 6 indices (2 triangles)")); - - return new btConvexHullShape((btScalar*) &mVertexBuffer[0].x, mVertexCount, sizeof(Vector3)); - } - //------------------------------------------------------------------------------------------------ - btBvhTriangleMeshShape* VertexIndexToShape::createTrimesh() - { - assert(mVertexCount && (mIndexCount >= 6) && - ("Mesh must have some vertices and at least 6 indices (2 triangles)")); - - unsigned int numFaces = mIndexCount / 3; - - btTriangleMesh *trimesh = new btTriangleMesh(); - unsigned int *indices = mIndexBuffer; - Vector3 *vertices = mVertexBuffer; - - btVector3 vertexPos[3]; - for (unsigned int n = 0; n < numFaces; ++n) - { - { - const Vector3 &vec = vertices[*indices]; - vertexPos[0][0] = vec.x; - vertexPos[0][1] = vec.y; - vertexPos[0][2] = vec.z; - } - { - const Vector3 &vec = vertices[*(indices + 1)]; - vertexPos[1][0] = vec.x; - vertexPos[1][1] = vec.y; - vertexPos[1][2] = vec.z; - } - { - const Vector3 &vec = vertices[*(indices + 2)]; - vertexPos[2][0] = vec.x; - vertexPos[2][1] = vec.y; - vertexPos[2][2] = vec.z; - } - - indices += 3; - - trimesh->addTriangle(vertexPos[0], vertexPos[1], vertexPos[2]); - } - - const bool useQuantizedAABB = true; - btBvhTriangleMeshShape *shape = new btBvhTriangleMeshShape(trimesh, useQuantizedAABB); - - shape->setLocalScaling(Convert::toBullet(mScale)); - - return shape; - } - //------------------------------------------------------------------------------------------------ - VertexIndexToShape::~VertexIndexToShape() - { - delete[] mVertexBuffer; - delete[] mIndexBuffer; - - if (mBoneIndex) - { - for(BoneIndex::iterator i = mBoneIndex->begin(); - i != mBoneIndex->end(); - ++i) - { - delete i->second; - } - delete mBoneIndex; - } - } - //------------------------------------------------------------------------------------------------ - VertexIndexToShape::VertexIndexToShape(const Matrix4 &transform) : - mVertexBuffer (0), - mIndexBuffer (0), - mVertexCount (0), - mIndexCount (0), - mTransform (transform), - mBoundRadius (-1), - mBounds (Vector3(-1,-1,-1)), - mBoneIndex (0), - mScale(1) - { - } + void VertexIndexToShape::addStaticVertexData(const VertexData *vertex_data) + { + if (!vertex_data) + return; + + const VertexData *data = vertex_data; + + const unsigned int prev_size = mVertexCount; + mVertexCount += (unsigned int)data->vertexCount; + + Ogre::Vector3* tmp_vert = new Ogre::Vector3[mVertexCount]; + if (mVertexBuffer) + { + memcpy(tmp_vert, mVertexBuffer, sizeof(Vector3) * prev_size); + delete[] mVertexBuffer; + } + mVertexBuffer = tmp_vert; + + // Get the positional buffer element + { + const Ogre::VertexElement* posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); + Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource()); + const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); + + unsigned char* vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); + float* pReal; + Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size]; + const unsigned int vertexCount = (unsigned int)data->vertexCount; + for(unsigned int j = 0; j < vertexCount; ++j) + { + posElem->baseVertexPointerToElement(vertex, &pReal); + vertex += vSize; + + curVertices->x = (*pReal++); + curVertices->y = (*pReal++); + curVertices->z = (*pReal++); + + *curVertices = mTransform * (*curVertices); + + curVertices++; + } + vbuf->unlock(); + } + } + + //------------------------------------------------------------------------------------------------ + void VertexIndexToShape::addAnimatedVertexData(const Ogre::VertexData *vertex_data, + const Ogre::VertexData *blend_data, + const Ogre::Mesh::IndexMap *indexMap) + { + // Get the bone index element + assert(vertex_data); + + const VertexData *data = blend_data; + const unsigned int prev_size = mVertexCount; + mVertexCount += (unsigned int)data->vertexCount; + Ogre::Vector3* tmp_vert = new Ogre::Vector3[mVertexCount]; + if (mVertexBuffer) + { + memcpy(tmp_vert, mVertexBuffer, sizeof(Vector3) * prev_size); + delete[] mVertexBuffer; + } + mVertexBuffer = tmp_vert; + + // Get the positional buffer element + { + const Ogre::VertexElement* posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); + assert (posElem); + Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource()); + const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); + + unsigned char* vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); + float* pReal; + Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size]; + const unsigned int vertexCount = (unsigned int)data->vertexCount; + for(unsigned int j = 0; j < vertexCount; ++j) + { + posElem->baseVertexPointerToElement(vertex, &pReal); + vertex += vSize; + + curVertices->x = (*pReal++); + curVertices->y = (*pReal++); + curVertices->z = (*pReal++); + + *curVertices = mTransform * (*curVertices); + + curVertices++; + } + vbuf->unlock(); + } + + { + const Ogre::VertexElement* bneElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_BLEND_INDICES); + assert (bneElem); + + Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(bneElem->getSource()); + const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); + unsigned char* vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); + + unsigned char* pBone; + + if (!mBoneIndex) + mBoneIndex = new BoneIndex(); + BoneIndex::iterator i; + + Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size]; + + const unsigned int vertexCount = (unsigned int)vertex_data->vertexCount; + for(unsigned int j = 0; j < vertexCount; ++j) + { + bneElem->baseVertexPointerToElement(vertex, &pBone); + vertex += vSize; + + const unsigned char currBone = (indexMap) ? (*indexMap)[*pBone] : *pBone; + i = mBoneIndex->find (currBone); + Vector3Array* l = 0; + if (i == mBoneIndex->end()) + { + l = new Vector3Array; + mBoneIndex->insert(BoneKeyIndex(currBone, l)); + } + else + { + l = i->second; + } + + l->push_back(*curVertices); + + curVertices++; + } + vbuf->unlock(); + } + } + + //------------------------------------------------------------------------------------------------ + void VertexIndexToShape::addIndexData(IndexData *data, const unsigned int offset) + { + const unsigned int prev_size = mIndexCount; + mIndexCount += (unsigned int)data->indexCount; + + unsigned int* tmp_ind = new unsigned int[mIndexCount]; + if (mIndexBuffer) + { + memcpy (tmp_ind, mIndexBuffer, sizeof(unsigned int) * prev_size); + delete[] mIndexBuffer; + } + mIndexBuffer = tmp_ind; + + const unsigned int numTris = (unsigned int) data->indexCount / 3; + HardwareIndexBufferSharedPtr ibuf = data->indexBuffer; + const bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT); + unsigned int index_offset = prev_size; + + if (use32bitindexes) + { + const unsigned int* pInt = static_cast(ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); + for(unsigned int k = 0; k < numTris; ++k) + { + mIndexBuffer[index_offset ++] = offset + *pInt++; + mIndexBuffer[index_offset ++] = offset + *pInt++; + mIndexBuffer[index_offset ++] = offset + *pInt++; + } + ibuf->unlock(); + } + else + { + const unsigned short* pShort = static_cast(ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); + for(unsigned int k = 0; k < numTris; ++k) + { + mIndexBuffer[index_offset ++] = offset + static_cast (*pShort++); + mIndexBuffer[index_offset ++] = offset + static_cast (*pShort++); + mIndexBuffer[index_offset ++] = offset + static_cast (*pShort++); + } + ibuf->unlock(); + } + + } + + //------------------------------------------------------------------------------------------------ + Real VertexIndexToShape::getRadius() + { + if (mBoundRadius == (-1)) + { + getSize(); + mBoundRadius = (std::max(mBounds.x,std::max(mBounds.y,mBounds.z)) * 0.5); + } + return mBoundRadius; + } + + //------------------------------------------------------------------------------------------------ + Vector3 VertexIndexToShape::getSize() + { + const unsigned int vCount = getVertexCount(); + if (mBounds == Ogre::Vector3(-1,-1,-1) && vCount > 0) + { + + const Ogre::Vector3 * const v = getVertices(); + + Ogre::Vector3 vmin(v[0]); + Ogre::Vector3 vmax(v[0]); + + for(unsigned int j = 1; j < vCount; j++) + { + vmin.x = std::min(vmin.x, v[j].x); + vmin.y = std::min(vmin.y, v[j].y); + vmin.z = std::min(vmin.z, v[j].z); + + vmax.x = std::max(vmax.x, v[j].x); + vmax.y = std::max(vmax.y, v[j].y); + vmax.z = std::max(vmax.z, v[j].z); + } + + mBounds.x = vmax.x - vmin.x; + mBounds.y = vmax.y - vmin.y; + mBounds.z = vmax.z - vmin.z; + } + + return mBounds; + } + + //------------------------------------------------------------------------------------------------ + const Ogre::Vector3* VertexIndexToShape::getVertices() + { + return mVertexBuffer; + } + + //------------------------------------------------------------------------------------------------ + unsigned int VertexIndexToShape::getVertexCount() + { + return mVertexCount; + } + + //------------------------------------------------------------------------------------------------ + const unsigned int* VertexIndexToShape::getIndices() + { + return mIndexBuffer; + } + + //------------------------------------------------------------------------------------------------ + unsigned int VertexIndexToShape::getIndexCount() + { + return mIndexCount; + } + + //------------------------------------------------------------------------------------------------ + btSphereShape* VertexIndexToShape::createSphere() + { + const Ogre::Real rad = getRadius(); + assert((rad > 0.0) && + ("Sphere radius must be greater than zero")); + btSphereShape* shape = new btSphereShape(rad); + + shape->setLocalScaling(Convert::toBullet(mScale)); + + return shape; + } + + //------------------------------------------------------------------------------------------------ + btBoxShape* VertexIndexToShape::createBox() + { + const Ogre::Vector3 sz = getSize(); + + assert((sz.x > 0.0) && (sz.y > 0.0) && (sz.y > 0.0) && + ("Size of box must be greater than zero on all axes")); + + btBoxShape* shape = new btBoxShape(Convert::toBullet(sz * 0.5)); + + shape->setLocalScaling(Convert::toBullet(mScale)); + + return shape; + } + + //------------------------------------------------------------------------------------------------ + btCylinderShape* VertexIndexToShape::createCylinder() + { + const Ogre::Vector3 sz = getSize(); + + assert((sz.x > 0.0) && (sz.y > 0.0) && (sz.y > 0.0) && + ("Size of Cylinder must be greater than zero on all axes")); + + btCylinderShape* shape = new btCylinderShapeX(Convert::toBullet(sz * 0.5)); + + shape->setLocalScaling(Convert::toBullet(mScale)); + + return shape; + } + + //------------------------------------------------------------------------------------------------ + btConvexHullShape* VertexIndexToShape::createConvex() + { + assert(mVertexCount && (mIndexCount >= 6) && + ("Mesh must have some vertices and at least 6 indices (2 triangles)")); + + return new btConvexHullShape((btScalar*) &mVertexBuffer[0].x, mVertexCount, sizeof(Vector3)); + } + + //------------------------------------------------------------------------------------------------ + btBvhTriangleMeshShape* VertexIndexToShape::createTrimesh() + { + assert(mVertexCount && (mIndexCount >= 6) && + ("Mesh must have some vertices and at least 6 indices (2 triangles)")); + + unsigned int numFaces = mIndexCount / 3; + + btTriangleMesh *trimesh = new btTriangleMesh(); + unsigned int *indices = mIndexBuffer; + Vector3 *vertices = mVertexBuffer; + + btVector3 vertexPos[3]; + for (unsigned int n = 0; n < numFaces; ++n) + { + { + const Vector3 &vec = vertices[*indices]; + vertexPos[0][0] = vec.x; + vertexPos[0][1] = vec.y; + vertexPos[0][2] = vec.z; + } + { + const Vector3 &vec = vertices[*(indices + 1)]; + vertexPos[1][0] = vec.x; + vertexPos[1][1] = vec.y; + vertexPos[1][2] = vec.z; + } + { + const Vector3 &vec = vertices[*(indices + 2)]; + vertexPos[2][0] = vec.x; + vertexPos[2][1] = vec.y; + vertexPos[2][2] = vec.z; + } + + indices += 3; + + trimesh->addTriangle(vertexPos[0], vertexPos[1], vertexPos[2]); + } + + const bool useQuantizedAABB = true; + btBvhTriangleMeshShape *shape = new btBvhTriangleMeshShape(trimesh, useQuantizedAABB); + + shape->setLocalScaling(Convert::toBullet(mScale)); + + return shape; + } + + //------------------------------------------------------------------------------------------------ + VertexIndexToShape::~VertexIndexToShape() + { + delete[] mVertexBuffer; + delete[] mIndexBuffer; + + if (mBoneIndex) + { + for(BoneIndex::iterator i = mBoneIndex->begin(); + i != mBoneIndex->end(); + ++i) + { + delete i->second; + } + delete mBoneIndex; + } + } + + //------------------------------------------------------------------------------------------------ + VertexIndexToShape::VertexIndexToShape(const Matrix4 &transform) : + mVertexBuffer (0), + mIndexBuffer (0), + mVertexCount (0), + mIndexCount (0), + mTransform (transform), + mBoundRadius (-1), + mBounds (Vector3(-1,-1,-1)), + mBoneIndex (0), + mScale(1) + { + } /* * ============================================================================================= @@ -393,107 +408,112 @@ namespace BtOgre { * ============================================================================================= */ - StaticMeshToShapeConverter::StaticMeshToShapeConverter() : - VertexIndexToShape(), - mEntity (0), - mNode (0) - { - } - //------------------------------------------------------------------------------------------------ - StaticMeshToShapeConverter::~StaticMeshToShapeConverter() - { - } - //------------------------------------------------------------------------------------------------ - StaticMeshToShapeConverter::StaticMeshToShapeConverter(Entity *entity, const Matrix4 &transform) : - VertexIndexToShape(transform), - mEntity (0), - mNode (0) - { - addEntity(entity, transform); - } - //------------------------------------------------------------------------------------------------ - StaticMeshToShapeConverter::StaticMeshToShapeConverter(Renderable *rend, const Matrix4 &transform) : - VertexIndexToShape(transform), - mEntity (0), - mNode (0) - { - RenderOperation op; - rend->getRenderOperation(op); - VertexIndexToShape::addStaticVertexData(op.vertexData); - if(op.useIndexes) - VertexIndexToShape::addIndexData(op.indexData); - - } - //------------------------------------------------------------------------------------------------ - void StaticMeshToShapeConverter::addEntity(Entity *entity,const Matrix4 &transform) - { - // Each entity added need to reset size and radius - // next time getRadius and getSize are asked, they're computed. - mBounds = Ogre::Vector3(-1,-1,-1); - mBoundRadius = -1; - - mEntity = entity; - mNode = (SceneNode*)(mEntity->getParentNode()); - mTransform = transform; - mScale = mNode->getScale(); - - if (mEntity->getMesh()->sharedVertexData) - { - VertexIndexToShape::addStaticVertexData (mEntity->getMesh()->sharedVertexData); - } - - for (unsigned int i = 0;i < mEntity->getNumSubEntities();++i) - { - SubMesh *sub_mesh = mEntity->getSubEntity(i)->getSubMesh(); - - if (!sub_mesh->useSharedVertices) - { - VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount); - VertexIndexToShape::addStaticVertexData (sub_mesh->vertexData); - } - else - { - VertexIndexToShape::addIndexData (sub_mesh->indexData); - } - - } - } - //------------------------------------------------------------------------------------------------ - void StaticMeshToShapeConverter::addMesh(const MeshPtr &mesh, const Matrix4 &transform) - { - // Each entity added need to reset size and radius - // next time getRadius and getSize are asked, they're computed. - mBounds = Ogre::Vector3(-1,-1,-1); - mBoundRadius = -1; - - //_entity = entity; - //_node = (SceneNode*)(_entity->getParentNode()); - mTransform = transform; - - if (mesh->hasSkeleton ()) - Ogre::LogManager::getSingleton().logMessage("MeshToShapeConverter::addMesh : Mesh " + mesh->getName () + " as skeleton but added to trimesh non animated"); - - if (mesh->sharedVertexData) - { - VertexIndexToShape::addStaticVertexData (mesh->sharedVertexData); - } - - for(unsigned int i = 0;i < mesh->getNumSubMeshes();++i) - { - SubMesh *sub_mesh = mesh->getSubMesh(i); - - if (!sub_mesh->useSharedVertices) - { - VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount); - VertexIndexToShape::addStaticVertexData (sub_mesh->vertexData); - } - else - { - VertexIndexToShape::addIndexData (sub_mesh->indexData); - } - - } - } + StaticMeshToShapeConverter::StaticMeshToShapeConverter() : + VertexIndexToShape(), + mEntity (0), + mNode (0) + { + } + + //------------------------------------------------------------------------------------------------ + StaticMeshToShapeConverter::~StaticMeshToShapeConverter() + { + } + + //------------------------------------------------------------------------------------------------ + StaticMeshToShapeConverter::StaticMeshToShapeConverter(Entity *entity, const Matrix4 &transform) : + VertexIndexToShape(transform), + mEntity (0), + mNode (0) + { + addEntity(entity, transform); + } + + //------------------------------------------------------------------------------------------------ + StaticMeshToShapeConverter::StaticMeshToShapeConverter(Renderable *rend, const Matrix4 &transform) : + VertexIndexToShape(transform), + mEntity (0), + mNode (0) + { + RenderOperation op; + rend->getRenderOperation(op); + VertexIndexToShape::addStaticVertexData(op.vertexData); + if(op.useIndexes) + VertexIndexToShape::addIndexData(op.indexData); + + } + + //------------------------------------------------------------------------------------------------ + void StaticMeshToShapeConverter::addEntity(Entity *entity,const Matrix4 &transform) + { + // Each entity added need to reset size and radius + // next time getRadius and getSize are asked, they're computed. + mBounds = Ogre::Vector3(-1,-1,-1); + mBoundRadius = -1; + + mEntity = entity; + mNode = (SceneNode*)(mEntity->getParentNode()); + mTransform = transform; + mScale = mNode->getScale(); + + if (mEntity->getMesh()->sharedVertexData) + { + VertexIndexToShape::addStaticVertexData (mEntity->getMesh()->sharedVertexData); + } + + for (unsigned int i = 0;i < mEntity->getNumSubEntities();++i) + { + SubMesh *sub_mesh = mEntity->getSubEntity(i)->getSubMesh(); + + if (!sub_mesh->useSharedVertices) + { + VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount); + VertexIndexToShape::addStaticVertexData (sub_mesh->vertexData); + } + else + { + VertexIndexToShape::addIndexData (sub_mesh->indexData); + } + + } + } + + //------------------------------------------------------------------------------------------------ + void StaticMeshToShapeConverter::addMesh(const MeshPtr &mesh, const Matrix4 &transform) + { + // Each entity added need to reset size and radius + // next time getRadius and getSize are asked, they're computed. + mBounds = Ogre::Vector3(-1,-1,-1); + mBoundRadius = -1; + + //_entity = entity; + //_node = (SceneNode*)(_entity->getParentNode()); + mTransform = transform; + + if (mesh->hasSkeleton ()) + Ogre::LogManager::getSingleton().logMessage("MeshToShapeConverter::addMesh : Mesh " + mesh->getName () + " as skeleton but added to trimesh non animated"); + + if (mesh->sharedVertexData) + { + VertexIndexToShape::addStaticVertexData (mesh->sharedVertexData); + } + + for(unsigned int i = 0;i < mesh->getNumSubMeshes();++i) + { + SubMesh *sub_mesh = mesh->getSubMesh(i); + + if (!sub_mesh->useSharedVertices) + { + VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount); + VertexIndexToShape::addStaticVertexData (sub_mesh->vertexData); + } + else + { + VertexIndexToShape::addIndexData (sub_mesh->indexData); + } + + } + } /* * ============================================================================================= @@ -501,284 +521,292 @@ namespace BtOgre { * ============================================================================================= */ - AnimatedMeshToShapeConverter::AnimatedMeshToShapeConverter(Entity *entity,const Matrix4 &transform) : - VertexIndexToShape(transform), - mEntity (0), - mNode (0), - mTransformedVerticesTemp(0), - mTransformedVerticesTempSize(0) - { - addEntity(entity, transform); - } - //------------------------------------------------------------------------------------------------ - AnimatedMeshToShapeConverter::AnimatedMeshToShapeConverter() : - VertexIndexToShape(), - mEntity (0), - mNode (0), - mTransformedVerticesTemp(0), - mTransformedVerticesTempSize(0) - { - } - //------------------------------------------------------------------------------------------------ - AnimatedMeshToShapeConverter::~AnimatedMeshToShapeConverter() - { - delete[] mTransformedVerticesTemp; - } - //------------------------------------------------------------------------------------------------ - void AnimatedMeshToShapeConverter::addEntity(Entity *entity,const Matrix4 &transform) - { - // Each entity added need to reset size and radius - // next time getRadius and getSize are asked, they're computed. - mBounds = Ogre::Vector3(-1,-1,-1); - mBoundRadius = -1; - - mEntity = entity; - mNode = (SceneNode*)(mEntity->getParentNode()); - mTransform = transform; - - assert (entity->getMesh()->hasSkeleton ()); - - mEntity->addSoftwareAnimationRequest(false); - mEntity->_updateAnimation(); - - if (mEntity->getMesh()->sharedVertexData) - { - VertexIndexToShape::addAnimatedVertexData (mEntity->getMesh()->sharedVertexData, - mEntity->_getSkelAnimVertexData(), - &mEntity->getMesh()->sharedBlendIndexToBoneIndexMap); - } - - for (unsigned int i = 0;i < mEntity->getNumSubEntities();++i) - { - SubMesh *sub_mesh = mEntity->getSubEntity(i)->getSubMesh(); - - if (!sub_mesh->useSharedVertices) - { - VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount); - - VertexIndexToShape::addAnimatedVertexData (sub_mesh->vertexData, - mEntity->getSubEntity(i)->_getSkelAnimVertexData(), - &sub_mesh->blendIndexToBoneIndexMap); - } - else - { - VertexIndexToShape::addIndexData (sub_mesh->indexData); - } - - } - - mEntity->removeSoftwareAnimationRequest(false); - } - //------------------------------------------------------------------------------------------------ - void AnimatedMeshToShapeConverter::addMesh(const MeshPtr &mesh, const Matrix4 &transform) - { - // Each entity added need to reset size and radius - // next time getRadius and getSize are asked, they're computed. - mBounds = Ogre::Vector3(-1,-1,-1); - mBoundRadius = -1; - - //_entity = entity; - //_node = (SceneNode*)(_entity->getParentNode()); - mTransform = transform; - - assert (mesh->hasSkeleton ()); - - if (mesh->sharedVertexData) - { - VertexIndexToShape::addAnimatedVertexData (mesh->sharedVertexData, - 0, - &mesh->sharedBlendIndexToBoneIndexMap); - } - - for(unsigned int i = 0;i < mesh->getNumSubMeshes();++i) - { - SubMesh *sub_mesh = mesh->getSubMesh(i); - - if (!sub_mesh->useSharedVertices) - { - VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount); - - VertexIndexToShape::addAnimatedVertexData (sub_mesh->vertexData, - 0, - &sub_mesh->blendIndexToBoneIndexMap); - } - else - { - VertexIndexToShape::addIndexData (sub_mesh->indexData); - } - - } - } - //------------------------------------------------------------------------------------------------ - bool AnimatedMeshToShapeConverter::getBoneVertices(unsigned char bone, - unsigned int &vertex_count, - Ogre::Vector3* &vertices, - const Vector3 &bonePosition) - { - BoneIndex::iterator i = mBoneIndex->find(bone); - - if (i == mBoneIndex->end()) - return false; - - if (i->second->empty()) - return false; - - vertex_count = (unsigned int) i->second->size() + 1; - if (vertex_count > mTransformedVerticesTempSize) - { - if (mTransformedVerticesTemp) - delete[] mTransformedVerticesTemp; - - mTransformedVerticesTemp = new Ogre::Vector3[vertex_count]; - - } - - vertices = mTransformedVerticesTemp; - vertices[0] = bonePosition; - //mEntity->_getParentNodeFullTransform() * - // mEntity->getSkeleton()->getBone(bone)->_getDerivedPosition(); - - //mEntity->getSkeleton()->getBone(bone)->_getDerivedOrientation() - unsigned int currBoneVertex = 1; - Vector3Array::iterator j = i->second->begin(); - while(j != i->second->end()) - { - vertices[currBoneVertex] = (*j); - ++j; - ++currBoneVertex; - } - return true; - } - //------------------------------------------------------------------------------------------------ - btBoxShape* AnimatedMeshToShapeConverter::createAlignedBox(unsigned char bone, - const Vector3 &bonePosition, - const Quaternion &boneOrientation) - { - unsigned int vertex_count; - Vector3* vertices; - - if (!getBoneVertices(bone, vertex_count, vertices, bonePosition)) - return 0; - - Vector3 min_vec(vertices[0]); - Vector3 max_vec(vertices[0]); - - for(unsigned int j = 1; j < vertex_count ;j++) - { - min_vec.x = std::min(min_vec.x,vertices[j].x); - min_vec.y = std::min(min_vec.y,vertices[j].y); - min_vec.z = std::min(min_vec.z,vertices[j].z); - - max_vec.x = std::max(max_vec.x,vertices[j].x); - max_vec.y = std::max(max_vec.y,vertices[j].y); - max_vec.z = std::max(max_vec.z,vertices[j].z); - } - const Ogre::Vector3 maxMinusMin(max_vec - min_vec); - btBoxShape* box = new btBoxShape(Convert::toBullet(maxMinusMin)); - - /*const Ogre::Vector3 pos - (min_vec.x + (maxMinusMin.x * 0.5), - min_vec.y + (maxMinusMin.y * 0.5), - min_vec.z + (maxMinusMin.z * 0.5));*/ - - //box->setPosition(pos); - - return box; - } - //------------------------------------------------------------------------------------------------ - bool AnimatedMeshToShapeConverter::getOrientedBox(unsigned char bone, - const Vector3 &bonePosition, - const Quaternion &boneOrientation, - Vector3 &box_afExtent, - Vector3 *box_akAxis, - Vector3 &box_kCenter) - { - unsigned int vertex_count; - Vector3* vertices; - - if (!getBoneVertices(bone, vertex_count, vertices, bonePosition)) - return false; - - box_kCenter = Vector3::ZERO; - - { - for(unsigned int c = 0 ;c < vertex_count;c++) - { - box_kCenter += vertices[c]; - } - const Ogre::Real invVertexCount = 1.0 / vertex_count; - box_kCenter *= invVertexCount; - } - Quaternion orient = boneOrientation; - orient.ToAxes(box_akAxis); - - // Let C be the box center and let U0, U1, and U2 be the box axes. Each - // input point is of the form X = C + y0*U0 + y1*U1 + y2*U2. The - // following code computes min(y0), max(y0), min(y1), max(y1), min(y2), - // and max(y2). The box center is then adjusted to be - // C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1 + - // 0.5*(min(y2)+max(y2))*U2 - - Ogre::Vector3 kDiff (vertices[1] - box_kCenter); - Ogre::Real fY0Min = kDiff.dotProduct(box_akAxis[0]), fY0Max = fY0Min; - Ogre::Real fY1Min = kDiff.dotProduct(box_akAxis[1]), fY1Max = fY1Min; - Ogre::Real fY2Min = kDiff.dotProduct(box_akAxis[2]), fY2Max = fY2Min; - - for (unsigned int i = 2; i < vertex_count; i++) - { - kDiff = vertices[i] - box_kCenter; - - const Ogre::Real fY0 = kDiff.dotProduct(box_akAxis[0]); - if ( fY0 < fY0Min ) - fY0Min = fY0; - else if ( fY0 > fY0Max ) - fY0Max = fY0; - - const Ogre::Real fY1 = kDiff.dotProduct(box_akAxis[1]); - if ( fY1 < fY1Min ) - fY1Min = fY1; - else if ( fY1 > fY1Max ) - fY1Max = fY1; - - const Ogre::Real fY2 = kDiff.dotProduct(box_akAxis[2]); - if ( fY2 < fY2Min ) - fY2Min = fY2; - else if ( fY2 > fY2Max ) - fY2Max = fY2; - } - - box_afExtent.x = ((Real)0.5)*(fY0Max - fY0Min); - box_afExtent.y = ((Real)0.5)*(fY1Max - fY1Min); - box_afExtent.z = ((Real)0.5)*(fY2Max - fY2Min); - - box_kCenter += (0.5*(fY0Max+fY0Min))*box_akAxis[0] + - (0.5*(fY1Max+fY1Min))*box_akAxis[1] + - (0.5*(fY2Max+fY2Min))*box_akAxis[2]; - - box_afExtent *= 2.0; - - return true; - } - //------------------------------------------------------------------------------------------------ - btBoxShape *AnimatedMeshToShapeConverter::createOrientedBox(unsigned char bone, - const Vector3 &bonePosition, - const Quaternion &boneOrientation) - { - Ogre::Vector3 box_akAxis[3]; - Ogre::Vector3 box_afExtent; - Ogre::Vector3 box_afCenter; - - if (!getOrientedBox(bone, bonePosition, boneOrientation, - box_afExtent, - box_akAxis, - box_afCenter)) - return 0; - - btBoxShape *geom = new btBoxShape(Convert::toBullet(box_afExtent)); - //geom->setOrientation(Quaternion(box_akAxis[0],box_akAxis[1],box_akAxis[2])); - //geom->setPosition(box_afCenter); - return geom; - } + AnimatedMeshToShapeConverter::AnimatedMeshToShapeConverter(Entity *entity,const Matrix4 &transform) : + VertexIndexToShape(transform), + mEntity (0), + mNode (0), + mTransformedVerticesTemp(0), + mTransformedVerticesTempSize(0) + { + addEntity(entity, transform); + } + + //------------------------------------------------------------------------------------------------ + AnimatedMeshToShapeConverter::AnimatedMeshToShapeConverter() : + VertexIndexToShape(), + mEntity (0), + mNode (0), + mTransformedVerticesTemp(0), + mTransformedVerticesTempSize(0) + { + } + + //------------------------------------------------------------------------------------------------ + AnimatedMeshToShapeConverter::~AnimatedMeshToShapeConverter() + { + delete[] mTransformedVerticesTemp; + } + + //------------------------------------------------------------------------------------------------ + void AnimatedMeshToShapeConverter::addEntity(Entity *entity,const Matrix4 &transform) + { + // Each entity added need to reset size and radius + // next time getRadius and getSize are asked, they're computed. + mBounds = Ogre::Vector3(-1,-1,-1); + mBoundRadius = -1; + + mEntity = entity; + mNode = (SceneNode*)(mEntity->getParentNode()); + mTransform = transform; + + assert (entity->getMesh()->hasSkeleton ()); + + mEntity->addSoftwareAnimationRequest(false); + mEntity->_updateAnimation(); + + if (mEntity->getMesh()->sharedVertexData) + { + VertexIndexToShape::addAnimatedVertexData (mEntity->getMesh()->sharedVertexData, + mEntity->_getSkelAnimVertexData(), + &mEntity->getMesh()->sharedBlendIndexToBoneIndexMap); + } + + for (unsigned int i = 0;i < mEntity->getNumSubEntities();++i) + { + SubMesh *sub_mesh = mEntity->getSubEntity(i)->getSubMesh(); + + if (!sub_mesh->useSharedVertices) + { + VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount); + + VertexIndexToShape::addAnimatedVertexData (sub_mesh->vertexData, + mEntity->getSubEntity(i)->_getSkelAnimVertexData(), + &sub_mesh->blendIndexToBoneIndexMap); + } + else + { + VertexIndexToShape::addIndexData (sub_mesh->indexData); + } + + } + + mEntity->removeSoftwareAnimationRequest(false); + } + + //------------------------------------------------------------------------------------------------ + void AnimatedMeshToShapeConverter::addMesh(const MeshPtr &mesh, const Matrix4 &transform) + { + // Each entity added need to reset size and radius + // next time getRadius and getSize are asked, they're computed. + mBounds = Ogre::Vector3(-1,-1,-1); + mBoundRadius = -1; + + //_entity = entity; + //_node = (SceneNode*)(_entity->getParentNode()); + mTransform = transform; + + assert (mesh->hasSkeleton ()); + + if (mesh->sharedVertexData) + { + VertexIndexToShape::addAnimatedVertexData (mesh->sharedVertexData, + 0, + &mesh->sharedBlendIndexToBoneIndexMap); + } + + for(unsigned int i = 0;i < mesh->getNumSubMeshes();++i) + { + SubMesh *sub_mesh = mesh->getSubMesh(i); + + if (!sub_mesh->useSharedVertices) + { + VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount); + + VertexIndexToShape::addAnimatedVertexData (sub_mesh->vertexData, + 0, + &sub_mesh->blendIndexToBoneIndexMap); + } + else + { + VertexIndexToShape::addIndexData (sub_mesh->indexData); + } + + } + } + + //------------------------------------------------------------------------------------------------ + bool AnimatedMeshToShapeConverter::getBoneVertices(unsigned char bone, + unsigned int &vertex_count, + Ogre::Vector3* &vertices, + const Vector3 &bonePosition) + { + BoneIndex::iterator i = mBoneIndex->find(bone); + + if (i == mBoneIndex->end()) + return false; + + if (i->second->empty()) + return false; + + vertex_count = (unsigned int) i->second->size() + 1; + if (vertex_count > mTransformedVerticesTempSize) + { + if (mTransformedVerticesTemp) + delete[] mTransformedVerticesTemp; + + mTransformedVerticesTemp = new Ogre::Vector3[vertex_count]; + + } + + vertices = mTransformedVerticesTemp; + vertices[0] = bonePosition; + //mEntity->_getParentNodeFullTransform() * + //mEntity->getSkeleton()->getBone(bone)->_getDerivedPosition(); + + //mEntity->getSkeleton()->getBone(bone)->_getDerivedOrientation() + unsigned int currBoneVertex = 1; + Vector3Array::iterator j = i->second->begin(); + while(j != i->second->end()) + { + vertices[currBoneVertex] = (*j); + ++j; + ++currBoneVertex; + } + return true; + } + + //------------------------------------------------------------------------------------------------ + btBoxShape* AnimatedMeshToShapeConverter::createAlignedBox(unsigned char bone, + const Vector3 &bonePosition, + const Quaternion &boneOrientation) + { + unsigned int vertex_count; + Vector3* vertices; + + if (!getBoneVertices(bone, vertex_count, vertices, bonePosition)) + return 0; + + Vector3 min_vec(vertices[0]); + Vector3 max_vec(vertices[0]); + + for(unsigned int j = 1; j < vertex_count ;j++) + { + min_vec.x = std::min(min_vec.x,vertices[j].x); + min_vec.y = std::min(min_vec.y,vertices[j].y); + min_vec.z = std::min(min_vec.z,vertices[j].z); + + max_vec.x = std::max(max_vec.x,vertices[j].x); + max_vec.y = std::max(max_vec.y,vertices[j].y); + max_vec.z = std::max(max_vec.z,vertices[j].z); + } + const Ogre::Vector3 maxMinusMin(max_vec - min_vec); + btBoxShape* box = new btBoxShape(Convert::toBullet(maxMinusMin)); + + /*const Ogre::Vector3 pos + (min_vec.x + (maxMinusMin.x * 0.5), + min_vec.y + (maxMinusMin.y * 0.5), + min_vec.z + (maxMinusMin.z * 0.5));*/ + + //box->setPosition(pos); + + return box; + } + + //------------------------------------------------------------------------------------------------ + bool AnimatedMeshToShapeConverter::getOrientedBox(unsigned char bone, + const Vector3 &bonePosition, + const Quaternion &boneOrientation, + Vector3 &box_afExtent, + Vector3 *box_akAxis, + Vector3 &box_kCenter) + { + unsigned int vertex_count; + Vector3* vertices; + + if (!getBoneVertices(bone, vertex_count, vertices, bonePosition)) + return false; + + box_kCenter = Vector3::ZERO; + + { + for(unsigned int c = 0 ;c < vertex_count;c++) + { + box_kCenter += vertices[c]; + } + const Ogre::Real invVertexCount = 1.0 / vertex_count; + box_kCenter *= invVertexCount; + } + Quaternion orient = boneOrientation; + orient.ToAxes(box_akAxis); + + // Let C be the box center and let U0, U1, and U2 be the box axes. Each + // input point is of the form X = C + y0*U0 + y1*U1 + y2*U2. The + // following code computes min(y0), max(y0), min(y1), max(y1), min(y2), + // and max(y2). The box center is then adjusted to be + // C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1 + + // 0.5*(min(y2)+max(y2))*U2 + + Ogre::Vector3 kDiff (vertices[1] - box_kCenter); + Ogre::Real fY0Min = kDiff.dotProduct(box_akAxis[0]), fY0Max = fY0Min; + Ogre::Real fY1Min = kDiff.dotProduct(box_akAxis[1]), fY1Max = fY1Min; + Ogre::Real fY2Min = kDiff.dotProduct(box_akAxis[2]), fY2Max = fY2Min; + + for (unsigned int i = 2; i < vertex_count; i++) + { + kDiff = vertices[i] - box_kCenter; + + const Ogre::Real fY0 = kDiff.dotProduct(box_akAxis[0]); + if ( fY0 < fY0Min ) + fY0Min = fY0; + else if ( fY0 > fY0Max ) + fY0Max = fY0; + + const Ogre::Real fY1 = kDiff.dotProduct(box_akAxis[1]); + if ( fY1 < fY1Min ) + fY1Min = fY1; + else if ( fY1 > fY1Max ) + fY1Max = fY1; + + const Ogre::Real fY2 = kDiff.dotProduct(box_akAxis[2]); + if ( fY2 < fY2Min ) + fY2Min = fY2; + else if ( fY2 > fY2Max ) + fY2Max = fY2; + } + + box_afExtent.x = ((Real)0.5)*(fY0Max - fY0Min); + box_afExtent.y = ((Real)0.5)*(fY1Max - fY1Min); + box_afExtent.z = ((Real)0.5)*(fY2Max - fY2Min); + + box_kCenter += (0.5*(fY0Max+fY0Min))*box_akAxis[0] + + (0.5*(fY1Max+fY1Min))*box_akAxis[1] + + (0.5*(fY2Max+fY2Min))*box_akAxis[2]; + + box_afExtent *= 2.0; + + return true; + } + + //------------------------------------------------------------------------------------------------ + btBoxShape *AnimatedMeshToShapeConverter::createOrientedBox(unsigned char bone, + const Vector3 &bonePosition, + const Quaternion &boneOrientation) + { + Ogre::Vector3 box_akAxis[3]; + Ogre::Vector3 box_afExtent; + Ogre::Vector3 box_afCenter; + + if (!getOrientedBox(bone, bonePosition, boneOrientation, + box_afExtent, + box_akAxis, + box_afCenter)) + return 0; + + btBoxShape *geom = new btBoxShape(Convert::toBullet(box_afExtent)); + //geom->setOrientation(Quaternion(box_akAxis[0],box_akAxis[1],box_akAxis[2])); + //geom->setPosition(box_afCenter); + return geom; + } /* * ============================================================================================= @@ -786,133 +814,138 @@ namespace BtOgre { * ============================================================================================= */ - DynamicRenderable::DynamicRenderable() - { - } - //------------------------------------------------------------------------------------------------ - DynamicRenderable::~DynamicRenderable() - { - delete mRenderOp.vertexData; - delete mRenderOp.indexData; - } - //------------------------------------------------------------------------------------------------ - void DynamicRenderable::initialize(RenderOperation::OperationType operationType, - bool useIndices) - { - // Initialize render operation - mRenderOp.operationType = operationType; - mRenderOp.useIndexes = useIndices; - mRenderOp.vertexData = new VertexData; - if (mRenderOp.useIndexes) - mRenderOp.indexData = new IndexData; - - // Reset buffer capacities - mVertexBufferCapacity = 0; - mIndexBufferCapacity = 0; - - // Create vertex declaration - createVertexDeclaration(); - } - //------------------------------------------------------------------------------------------------ - void DynamicRenderable::prepareHardwareBuffers(size_t vertexCount, - size_t indexCount) - { - // Prepare vertex buffer - size_t newVertCapacity = mVertexBufferCapacity; - if ((vertexCount > mVertexBufferCapacity) || - (!mVertexBufferCapacity)) - { - // vertexCount exceeds current capacity! - // It is necessary to reallocate the buffer. - - // Check if this is the first call - if (!newVertCapacity) - newVertCapacity = 1; - - // Make capacity the next power of two - while (newVertCapacity < vertexCount) - newVertCapacity <<= 1; - } - else if (vertexCount < mVertexBufferCapacity>>1) { - // Make capacity the previous power of two - while (vertexCount < newVertCapacity>>1) - newVertCapacity >>= 1; - } - if (newVertCapacity != mVertexBufferCapacity) - { - mVertexBufferCapacity = newVertCapacity; - // Create new vertex buffer - HardwareVertexBufferSharedPtr vbuf = - HardwareBufferManager::getSingleton().createVertexBuffer( - mRenderOp.vertexData->vertexDeclaration->getVertexSize(0), - mVertexBufferCapacity, - HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // TODO: Custom HBU_? - - // Bind buffer - mRenderOp.vertexData->vertexBufferBinding->setBinding(0, vbuf); - } - // Update vertex count in the render operation - mRenderOp.vertexData->vertexCount = vertexCount; - - if (mRenderOp.useIndexes) - { - OgreAssert(indexCount <= std::numeric_limits::max(), "indexCount exceeds 16 bit"); - - size_t newIndexCapacity = mIndexBufferCapacity; - // Prepare index buffer - if ((indexCount > newIndexCapacity) || - (!newIndexCapacity)) - { - // indexCount exceeds current capacity! - // It is necessary to reallocate the buffer. - - // Check if this is the first call - if (!newIndexCapacity) - newIndexCapacity = 1; - - // Make capacity the next power of two - while (newIndexCapacity < indexCount) - newIndexCapacity <<= 1; - - } - else if (indexCount < newIndexCapacity>>1) - { - // Make capacity the previous power of two - while (indexCount < newIndexCapacity>>1) - newIndexCapacity >>= 1; - } - - if (newIndexCapacity != mIndexBufferCapacity) - { - mIndexBufferCapacity = newIndexCapacity; - // Create new index buffer - mRenderOp.indexData->indexBuffer = - HardwareBufferManager::getSingleton().createIndexBuffer( - HardwareIndexBuffer::IT_16BIT, - mIndexBufferCapacity, - HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // TODO: Custom HBU_? - } - - // Update index count in the render operation - mRenderOp.indexData->indexCount = indexCount; - } - } - //------------------------------------------------------------------------------------------------ - Real DynamicRenderable::getBoundingRadius(void) const - { - return Math::Sqrt(std::max(mBox.getMaximum().squaredLength(), mBox.getMinimum().squaredLength())); - } - //------------------------------------------------------------------------------------------------ - Real DynamicRenderable::getSquaredViewDepth(const Camera* cam) const - { - Vector3 vMin, vMax, vMid, vDist; - vMin = mBox.getMinimum(); - vMax = mBox.getMaximum(); - vMid = ((vMax - vMin) * 0.5) + vMin; - vDist = cam->getDerivedPosition() - vMid; - - return vDist.squaredLength(); - } + DynamicRenderable::DynamicRenderable() + { + } + + //------------------------------------------------------------------------------------------------ + DynamicRenderable::~DynamicRenderable() + { + delete mRenderOp.vertexData; + delete mRenderOp.indexData; + } + + //------------------------------------------------------------------------------------------------ + void DynamicRenderable::initialize(RenderOperation::OperationType operationType, + bool useIndices) + { + // Initialize render operation + mRenderOp.operationType = operationType; + mRenderOp.useIndexes = useIndices; + mRenderOp.vertexData = new VertexData; + if (mRenderOp.useIndexes) + mRenderOp.indexData = new IndexData; + + // Reset buffer capacities + mVertexBufferCapacity = 0; + mIndexBufferCapacity = 0; + + // Create vertex declaration + createVertexDeclaration(); + } + + //------------------------------------------------------------------------------------------------ + void DynamicRenderable::prepareHardwareBuffers(size_t vertexCount, + size_t indexCount) + { + // Prepare vertex buffer + size_t newVertCapacity = mVertexBufferCapacity; + if ((vertexCount > mVertexBufferCapacity) || + (!mVertexBufferCapacity)) + { + // vertexCount exceeds current capacity! + // It is necessary to reallocate the buffer. + + // Check if this is the first call + if (!newVertCapacity) + newVertCapacity = 1; + + // Make capacity the next power of two + while (newVertCapacity < vertexCount) + newVertCapacity <<= 1; + } + else if (vertexCount < mVertexBufferCapacity>>1) { + // Make capacity the previous power of two + while (vertexCount < newVertCapacity>>1) + newVertCapacity >>= 1; + } + if (newVertCapacity != mVertexBufferCapacity) + { + mVertexBufferCapacity = newVertCapacity; + // Create new vertex buffer + HardwareVertexBufferSharedPtr vbuf = + HardwareBufferManager::getSingleton().createVertexBuffer( + mRenderOp.vertexData->vertexDeclaration->getVertexSize(0), + mVertexBufferCapacity, + HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // TODO: Custom HBU_? + + // Bind buffer + mRenderOp.vertexData->vertexBufferBinding->setBinding(0, vbuf); + } + // Update vertex count in the render operation + mRenderOp.vertexData->vertexCount = vertexCount; + + if (mRenderOp.useIndexes) + { + OgreAssert(indexCount <= std::numeric_limits::max(), "indexCount exceeds 16 bit"); + + size_t newIndexCapacity = mIndexBufferCapacity; + // Prepare index buffer + if ((indexCount > newIndexCapacity) || + (!newIndexCapacity)) + { + // indexCount exceeds current capacity! + // It is necessary to reallocate the buffer. + + // Check if this is the first call + if (!newIndexCapacity) + newIndexCapacity = 1; + + // Make capacity the next power of two + while (newIndexCapacity < indexCount) + newIndexCapacity <<= 1; + + } + else if (indexCount < newIndexCapacity>>1) + { + // Make capacity the previous power of two + while (indexCount < newIndexCapacity>>1) + newIndexCapacity >>= 1; + } + + if (newIndexCapacity != mIndexBufferCapacity) + { + mIndexBufferCapacity = newIndexCapacity; + // Create new index buffer + mRenderOp.indexData->indexBuffer = + HardwareBufferManager::getSingleton().createIndexBuffer( + HardwareIndexBuffer::IT_16BIT, + mIndexBufferCapacity, + HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // TODO: Custom HBU_? + } + + // Update index count in the render operation + mRenderOp.indexData->indexCount = indexCount; + } + } + + //------------------------------------------------------------------------------------------------ + Real DynamicRenderable::getBoundingRadius(void) const + { + return Math::Sqrt(std::max(mBox.getMaximum().squaredLength(), mBox.getMinimum().squaredLength())); + } + + //------------------------------------------------------------------------------------------------ + Real DynamicRenderable::getSquaredViewDepth(const Camera* cam) const + { + Vector3 vMin, vMax, vMid, vDist; + vMin = mBox.getMinimum(); + vMax = mBox.getMaximum(); + vMid = ((vMax - vMin) * 0.5) + vMin; + vDist = cam->getDerivedPosition() - vMid; + + return vDist.squaredLength(); + } /* * ============================================================================================= @@ -920,125 +953,138 @@ namespace BtOgre { * ============================================================================================= */ - enum { - POSITION_BINDING, - TEXCOORD_BINDING - }; - //------------------------------------------------------------------------------------------------ - DynamicLines::DynamicLines(OperationType opType) - { - initialize(opType,false); - setMaterial("BaseWhiteNoLighting"); - mDirty = true; - } - //------------------------------------------------------------------------------------------------ - DynamicLines::~DynamicLines() - { - } - //------------------------------------------------------------------------------------------------ - void DynamicLines::setOperationType(OperationType opType) - { - mRenderOp.operationType = opType; - } - //------------------------------------------------------------------------------------------------ - RenderOperation::OperationType DynamicLines::getOperationType() const - { - return mRenderOp.operationType; - } - //------------------------------------------------------------------------------------------------ - void DynamicLines::addPoint(const Vector3 &p) - { - mPoints.push_back(p); - mDirty = true; - } - //------------------------------------------------------------------------------------------------ - void DynamicLines::addPoint(Real x, Real y, Real z) - { - mPoints.push_back(Vector3(x,y,z)); - mDirty = true; - } - //------------------------------------------------------------------------------------------------ - const Vector3& DynamicLines::getPoint(unsigned short index) const - { - assert(index < mPoints.size() && "Point index is out of bounds!!"); - return mPoints[index]; - } - //------------------------------------------------------------------------------------------------ - unsigned short DynamicLines::getNumPoints(void) const - { - return (unsigned short)mPoints.size(); - } - //------------------------------------------------------------------------------------------------ - void DynamicLines::setPoint(unsigned short index, const Vector3 &value) - { - assert(index < mPoints.size() && "Point index is out of bounds!!"); - - mPoints[index] = value; - mDirty = true; - } - //------------------------------------------------------------------------------------------------ - void DynamicLines::clear() - { - mPoints.clear(); - mDirty = true; - } - //------------------------------------------------------------------------------------------------ - void DynamicLines::update() - { - if (mDirty) fillHardwareBuffers(); - } - //------------------------------------------------------------------------------------------------ - void DynamicLines::createVertexDeclaration() - { - VertexDeclaration *decl = mRenderOp.vertexData->vertexDeclaration; - decl->addElement(POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION); - } - //------------------------------------------------------------------------------------------------ - void DynamicLines::fillHardwareBuffers() - { - int size = mPoints.size(); - - prepareHardwareBuffers(size,0); - - if (!size) { - mBox.setExtents(Vector3::ZERO,Vector3::ZERO); - mDirty=false; - return; - } - - Vector3 vaabMin = mPoints[0]; - Vector3 vaabMax = mPoints[0]; - - HardwareVertexBufferSharedPtr vbuf = - mRenderOp.vertexData->vertexBufferBinding->getBuffer(0); - - Real *prPos = static_cast(vbuf->lock(HardwareBuffer::HBL_DISCARD)); - { - for(int i = 0; i < size; i++) - { - *prPos++ = mPoints[i].x; - *prPos++ = mPoints[i].y; - *prPos++ = mPoints[i].z; - - if(mPoints[i].x < vaabMin.x) - vaabMin.x = mPoints[i].x; - if(mPoints[i].y < vaabMin.y) - vaabMin.y = mPoints[i].y; - if(mPoints[i].z < vaabMin.z) - vaabMin.z = mPoints[i].z; - - if(mPoints[i].x > vaabMax.x) - vaabMax.x = mPoints[i].x; - if(mPoints[i].y > vaabMax.y) - vaabMax.y = mPoints[i].y; - if(mPoints[i].z > vaabMax.z) - vaabMax.z = mPoints[i].z; - } - } - vbuf->unlock(); - - mBox.setExtents(vaabMin, vaabMax); - - mDirty = false; - } -} + enum { + POSITION_BINDING, + TEXCOORD_BINDING + }; + + //------------------------------------------------------------------------------------------------ + DynamicLines::DynamicLines(OperationType opType) + { + initialize(opType,false); + setMaterial("BaseWhiteNoLighting"); + mDirty = true; + } + + //------------------------------------------------------------------------------------------------ + DynamicLines::~DynamicLines() + { + } + + //------------------------------------------------------------------------------------------------ + void DynamicLines::setOperationType(OperationType opType) + { + mRenderOp.operationType = opType; + } + + //------------------------------------------------------------------------------------------------ + RenderOperation::OperationType DynamicLines::getOperationType() const + { + return mRenderOp.operationType; + } + + //------------------------------------------------------------------------------------------------ + void DynamicLines::addPoint(const Vector3 &p) + { + mPoints.push_back(p); + mDirty = true; + } + + //------------------------------------------------------------------------------------------------ + void DynamicLines::addPoint(Real x, Real y, Real z) + { + mPoints.push_back(Vector3(x,y,z)); + mDirty = true; + } + + //------------------------------------------------------------------------------------------------ + const Vector3& DynamicLines::getPoint(unsigned short index) const + { + assert(index < mPoints.size() && "Point index is out of bounds!!"); + return mPoints[index]; + } + + //------------------------------------------------------------------------------------------------ + unsigned short DynamicLines::getNumPoints(void) const + { + return (unsigned short)mPoints.size(); + } + + //------------------------------------------------------------------------------------------------ + void DynamicLines::setPoint(unsigned short index, const Vector3 &value) + { + assert(index < mPoints.size() && "Point index is out of bounds!!"); + + mPoints[index] = value; + mDirty = true; + } + + //------------------------------------------------------------------------------------------------ + void DynamicLines::clear() + { + mPoints.clear(); + mDirty = true; + } + + //------------------------------------------------------------------------------------------------ + void DynamicLines::update() + { + if (mDirty) fillHardwareBuffers(); + } + + //------------------------------------------------------------------------------------------------ + void DynamicLines::createVertexDeclaration() + { + VertexDeclaration *decl = mRenderOp.vertexData->vertexDeclaration; + decl->addElement(POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION); + } + + //------------------------------------------------------------------------------------------------ + void DynamicLines::fillHardwareBuffers() + { + int size = mPoints.size(); + + prepareHardwareBuffers(size,0); + + if (!size) { + mBox.setExtents(Vector3::ZERO,Vector3::ZERO); + mDirty=false; + return; + } + + Vector3 vaabMin = mPoints[0]; + Vector3 vaabMax = mPoints[0]; + + HardwareVertexBufferSharedPtr vbuf = + mRenderOp.vertexData->vertexBufferBinding->getBuffer(0); + + Real *prPos = static_cast(vbuf->lock(HardwareBuffer::HBL_DISCARD)); + { + for(int i = 0; i < size; i++) + { + *prPos++ = mPoints[i].x; + *prPos++ = mPoints[i].y; + *prPos++ = mPoints[i].z; + + if(mPoints[i].x < vaabMin.x) + vaabMin.x = mPoints[i].x; + if(mPoints[i].y < vaabMin.y) + vaabMin.y = mPoints[i].y; + if(mPoints[i].z < vaabMin.z) + vaabMin.z = mPoints[i].z; + + if(mPoints[i].x > vaabMax.x) + vaabMax.x = mPoints[i].x; + if(mPoints[i].y > vaabMax.y) + vaabMax.y = mPoints[i].y; + if(mPoints[i].z > vaabMax.z) + vaabMax.z = mPoints[i].z; + } + } + vbuf->unlock(); + + mBox.setExtents(vaabMin, vaabMax); + + mDirty = false; + } +} diff --git a/bullet/BtOgreExtras.h b/bullet/BtOgreExtras.h index f95943377..f3e1aa87a 100644 --- a/bullet/BtOgreExtras.h +++ b/bullet/BtOgreExtras.h @@ -35,26 +35,26 @@ typedef std::vector Vector3Array; class Convert { public: - Convert() {}; - ~Convert() {}; - - static btQuaternion toBullet(const Ogre::Quaternion &q) - { - return btQuaternion(q.x, q.y, q.z, q.w); - } - static btVector3 toBullet(const Ogre::Vector3 &v) - { - return btVector3(v.x, v.y, v.z); - } - - static Ogre::Quaternion toOgre(const btQuaternion &q) - { - return Ogre::Quaternion(q.w(), q.x(), q.y(), q.z()); - } - static Ogre::Vector3 toOgre(const btVector3 &v) - { - return Ogre::Vector3(v.x(), v.y(), v.z()); - } + Convert() {}; + ~Convert() {}; + + static btQuaternion toBullet(const Ogre::Quaternion &q) + { + return btQuaternion(q.x, q.y, q.z, q.w); + } + static btVector3 toBullet(const Ogre::Vector3 &v) + { + return btVector3(v.x, v.y, v.z); + } + + static Ogre::Quaternion toOgre(const btQuaternion &q) + { + return Ogre::Quaternion(q.w(), q.x(), q.y(), q.z()); + } + static Ogre::Vector3 toOgre(const btVector3 &v) + { + return Ogre::Vector3(v.x(), v.y(), v.z()); + } }; //From here on its debug-drawing stuff. ------------------------------------------------------------------ @@ -151,11 +151,11 @@ public: /// Remove all points from the point list void clear(); - /// Call this to update the hardware buffer after making changes. + /// Call this to update the hardware buffer after making changes. void update(); /** Set the type of operation to draw with. - * @param opType Can be one of + * @param opType Can be one of * - RenderOperation::OT_LINE_STRIP * - RenderOperation::OT_LINE_LIST * - RenderOperation::OT_POINT_LIST @@ -181,20 +181,20 @@ private: class DebugDrawer : public btIDebugDraw { protected: - Ogre::SceneNode *mNode; - btDynamicsWorld *mWorld; - DynamicLines *mLineDrawer; - bool mDebugOn; + Ogre::SceneNode *mNode; + btDynamicsWorld *mWorld; + DynamicLines *mLineDrawer; + bool mDebugOn; public: - DebugDrawer(Ogre::SceneNode *node, btDynamicsWorld *world) - : mNode(node), - mWorld(world), - mDebugOn(true) - { - mLineDrawer = new DynamicLines(Ogre::RenderOperation::OT_LINE_LIST); - mNode->attachObject(mLineDrawer); + DebugDrawer(Ogre::SceneNode *node, btDynamicsWorld *world) + : mNode(node), + mWorld(world), + mDebugOn(true) + { + mLineDrawer = new DynamicLines(Ogre::RenderOperation::OT_LINE_LIST); + mNode->attachObject(mLineDrawer); if (!Ogre::ResourceGroupManager::getSingleton().resourceGroupExists("BtOgre")) Ogre::ResourceGroupManager::getSingleton().createResourceGroup("BtOgre"); @@ -205,68 +205,68 @@ public: mat->setSelfIllumination(1,1,1); } - mLineDrawer->setMaterial("BtOgre/DebugLines"); - } + mLineDrawer->setMaterial("BtOgre/DebugLines"); + } - ~DebugDrawer() - { + ~DebugDrawer() + { Ogre::MaterialManager::getSingleton().remove("BtOgre/DebugLines"); Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("BtOgre"); - delete mLineDrawer; - } - - void step() - { - if (mDebugOn) - { - mWorld->debugDrawWorld(); - mLineDrawer->update(); - mNode->needUpdate(); - mLineDrawer->clear(); - } - else - { - mLineDrawer->clear(); - mLineDrawer->update(); - mNode->needUpdate(); - } - } - - void drawLine(const btVector3& from,const btVector3& to,const btVector3& color) - { - mLineDrawer->addPoint(Convert::toOgre(from)); - mLineDrawer->addPoint(Convert::toOgre(to)); - } - - void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color) - { - mLineDrawer->addPoint(Convert::toOgre(PointOnB)); - mLineDrawer->addPoint(Convert::toOgre(PointOnB) + (Convert::toOgre(normalOnB) * distance * 20)); - } - - void reportErrorWarning(const char* warningString) - { - Ogre::LogManager::getSingleton().logMessage(warningString); - } - - void draw3dText(const btVector3& location,const char* textString) - { - } - - //0 for off, anything else for on. - void setDebugMode(int isOn) - { - mDebugOn = (isOn == 0) ? false : true; - - if (!mDebugOn) - mLineDrawer->clear(); - } - - //0 for off, anything else for on. - int getDebugMode() const - { - return mDebugOn; - } + delete mLineDrawer; + } + + void step() + { + if (mDebugOn) + { + mWorld->debugDrawWorld(); + mLineDrawer->update(); + mNode->needUpdate(); + mLineDrawer->clear(); + } + else + { + mLineDrawer->clear(); + mLineDrawer->update(); + mNode->needUpdate(); + } + } + + void drawLine(const btVector3& from,const btVector3& to,const btVector3& color) + { + mLineDrawer->addPoint(Convert::toOgre(from)); + mLineDrawer->addPoint(Convert::toOgre(to)); + } + + void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color) + { + mLineDrawer->addPoint(Convert::toOgre(PointOnB)); + mLineDrawer->addPoint(Convert::toOgre(PointOnB) + (Convert::toOgre(normalOnB) * distance * 20)); + } + + void reportErrorWarning(const char* warningString) + { + Ogre::LogManager::getSingleton().logMessage(warningString); + } + + void draw3dText(const btVector3& location,const char* textString) + { + } + + //0 for off, anything else for on. + void setDebugMode(int isOn) + { + mDebugOn = (isOn == 0) ? false : true; + + if (!mDebugOn) + mLineDrawer->clear(); + } + + //0 for off, anything else for on. + int getDebugMode() const + { + return mDebugOn; + } }; diff --git a/bullet/BtOgreGP.h b/bullet/BtOgreGP.h index 1894a79b3..f0534de4b 100644 --- a/bullet/BtOgreGP.h +++ b/bullet/BtOgreGP.h @@ -3,7 +3,7 @@ * * Filename: BtOgreGP.h * - * Description: The part of BtOgre that handles information transfer from Ogre to + * Description: The part of BtOgre that handles information transfer from Ogre to * Bullet (like mesh data for making trimeshes). * * Version: 1.0 @@ -29,49 +29,49 @@ typedef std::pair BoneKeyIndex; class VertexIndexToShape { public: - VertexIndexToShape(const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); - ~VertexIndexToShape(); + VertexIndexToShape(const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); + ~VertexIndexToShape(); - Ogre::Real getRadius(); - Ogre::Vector3 getSize(); + Ogre::Real getRadius(); + Ogre::Vector3 getSize(); - btSphereShape* createSphere(); - btBoxShape* createBox(); - btBvhTriangleMeshShape* createTrimesh(); - btCylinderShape* createCylinder(); - btConvexHullShape* createConvex(); + btSphereShape* createSphere(); + btBoxShape* createBox(); + btBvhTriangleMeshShape* createTrimesh(); + btCylinderShape* createCylinder(); + btConvexHullShape* createConvex(); - const Ogre::Vector3* getVertices(); - unsigned int getVertexCount(); - const unsigned int* getIndices(); - unsigned int getIndexCount(); + const Ogre::Vector3* getVertices(); + unsigned int getVertexCount(); + const unsigned int* getIndices(); + unsigned int getIndexCount(); protected: - void addStaticVertexData(const Ogre::VertexData *vertex_data); + void addStaticVertexData(const Ogre::VertexData *vertex_data); - void addAnimatedVertexData(const Ogre::VertexData *vertex_data, - const Ogre::VertexData *blended_data, - const Ogre::Mesh::IndexMap *indexMap); + void addAnimatedVertexData(const Ogre::VertexData *vertex_data, + const Ogre::VertexData *blended_data, + const Ogre::Mesh::IndexMap *indexMap); - void addIndexData(Ogre::IndexData *data, const unsigned int offset = 0); + void addIndexData(Ogre::IndexData *data, const unsigned int offset = 0); protected: - Ogre::Vector3* mVertexBuffer; - unsigned int* mIndexBuffer; - unsigned int mVertexCount; - unsigned int mIndexCount; + Ogre::Vector3* mVertexBuffer; + unsigned int* mIndexBuffer; + unsigned int mVertexCount; + unsigned int mIndexCount; - Ogre::Matrix4 mTransform; + Ogre::Matrix4 mTransform; - Ogre::Real mBoundRadius; - Ogre::Vector3 mBounds; + Ogre::Real mBoundRadius; + Ogre::Vector3 mBounds; - BoneIndex *mBoneIndex; + BoneIndex *mBoneIndex; - Ogre::Vector3 mScale; + Ogre::Vector3 mScale; }; //For static (non-animated) meshes. @@ -79,21 +79,21 @@ class StaticMeshToShapeConverter : public VertexIndexToShape { public: - StaticMeshToShapeConverter(Ogre::Renderable *rend, const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); - StaticMeshToShapeConverter(Ogre::Entity *entity, const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); - StaticMeshToShapeConverter(); + StaticMeshToShapeConverter(Ogre::Renderable *rend, const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); + StaticMeshToShapeConverter(Ogre::Entity *entity, const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); + StaticMeshToShapeConverter(); - ~StaticMeshToShapeConverter(); + ~StaticMeshToShapeConverter(); - void addEntity(Ogre::Entity *entity,const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); - - void addMesh(const Ogre::MeshPtr &mesh, const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); + void addEntity(Ogre::Entity *entity,const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); + + void addMesh(const Ogre::MeshPtr &mesh, const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); protected: - Ogre::Entity* mEntity; - Ogre::SceneNode* mNode; + Ogre::Entity* mEntity; + Ogre::SceneNode* mNode; }; //For animated meshes. @@ -101,43 +101,42 @@ class AnimatedMeshToShapeConverter : public VertexIndexToShape { public: - AnimatedMeshToShapeConverter(Ogre::Entity *entity, const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); - AnimatedMeshToShapeConverter(); - ~AnimatedMeshToShapeConverter(); + AnimatedMeshToShapeConverter(Ogre::Entity *entity, const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); + AnimatedMeshToShapeConverter(); + ~AnimatedMeshToShapeConverter(); - void addEntity(Ogre::Entity *entity,const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); - void addMesh(const Ogre::MeshPtr &mesh, const Ogre::Matrix4 &transform); + void addEntity(Ogre::Entity *entity,const Ogre::Matrix4 &transform = Ogre::Matrix4::IDENTITY); + void addMesh(const Ogre::MeshPtr &mesh, const Ogre::Matrix4 &transform); - btBoxShape* createAlignedBox(unsigned char bone, - const Ogre::Vector3 &bonePosition, - const Ogre::Quaternion &boneOrientation); + btBoxShape* createAlignedBox(unsigned char bone, + const Ogre::Vector3 &bonePosition, + const Ogre::Quaternion &boneOrientation); - btBoxShape* createOrientedBox(unsigned char bone, - const Ogre::Vector3 &bonePosition, - const Ogre::Quaternion &boneOrientation); + btBoxShape* createOrientedBox(unsigned char bone, + const Ogre::Vector3 &bonePosition, + const Ogre::Quaternion &boneOrientation); protected: - bool getBoneVertices(unsigned char bone, - unsigned int &vertex_count, - Ogre::Vector3* &vertices, - const Ogre::Vector3 &bonePosition); + bool getBoneVertices(unsigned char bone, + unsigned int &vertex_count, + Ogre::Vector3* &vertices, + const Ogre::Vector3 &bonePosition); - bool getOrientedBox(unsigned char bone, - const Ogre::Vector3 &bonePosition, - const Ogre::Quaternion &boneOrientation, - Ogre::Vector3 &extents, - Ogre::Vector3 *axis, - Ogre::Vector3 ¢er); + bool getOrientedBox(unsigned char bone, + const Ogre::Vector3 &bonePosition, + const Ogre::Quaternion &boneOrientation, + Ogre::Vector3 &extents, + Ogre::Vector3 *axis, + Ogre::Vector3 ¢er); - - Ogre::Entity* mEntity; - Ogre::SceneNode* mNode; + Ogre::Entity* mEntity; + Ogre::SceneNode* mNode; - Ogre::Vector3 *mTransformedVerticesTemp; - size_t mTransformedVerticesTempSize; + Ogre::Vector3 *mTransformedVerticesTemp; + size_t mTransformedVerticesTempSize; }; } -#endif \ No newline at end of file +#endif diff --git a/bullet/BtOgrePG.h b/bullet/BtOgrePG.h index b1d271540..9ff069a8f 100644 --- a/bullet/BtOgrePG.h +++ b/bullet/BtOgrePG.h @@ -3,7 +3,7 @@ * * Filename: BtOgrePG.h * - * Description: The part of BtOgre that handles information transfer from Bullet to + * Description: The part of BtOgre that handles information transfer from Bullet to * Ogre (like updating graphics object positions). * * Version: 1.0 @@ -25,7 +25,7 @@ namespace BtOgre { //A MotionState is Bullet's way of informing you about updates to an object. //Pass this MotionState to a btRigidBody to have your SceneNode updated automaticaly. -class RigidBodyState : public btMotionState +class RigidBodyState : public btMotionState { protected: btTransform mTransform; @@ -42,19 +42,19 @@ class RigidBodyState : public btMotionState } RigidBodyState(Ogre::SceneNode *node) - : mTransform(((node != NULL) ? BtOgre::Convert::toBullet(node->getOrientation()) : btQuaternion(0,0,0,1)), + : mTransform(((node != NULL) ? BtOgre::Convert::toBullet(node->getOrientation()) : btQuaternion(0,0,0,1)), ((node != NULL) ? BtOgre::Convert::toBullet(node->getPosition()) : btVector3(0,0,0))), mCenterOfMassOffset(btTransform::getIdentity()), mNode(node) { } - virtual void getWorldTransform(btTransform &ret) const + virtual void getWorldTransform(btTransform &ret) const { ret = mCenterOfMassOffset.inverse() * mTransform; } - virtual void setWorldTransform(const btTransform &in) + virtual void setWorldTransform(const btTransform &in) { if (mNode == NULL) return; @@ -68,7 +68,7 @@ class RigidBodyState : public btMotionState mNode->setPosition(pos.x(), pos.y(), pos.z()); } - void setNode(Ogre::SceneNode *node) + void setNode(Ogre::SceneNode *node) { mNode = node; } diff --git a/bullet/BulletShapeLoader.cpp b/bullet/BulletShapeLoader.cpp index 927ec6a27..48b87e1e8 100644 --- a/bullet/BulletShapeLoader.cpp +++ b/bullet/BulletShapeLoader.cpp @@ -2,8 +2,8 @@ -BulletShape::BulletShape(Ogre::ResourceManager* creator, const Ogre::String &name, - Ogre::ResourceHandle handle, const Ogre::String &group, bool isManual, +BulletShape::BulletShape(Ogre::ResourceManager* creator, const Ogre::String &name, + Ogre::ResourceHandle handle, const Ogre::String &group, bool isManual, Ogre::ManualResourceLoader *loader) : Ogre::Resource(creator, name, handle, group, isManual, loader) { @@ -12,9 +12,9 @@ Ogre::Resource(creator, name, handle, group, isManual, loader) /* For consistency with StringInterface, but we don't add any parameters here That's because the Resource implementation of StringInterface is to - list all the options that need to be set before loading, of which + list all the options that need to be set before loading, of which we have none as such. Full details can be set through scripts. - */ + */ Shape = NULL; collide = true; createParamDictionary("BulletShape"); @@ -70,8 +70,8 @@ BulletShapeManager *BulletShapeManager::getSingletonPtr() } BulletShapeManager &BulletShapeManager::getSingleton() -{ - assert(ms_Singleton); +{ + assert(ms_Singleton); return(*ms_Singleton); } @@ -103,8 +103,8 @@ BulletShapePtr BulletShapeManager::load(const Ogre::String &name, const Ogre::St return textf; } -Ogre::Resource *BulletShapeManager::createImpl(const Ogre::String &name, Ogre::ResourceHandle handle, - const Ogre::String &group, bool isManual, Ogre::ManualResourceLoader *loader, +Ogre::Resource *BulletShapeManager::createImpl(const Ogre::String &name, Ogre::ResourceHandle handle, + const Ogre::String &group, bool isManual, Ogre::ManualResourceLoader *loader, const Ogre::NameValuePairList *createParams) { BulletShape* res = new BulletShape(this, name, handle, group, isManual, loader); @@ -121,4 +121,4 @@ void BulletShapeLoader::loadResource(Ogre::Resource *resource) {} void BulletShapeLoader::load(const std::string &name,const std::string &group) -{} \ No newline at end of file +{} diff --git a/bullet/BulletShapeLoader.h b/bullet/BulletShapeLoader.h index e28a7175e..316ee523c 100644 --- a/bullet/BulletShapeLoader.h +++ b/bullet/BulletShapeLoader.h @@ -128,11 +128,11 @@ class BulletShapeLoader : public Ogre::ManualResourceLoader public: BulletShapeLoader(){}; - virtual ~BulletShapeLoader() {} + virtual ~BulletShapeLoader() {} - virtual void loadResource(Ogre::Resource *resource); + virtual void loadResource(Ogre::Resource *resource); - virtual void load(const std::string &name,const std::string &group); + virtual void load(const std::string &name,const std::string &group); }; -#endif \ No newline at end of file +#endif diff --git a/bullet/CMotionState.cpp b/bullet/CMotionState.cpp index 3725fd77a..5ddef5175 100644 --- a/bullet/CMotionState.cpp +++ b/bullet/CMotionState.cpp @@ -10,36 +10,36 @@ namespace OEngine { namespace Physic { - CMotionState::CMotionState(PhysicEngine* eng,std::string name) - { - pEng = eng; - tr.setIdentity(); - pName = name; - }; - - void CMotionState::getWorldTransform(btTransform &worldTrans) const - { - worldTrans = tr; - } - - void CMotionState::setWorldTransform(const btTransform &worldTrans) - { - tr = worldTrans; - - PhysicEvent evt; - evt.isNPC = isNPC; - evt.isPC = isPC; - evt.newTransform = tr; - evt.RigidBodyName = pName; - - if(isPC) - { - pEng->PEventList.push_back(evt); - } - else - { - pEng->NPEventList.push_back(evt); - } - } + CMotionState::CMotionState(PhysicEngine* eng,std::string name) + { + pEng = eng; + tr.setIdentity(); + pName = name; + }; + + void CMotionState::getWorldTransform(btTransform &worldTrans) const + { + worldTrans = tr; + } + + void CMotionState::setWorldTransform(const btTransform &worldTrans) + { + tr = worldTrans; + + PhysicEvent evt; + evt.isNPC = isNPC; + evt.isPC = isPC; + evt.newTransform = tr; + evt.RigidBodyName = pName; + + if(isPC) + { + pEng->PEventList.push_back(evt); + } + else + { + pEng->NPEventList.push_back(evt); + } + } }} diff --git a/bullet/CMotionState.h b/bullet/CMotionState.h index 3dfb3a05c..3508ab4ef 100644 --- a/bullet/CMotionState.h +++ b/bullet/CMotionState.h @@ -7,46 +7,46 @@ namespace OEngine { namespace Physic { - class PhysicEngine; - - /** - *A CMotionState is associated with a single RigidBody. - *When the RigidBody is moved by bullet, bullet will call the function setWorldTransform. - *for more info, see the bullet Wiki at btMotionState. - */ - class CMotionState:public btMotionState - { - public: - - CMotionState(PhysicEngine* eng,std::string name); - - /** - *Return the position of the RigidBody. - */ - virtual void getWorldTransform(btTransform &worldTrans) const; - - /** - *Function called by bullet when the RigidBody is moved. - *It add an event to the EventList of the PhysicEngine class. - */ - virtual void setWorldTransform(const btTransform &worldTrans); - - protected: - PhysicEngine* pEng; - btTransform tr; - bool isNPC; - bool isPC; - - std::string pName; - }; - - struct PhysicEvent - { - bool isNPC; - bool isPC; - btTransform newTransform; - std::string RigidBodyName; - }; + class PhysicEngine; + + /** + * A CMotionState is associated with a single RigidBody. + * When the RigidBody is moved by bullet, bullet will call the function setWorldTransform. + * for more info, see the bullet Wiki at btMotionState. + */ + class CMotionState:public btMotionState + { + public: + + CMotionState(PhysicEngine* eng,std::string name); + + /** + * Return the position of the RigidBody. + */ + virtual void getWorldTransform(btTransform &worldTrans) const; + + /** + * Function called by bullet when the RigidBody is moved. + * It add an event to the EventList of the PhysicEngine class. + */ + virtual void setWorldTransform(const btTransform &worldTrans); + + protected: + PhysicEngine* pEng; + btTransform tr; + bool isNPC; + bool isPC; + + std::string pName; + }; + + struct PhysicEvent + { + bool isNPC; + bool isPC; + btTransform newTransform; + std::string RigidBodyName; + }; }} #endif diff --git a/bullet/btKinematicCharacterController.cpp b/bullet/btKinematicCharacterController.cpp index d93034985..fc4f3278f 100644 --- a/bullet/btKinematicCharacterController.cpp +++ b/bullet/btKinematicCharacterController.cpp @@ -4,8 +4,8 @@ Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com 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, +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. @@ -28,109 +28,109 @@ subject to the following restrictions: class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback { public: - btKinematicClosestNotMeRayResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) - { - m_me[0] = me; - count = 1; - } - - btKinematicClosestNotMeRayResultCallback (btCollisionObject* me[], int count_) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) - { - count = count_; - - for(int i = 0; i < count; i++) - m_me[i] = me[i]; - } - - virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) - { - for(int i = 0; i < count; i++) - if (rayResult.m_collisionObject == m_me[i]) - return 1.0; - - return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace); - } + btKinematicClosestNotMeRayResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) + { + m_me[0] = me; + count = 1; + } + + btKinematicClosestNotMeRayResultCallback (btCollisionObject* me[], int count_) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) + { + count = count_; + + for(int i = 0; i < count; i++) + m_me[i] = me[i]; + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) + { + for(int i = 0; i < count; i++) + if (rayResult.m_collisionObject == m_me[i]) + return 1.0; + + return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace); + } protected: - btCollisionObject* m_me[10]; - int count; + btCollisionObject* m_me[10]; + int count; }; class btKinematicClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback { public: - btKinematicClosestNotMeConvexResultCallback( btCollisionObject* me, const btVector3& up, btScalar minSlopeDot ) - : btCollisionWorld::ClosestConvexResultCallback( btVector3( 0.0, 0.0, 0.0 ), btVector3( 0.0, 0.0, 0.0 ) ), - m_me( me ), m_up( up ), m_minSlopeDot( minSlopeDot ) - { - } - - virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace) - { - if( convexResult.m_hitCollisionObject == m_me ) - return btScalar( 1 ); - - btVector3 hitNormalWorld; - if( normalInWorldSpace ) - { - hitNormalWorld = convexResult.m_hitNormalLocal; - } - else - { - ///need to transform normal into worldspace - hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; - } - - // NOTE : m_hitNormalLocal is not always vertical on the ground with a capsule or a box... - - btScalar dotUp = m_up.dot(hitNormalWorld); - if( dotUp < m_minSlopeDot ) - return btScalar( 1 ); - - return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace); - } + btKinematicClosestNotMeConvexResultCallback( btCollisionObject* me, const btVector3& up, btScalar minSlopeDot ) + : btCollisionWorld::ClosestConvexResultCallback( btVector3( 0.0, 0.0, 0.0 ), btVector3( 0.0, 0.0, 0.0 ) ), + m_me( me ), m_up( up ), m_minSlopeDot( minSlopeDot ) + { + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace) + { + if( convexResult.m_hitCollisionObject == m_me ) + return btScalar( 1 ); + + btVector3 hitNormalWorld; + if( normalInWorldSpace ) + { + hitNormalWorld = convexResult.m_hitNormalLocal; + } + else + { + ///need to transform normal into worldspace + hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; + } + + // NOTE : m_hitNormalLocal is not always vertical on the ground with a capsule or a box... + + btScalar dotUp = m_up.dot(hitNormalWorld); + if( dotUp < m_minSlopeDot ) + return btScalar( 1 ); + + return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace); + } protected: - btCollisionObject* m_me; - const btVector3 m_up; - btScalar m_minSlopeDot; + btCollisionObject* m_me; + const btVector3 m_up; + btScalar m_minSlopeDot; }; btKinematicCharacterController::btKinematicCharacterController( btPairCachingGhostObject* externalGhostObject_, - btPairCachingGhostObject* internalGhostObject_, - btScalar stepHeight, - btScalar constantScale, - btScalar gravity, - btScalar fallVelocity, - btScalar jumpVelocity, - btScalar recoveringFactor ) + btPairCachingGhostObject* internalGhostObject_, + btScalar stepHeight, + btScalar constantScale, + btScalar gravity, + btScalar fallVelocity, + btScalar jumpVelocity, + btScalar recoveringFactor ) { - m_upAxis = btKinematicCharacterController::Y_AXIS; + m_upAxis = btKinematicCharacterController::Y_AXIS; - m_walkDirection.setValue( btScalar( 0 ), btScalar( 0 ), btScalar( 0 ) ); + m_walkDirection.setValue( btScalar( 0 ), btScalar( 0 ), btScalar( 0 ) ); - m_useGhostObjectSweepTest = true; + m_useGhostObjectSweepTest = true; - externalGhostObject = externalGhostObject_; - internalGhostObject = internalGhostObject_; + externalGhostObject = externalGhostObject_; + internalGhostObject = internalGhostObject_; - m_recoveringFactor = recoveringFactor; + m_recoveringFactor = recoveringFactor; - m_stepHeight = stepHeight; + m_stepHeight = stepHeight; - m_useWalkDirection = true; // use walk direction by default, legacy behavior - m_velocityTimeInterval = btScalar( 0 ); - m_verticalVelocity = btScalar( 0 ); - m_verticalOffset = btScalar( 0 ); + m_useWalkDirection = true; // use walk direction by default, legacy behavior + m_velocityTimeInterval = btScalar( 0 ); + m_verticalVelocity = btScalar( 0 ); + m_verticalOffset = btScalar( 0 ); - m_gravity = constantScale * gravity; - m_fallSpeed = constantScale * fallVelocity; // Terminal velocity of a sky diver in m/s. + m_gravity = constantScale * gravity; + m_fallSpeed = constantScale * fallVelocity; // Terminal velocity of a sky diver in m/s. - m_jumpSpeed = constantScale * jumpVelocity; // ? - m_wasJumping = false; + m_jumpSpeed = constantScale * jumpVelocity; // ? + m_wasJumping = false; - setMaxSlope( btRadians( 45.0 ) ); + setMaxSlope( btRadians( 45.0 ) ); mCollision = true; } @@ -147,78 +147,78 @@ void btKinematicCharacterController::setVerticalVelocity(float z) bool btKinematicCharacterController::recoverFromPenetration( btCollisionWorld* collisionWorld ) { - bool penetration = false; + bool penetration = false; if(!mCollision) return penetration; - collisionWorld->getDispatcher()->dispatchAllCollisionPairs( internalGhostObject->getOverlappingPairCache(), - collisionWorld->getDispatchInfo(), - collisionWorld->getDispatcher() ); + collisionWorld->getDispatcher()->dispatchAllCollisionPairs( internalGhostObject->getOverlappingPairCache(), + collisionWorld->getDispatchInfo(), + collisionWorld->getDispatcher() ); - btVector3 currentPosition = internalGhostObject->getWorldTransform().getOrigin(); + btVector3 currentPosition = internalGhostObject->getWorldTransform().getOrigin(); - btScalar maxPen = btScalar( 0 ); + btScalar maxPen = btScalar( 0 ); - for( int i = 0; i < internalGhostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++ ) - { - m_manifoldArray.resize(0); + for( int i = 0; i < internalGhostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++ ) + { + m_manifoldArray.resize(0); - btBroadphasePair* collisionPair = &internalGhostObject->getOverlappingPairCache()->getOverlappingPairArray()[i]; + btBroadphasePair* collisionPair = &internalGhostObject->getOverlappingPairCache()->getOverlappingPairArray()[i]; - if( collisionPair->m_algorithm ) - collisionPair->m_algorithm->getAllContactManifolds( m_manifoldArray ); + if( collisionPair->m_algorithm ) + collisionPair->m_algorithm->getAllContactManifolds( m_manifoldArray ); - for( int j = 0; j < m_manifoldArray.size(); j++ ) - { - btPersistentManifold* manifold = m_manifoldArray[j]; + for( int j = 0; j < m_manifoldArray.size(); j++ ) + { + btPersistentManifold* manifold = m_manifoldArray[j]; - btScalar directionSign = manifold->getBody0() == internalGhostObject ? btScalar( -1.0 ) : btScalar( 1.0 ); + btScalar directionSign = manifold->getBody0() == internalGhostObject ? btScalar( -1.0 ) : btScalar( 1.0 ); - for( int p = 0; p < manifold->getNumContacts(); p++ ) - { - const btManifoldPoint&pt = manifold->getContactPoint( p ); - if( (manifold->getBody1() == externalGhostObject && manifold->getBody0() == internalGhostObject) - ||(manifold->getBody0() == externalGhostObject && manifold->getBody1() == internalGhostObject) ) - { - } - else - { - btScalar dist = pt.getDistance(); + for( int p = 0; p < manifold->getNumContacts(); p++ ) + { + const btManifoldPoint&pt = manifold->getContactPoint( p ); + if( (manifold->getBody1() == externalGhostObject && manifold->getBody0() == internalGhostObject) + ||(manifold->getBody0() == externalGhostObject && manifold->getBody1() == internalGhostObject) ) + { + } + else + { + btScalar dist = pt.getDistance(); - if( dist < 0.0 ) - { - if( dist < maxPen ) - maxPen = dist; + if( dist < 0.0 ) + { + if( dist < maxPen ) + maxPen = dist; - // NOTE : btScalar affects the stairs but the parkinson... - // 0.0 , the capsule can break the walls... - currentPosition += pt.m_normalWorldOnB * directionSign * dist * m_recoveringFactor; + // NOTE : btScalar affects the stairs but the parkinson... + // 0.0 , the capsule can break the walls... + currentPosition += pt.m_normalWorldOnB * directionSign * dist * m_recoveringFactor; - penetration = true; - } - } - } + penetration = true; + } + } + } - // ??? - //manifold->clearManifold(); - } - } + // ??? + //manifold->clearManifold(); + } + } - btTransform transform = internalGhostObject->getWorldTransform(); + btTransform transform = internalGhostObject->getWorldTransform(); - transform.setOrigin( currentPosition ); + transform.setOrigin( currentPosition ); - internalGhostObject->setWorldTransform( transform ); - externalGhostObject->setWorldTransform( transform ); + internalGhostObject->setWorldTransform( transform ); + externalGhostObject->setWorldTransform( transform ); - return penetration; + return penetration; } btVector3 btKinematicCharacterController::stepUp( btCollisionWorld* world, const btVector3& currentPosition, btScalar& currentStepOffset ) { - btVector3 targetPosition = currentPosition + getUpAxisDirections()[ m_upAxis ] * ( m_stepHeight + ( m_verticalOffset > btScalar( 0.0 ) ? m_verticalOffset : 0.0 ) ); + btVector3 targetPosition = currentPosition + getUpAxisDirections()[ m_upAxis ] * ( m_stepHeight + ( m_verticalOffset > btScalar( 0.0 ) ? m_verticalOffset : 0.0 ) ); //if the no collisions mode is on, no need to go any further if(!mCollision) @@ -227,248 +227,248 @@ btVector3 btKinematicCharacterController::stepUp( btCollisionWorld* world, const return targetPosition; } - // Retrieve the collision shape - // - btCollisionShape* collisionShape = externalGhostObject->getCollisionShape(); - btAssert( collisionShape->isConvex() ); - - btConvexShape* convexShape = ( btConvexShape* )collisionShape; - - // FIXME: Handle penetration properly - // - btTransform start; - start.setIdentity(); - start.setOrigin( currentPosition + getUpAxisDirections()[ m_upAxis ] * ( convexShape->getMargin() ) ); - - btTransform end; - end.setIdentity(); - end.setOrigin( targetPosition ); - - btKinematicClosestNotMeConvexResultCallback callback( externalGhostObject, -getUpAxisDirections()[ m_upAxis ], m_maxSlopeCosine ); - callback.m_collisionFilterGroup = externalGhostObject->getBroadphaseHandle()->m_collisionFilterGroup; - callback.m_collisionFilterMask = externalGhostObject->getBroadphaseHandle()->m_collisionFilterMask; - - // Sweep test - // - if( m_useGhostObjectSweepTest ) - externalGhostObject->convexSweepTest( convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration ); - - else - world->convexSweepTest( convexShape, start, end, callback ); - - if( callback.hasHit() ) - { - // Only modify the position if the hit was a slope and not a wall or ceiling. - // - if( callback.m_hitNormalWorld.dot(getUpAxisDirections()[m_upAxis]) > btScalar( 0.0 ) ) - { - // We moved up only a fraction of the step height - // - currentStepOffset = m_stepHeight * callback.m_closestHitFraction; - - return currentPosition.lerp( targetPosition, callback.m_closestHitFraction ); - } - - m_verticalVelocity = btScalar( 0.0 ); - m_verticalOffset = btScalar( 0.0 ); - - return currentPosition; - } - else - { - currentStepOffset = m_stepHeight; - return targetPosition; - } + // Retrieve the collision shape + // + btCollisionShape* collisionShape = externalGhostObject->getCollisionShape(); + btAssert( collisionShape->isConvex() ); + + btConvexShape* convexShape = ( btConvexShape* )collisionShape; + + // FIXME: Handle penetration properly + // + btTransform start; + start.setIdentity(); + start.setOrigin( currentPosition + getUpAxisDirections()[ m_upAxis ] * ( convexShape->getMargin() ) ); + + btTransform end; + end.setIdentity(); + end.setOrigin( targetPosition ); + + btKinematicClosestNotMeConvexResultCallback callback( externalGhostObject, -getUpAxisDirections()[ m_upAxis ], m_maxSlopeCosine ); + callback.m_collisionFilterGroup = externalGhostObject->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = externalGhostObject->getBroadphaseHandle()->m_collisionFilterMask; + + // Sweep test + // + if( m_useGhostObjectSweepTest ) + externalGhostObject->convexSweepTest( convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration ); + + else + world->convexSweepTest( convexShape, start, end, callback ); + + if( callback.hasHit() ) + { + // Only modify the position if the hit was a slope and not a wall or ceiling. + // + if( callback.m_hitNormalWorld.dot(getUpAxisDirections()[m_upAxis]) > btScalar( 0.0 ) ) + { + // We moved up only a fraction of the step height + // + currentStepOffset = m_stepHeight * callback.m_closestHitFraction; + + return currentPosition.lerp( targetPosition, callback.m_closestHitFraction ); + } + + m_verticalVelocity = btScalar( 0.0 ); + m_verticalOffset = btScalar( 0.0 ); + + return currentPosition; + } + else + { + currentStepOffset = m_stepHeight; + return targetPosition; + } } ///Reflect the vector d around the vector r inline btVector3 reflect( const btVector3& d, const btVector3& r ) { - return d - ( btScalar( 2.0 ) * d.dot( r ) ) * r; + return d - ( btScalar( 2.0 ) * d.dot( r ) ) * r; } ///Project a vector u on another vector v inline btVector3 project( const btVector3& u, const btVector3& v ) { - return v * u.dot( v ); + return v * u.dot( v ); } ///Helper for computing the character sliding inline btVector3 slide( const btVector3& direction, const btVector3& planeNormal ) { - return direction - project( direction, planeNormal ); + return direction - project( direction, planeNormal ); } btVector3 slideOnCollision( const btVector3& fromPosition, const btVector3& toPosition, const btVector3& hitNormal ) { - btVector3 moveDirection = toPosition - fromPosition; - btScalar moveLength = moveDirection.length(); + btVector3 moveDirection = toPosition - fromPosition; + btScalar moveLength = moveDirection.length(); - if( moveLength <= btScalar( SIMD_EPSILON ) ) - return toPosition; + if( moveLength <= btScalar( SIMD_EPSILON ) ) + return toPosition; - moveDirection.normalize(); + moveDirection.normalize(); - btVector3 reflectDir = reflect( moveDirection, hitNormal ); - reflectDir.normalize(); + btVector3 reflectDir = reflect( moveDirection, hitNormal ); + reflectDir.normalize(); - return fromPosition + slide( reflectDir, hitNormal ) * moveLength; + return fromPosition + slide( reflectDir, hitNormal ) * moveLength; } btVector3 btKinematicCharacterController::stepForwardAndStrafe( btCollisionWorld* collisionWorld, const btVector3& currentPosition, const btVector3& walkMove ) { - // We go to ! - // - btVector3 targetPosition = currentPosition + walkMove; + // We go to ! + // + btVector3 targetPosition = currentPosition + walkMove; //if the no collisions mode is on, no need to go any further if(!mCollision) return targetPosition; - // Retrieve the collision shape - // - btCollisionShape* collisionShape = externalGhostObject->getCollisionShape(); - btAssert( collisionShape->isConvex() ); - - btConvexShape* convexShape = ( btConvexShape* )collisionShape; - - btTransform start; - start.setIdentity(); - - btTransform end; - end.setIdentity(); - - btScalar fraction = btScalar( 1.0 ); - - // This optimization scheme suffers in the corners. - // It basically jumps from a wall to another, then fails to find a new - // position (after 4 iterations here) and finally don't move at all. - // - // The stepping algorithm adds some problems with stairs. It seems - // the treads create some fake corner using capsules for collisions. - // - for( int i = 0; i < 4 && fraction > btScalar( 0.01 ); i++ ) - { - start.setOrigin( currentPosition ); - end.setOrigin( targetPosition ); - - btVector3 sweepDirNegative = currentPosition - targetPosition; - - btKinematicClosestNotMeConvexResultCallback callback( externalGhostObject, sweepDirNegative, btScalar( 0.0 ) ); - callback.m_collisionFilterGroup = externalGhostObject->getBroadphaseHandle()->m_collisionFilterGroup; - callback.m_collisionFilterMask = externalGhostObject->getBroadphaseHandle()->m_collisionFilterMask; - - if( m_useGhostObjectSweepTest ) - externalGhostObject->convexSweepTest( convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration ); - - else - collisionWorld->convexSweepTest( convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration ); - - if( callback.hasHit() ) - { - // Try another target position - // - targetPosition = slideOnCollision( currentPosition, targetPosition, callback.m_hitNormalWorld ); - fraction = callback.m_closestHitFraction; - } - else - - // Move to the valid target position - // - return targetPosition; - } - - // Don't move if you can't find a valid target position... - // It prevents some flickering. - // - return currentPosition; + // Retrieve the collision shape + // + btCollisionShape* collisionShape = externalGhostObject->getCollisionShape(); + btAssert( collisionShape->isConvex() ); + + btConvexShape* convexShape = ( btConvexShape* )collisionShape; + + btTransform start; + start.setIdentity(); + + btTransform end; + end.setIdentity(); + + btScalar fraction = btScalar( 1.0 ); + + // This optimization scheme suffers in the corners. + // It basically jumps from a wall to another, then fails to find a new + // position (after 4 iterations here) and finally don't move at all. + // + // The stepping algorithm adds some problems with stairs. It seems + // the treads create some fake corner using capsules for collisions. + // + for( int i = 0; i < 4 && fraction > btScalar( 0.01 ); i++ ) + { + start.setOrigin( currentPosition ); + end.setOrigin( targetPosition ); + + btVector3 sweepDirNegative = currentPosition - targetPosition; + + btKinematicClosestNotMeConvexResultCallback callback( externalGhostObject, sweepDirNegative, btScalar( 0.0 ) ); + callback.m_collisionFilterGroup = externalGhostObject->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = externalGhostObject->getBroadphaseHandle()->m_collisionFilterMask; + + if( m_useGhostObjectSweepTest ) + externalGhostObject->convexSweepTest( convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration ); + + else + collisionWorld->convexSweepTest( convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration ); + + if( callback.hasHit() ) + { + // Try another target position + // + targetPosition = slideOnCollision( currentPosition, targetPosition, callback.m_hitNormalWorld ); + fraction = callback.m_closestHitFraction; + } + else + + // Move to the valid target position + // + return targetPosition; + } + + // Don't move if you can't find a valid target position... + // It prevents some flickering. + // + return currentPosition; } ///Handle the gravity btScalar btKinematicCharacterController::addFallOffset( bool wasOnGround, btScalar currentStepOffset, btScalar dt ) { - btScalar downVelocity = ( m_verticalVelocity < 0.0 ? -m_verticalVelocity : btScalar( 0.0 ) ) * dt; + btScalar downVelocity = ( m_verticalVelocity < 0.0 ? -m_verticalVelocity : btScalar( 0.0 ) ) * dt; - if( downVelocity > btScalar( 0.0 ) && downVelocity < m_stepHeight && ( wasOnGround || !m_wasJumping ) ) - downVelocity = m_stepHeight; + if( downVelocity > btScalar( 0.0 ) && downVelocity < m_stepHeight && ( wasOnGround || !m_wasJumping ) ) + downVelocity = m_stepHeight; - return currentStepOffset + downVelocity; + return currentStepOffset + downVelocity; } btVector3 btKinematicCharacterController::stepDown( btCollisionWorld* collisionWorld, const btVector3& currentPosition, btScalar currentStepOffset ) { - btVector3 stepDrop = getUpAxisDirections()[ m_upAxis ] * currentStepOffset; + btVector3 stepDrop = getUpAxisDirections()[ m_upAxis ] * currentStepOffset; - // Be sure we are falling from the last m_currentPosition - // It prevents some flickering - // - btVector3 targetPosition = currentPosition - stepDrop; + // Be sure we are falling from the last m_currentPosition + // It prevents some flickering + // + btVector3 targetPosition = currentPosition - stepDrop; //if the no collisions mode is on, no need to go any further if(!mCollision) return targetPosition; - btTransform start; - start.setIdentity(); - start.setOrigin( currentPosition ); - - btTransform end; - end.setIdentity(); - end.setOrigin( targetPosition ); - - btKinematicClosestNotMeConvexResultCallback callback( internalGhostObject, getUpAxisDirections()[ m_upAxis ], m_maxSlopeCosine ); - callback.m_collisionFilterGroup = internalGhostObject->getBroadphaseHandle()->m_collisionFilterGroup; - callback.m_collisionFilterMask = internalGhostObject->getBroadphaseHandle()->m_collisionFilterMask; - - // Retrieve the collision shape - // - btCollisionShape* collisionShape = internalGhostObject->getCollisionShape(); - btAssert( collisionShape->isConvex() ); - btConvexShape* convexShape = ( btConvexShape* )collisionShape; - - if( m_useGhostObjectSweepTest ) - externalGhostObject->convexSweepTest( convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration ); - - else - collisionWorld->convexSweepTest( convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration ); - - if( callback.hasHit() ) - { - m_verticalVelocity = btScalar( 0.0 ); - m_verticalOffset = btScalar( 0.0 ); - m_wasJumping = false; - - // We dropped a fraction of the height -> hit floor - // - return currentPosition.lerp( targetPosition, callback.m_closestHitFraction ); - } - else - - // We dropped the full height - // - return targetPosition; + btTransform start; + start.setIdentity(); + start.setOrigin( currentPosition ); + + btTransform end; + end.setIdentity(); + end.setOrigin( targetPosition ); + + btKinematicClosestNotMeConvexResultCallback callback( internalGhostObject, getUpAxisDirections()[ m_upAxis ], m_maxSlopeCosine ); + callback.m_collisionFilterGroup = internalGhostObject->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = internalGhostObject->getBroadphaseHandle()->m_collisionFilterMask; + + // Retrieve the collision shape + // + btCollisionShape* collisionShape = internalGhostObject->getCollisionShape(); + btAssert( collisionShape->isConvex() ); + btConvexShape* convexShape = ( btConvexShape* )collisionShape; + + if( m_useGhostObjectSweepTest ) + externalGhostObject->convexSweepTest( convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration ); + + else + collisionWorld->convexSweepTest( convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration ); + + if( callback.hasHit() ) + { + m_verticalVelocity = btScalar( 0.0 ); + m_verticalOffset = btScalar( 0.0 ); + m_wasJumping = false; + + // We dropped a fraction of the height -> hit floor + // + return currentPosition.lerp( targetPosition, callback.m_closestHitFraction ); + } + else + + // We dropped the full height + // + return targetPosition; } void btKinematicCharacterController::setWalkDirection( const btVector3& walkDirection ) { - m_useWalkDirection = true; - m_walkDirection = walkDirection; + m_useWalkDirection = true; + m_walkDirection = walkDirection; } void btKinematicCharacterController::setVelocityForTimeInterval( const btVector3& velocity, btScalar timeInterval ) { - m_useWalkDirection = false; - m_walkDirection = velocity; - m_velocityTimeInterval = timeInterval; + m_useWalkDirection = false; + m_walkDirection = velocity; + m_velocityTimeInterval = timeInterval; } @@ -479,162 +479,162 @@ void btKinematicCharacterController::reset() void btKinematicCharacterController::warp( const btVector3& origin ) { - btTransform transform; - transform.setIdentity(); - transform.setOrigin( -origin ); + btTransform transform; + transform.setIdentity(); + transform.setOrigin( -origin ); - externalGhostObject->setWorldTransform( transform ); - internalGhostObject->setWorldTransform( transform ); + externalGhostObject->setWorldTransform( transform ); + internalGhostObject->setWorldTransform( transform ); } void btKinematicCharacterController::preStep( btCollisionWorld* collisionWorld ) { - BT_PROFILE( "preStep" ); + BT_PROFILE( "preStep" ); - for( int i = 0; i < 4 && recoverFromPenetration ( collisionWorld ); i++ ); + for( int i = 0; i < 4 && recoverFromPenetration ( collisionWorld ); i++ ); } void btKinematicCharacterController::playerStep( btCollisionWorld* collisionWorld, btScalar dt ) { - BT_PROFILE( "playerStep" ); + BT_PROFILE( "playerStep" ); - if( !m_useWalkDirection && m_velocityTimeInterval <= btScalar( 0.0 ) ) - return; + if( !m_useWalkDirection && m_velocityTimeInterval <= btScalar( 0.0 ) ) + return; - bool wasOnGround = onGround(); + bool wasOnGround = onGround(); - // Handle the gravity - // - m_verticalVelocity -= m_gravity * dt; + // Handle the gravity + // + m_verticalVelocity -= m_gravity * dt; - if( m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed ) - m_verticalVelocity = m_jumpSpeed; + if( m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed ) + m_verticalVelocity = m_jumpSpeed; - if( m_verticalVelocity < 0.0 && btFabs( m_verticalVelocity ) > btFabs( m_fallSpeed ) ) - m_verticalVelocity = -btFabs( m_fallSpeed ); + if( m_verticalVelocity < 0.0 && btFabs( m_verticalVelocity ) > btFabs( m_fallSpeed ) ) + m_verticalVelocity = -btFabs( m_fallSpeed ); - m_verticalOffset = m_verticalVelocity * dt; + m_verticalOffset = m_verticalVelocity * dt; - // This forced stepping up can cause problems when the character - // walks (jump in fact...) under too low ceilings. - // - btVector3 currentPosition = externalGhostObject->getWorldTransform().getOrigin(); - btScalar currentStepOffset; + // This forced stepping up can cause problems when the character + // walks (jump in fact...) under too low ceilings. + // + btVector3 currentPosition = externalGhostObject->getWorldTransform().getOrigin(); + btScalar currentStepOffset; - currentPosition = stepUp( collisionWorld, currentPosition, currentStepOffset ); + currentPosition = stepUp( collisionWorld, currentPosition, currentStepOffset ); - // Move in the air and slide against the walls ignoring the stair steps. - // - if( m_useWalkDirection ) - currentPosition = stepForwardAndStrafe( collisionWorld, currentPosition, m_walkDirection ); + // Move in the air and slide against the walls ignoring the stair steps. + // + if( m_useWalkDirection ) + currentPosition = stepForwardAndStrafe( collisionWorld, currentPosition, m_walkDirection ); - else - { - btScalar dtMoving = ( dt < m_velocityTimeInterval ) ? dt : m_velocityTimeInterval; - m_velocityTimeInterval -= dt; + else + { + btScalar dtMoving = ( dt < m_velocityTimeInterval ) ? dt : m_velocityTimeInterval; + m_velocityTimeInterval -= dt; - // How far will we move while we are moving ? - // - btVector3 moveDirection = m_walkDirection * dtMoving; + // How far will we move while we are moving ? + // + btVector3 moveDirection = m_walkDirection * dtMoving; - currentPosition = stepForwardAndStrafe( collisionWorld, currentPosition, moveDirection ); - } + currentPosition = stepForwardAndStrafe( collisionWorld, currentPosition, moveDirection ); + } - // Finally find the ground. - // - currentStepOffset = addFallOffset( wasOnGround, currentStepOffset, dt ); + // Finally find the ground. + // + currentStepOffset = addFallOffset( wasOnGround, currentStepOffset, dt ); - currentPosition = stepDown( collisionWorld, currentPosition, currentStepOffset ); + currentPosition = stepDown( collisionWorld, currentPosition, currentStepOffset ); - // Apply the new position to the collision objects. - // - btTransform tranform; - tranform = externalGhostObject->getWorldTransform(); - tranform.setOrigin( currentPosition ); + // Apply the new position to the collision objects. + // + btTransform tranform; + tranform = externalGhostObject->getWorldTransform(); + tranform.setOrigin( currentPosition ); - externalGhostObject->setWorldTransform( tranform ); - internalGhostObject->setWorldTransform( tranform ); + externalGhostObject->setWorldTransform( tranform ); + internalGhostObject->setWorldTransform( tranform ); } void btKinematicCharacterController::setFallSpeed( btScalar fallSpeed ) { - m_fallSpeed = fallSpeed; + m_fallSpeed = fallSpeed; } void btKinematicCharacterController::setJumpSpeed( btScalar jumpSpeed ) { - m_jumpSpeed = jumpSpeed; + m_jumpSpeed = jumpSpeed; } void btKinematicCharacterController::setMaxJumpHeight( btScalar maxJumpHeight ) { - m_maxJumpHeight = maxJumpHeight; + m_maxJumpHeight = maxJumpHeight; } bool btKinematicCharacterController::canJump() const { - return onGround(); + return onGround(); } void btKinematicCharacterController::jump() { - if( !canJump() ) - return; + if( !canJump() ) + return; - m_verticalVelocity = m_jumpSpeed; - m_wasJumping = true; + m_verticalVelocity = m_jumpSpeed; + m_wasJumping = true; } void btKinematicCharacterController::setGravity( btScalar gravity ) { - m_gravity = gravity; + m_gravity = gravity; } btScalar btKinematicCharacterController::getGravity() const { - return m_gravity; + return m_gravity; } void btKinematicCharacterController::setMaxSlope( btScalar slopeRadians ) { - m_maxSlopeRadians = slopeRadians; - m_maxSlopeCosine = btCos( slopeRadians ); + m_maxSlopeRadians = slopeRadians; + m_maxSlopeCosine = btCos( slopeRadians ); } btScalar btKinematicCharacterController::getMaxSlope() const { - return m_maxSlopeRadians; + return m_maxSlopeRadians; } bool btKinematicCharacterController::onGround() const { - return btFabs( m_verticalVelocity ) < btScalar( SIMD_EPSILON ) && - btFabs( m_verticalOffset ) < btScalar( SIMD_EPSILON ); + return btFabs( m_verticalVelocity ) < btScalar( SIMD_EPSILON ) && + btFabs( m_verticalOffset ) < btScalar( SIMD_EPSILON ); } btVector3* btKinematicCharacterController::getUpAxisDirections() { - static btVector3 sUpAxisDirection[] = - { - btVector3( btScalar( 0.0 ), btScalar( 0.0 ), btScalar( 0.0 ) ), - btVector3( btScalar( 0.0 ), btScalar( 1.0 ), btScalar( 0.0 ) ), - btVector3( btScalar( 0.0 ), btScalar( 0.0 ), btScalar( 1.0 ) ) - }; + static btVector3 sUpAxisDirection[] = + { + btVector3( btScalar( 0.0 ), btScalar( 0.0 ), btScalar( 0.0 ) ), + btVector3( btScalar( 0.0 ), btScalar( 1.0 ), btScalar( 0.0 ) ), + btVector3( btScalar( 0.0 ), btScalar( 0.0 ), btScalar( 1.0 ) ) + }; - return sUpAxisDirection; + return sUpAxisDirection; } diff --git a/bullet/btKinematicCharacterController.h b/bullet/btKinematicCharacterController.h index d58e242ad..d24cd9722 100644 --- a/bullet/btKinematicCharacterController.h +++ b/bullet/btKinematicCharacterController.h @@ -44,41 +44,41 @@ public: }; private: - btPairCachingGhostObject* externalGhostObject; // use this for querying collisions for sliding and move - btPairCachingGhostObject* internalGhostObject; // and this for recoreving from penetrations + btPairCachingGhostObject* externalGhostObject; // use this for querying collisions for sliding and move + btPairCachingGhostObject* internalGhostObject; // and this for recoreving from penetrations - btScalar m_verticalVelocity; - btScalar m_verticalOffset; - btScalar m_fallSpeed; - btScalar m_jumpSpeed; - btScalar m_maxJumpHeight; - btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value) - btScalar m_maxSlopeCosine; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization) - btScalar m_gravity; - btScalar m_recoveringFactor; + btScalar m_verticalVelocity; + btScalar m_verticalOffset; + btScalar m_fallSpeed; + btScalar m_jumpSpeed; + btScalar m_maxJumpHeight; + btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value) + btScalar m_maxSlopeCosine; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization) + btScalar m_gravity; + btScalar m_recoveringFactor; - btScalar m_stepHeight; + btScalar m_stepHeight; - ///this is the desired walk direction, set by the user - btVector3 m_walkDirection; + ///this is the desired walk direction, set by the user + btVector3 m_walkDirection; - ///keep track of the contact manifolds - btManifoldArray m_manifoldArray; + ///keep track of the contact manifolds + btManifoldArray m_manifoldArray; ///Gravity attributes - bool m_wasJumping; + bool m_wasJumping; - bool m_useGhostObjectSweepTest; - bool m_useWalkDirection; - btScalar m_velocityTimeInterval; + bool m_useGhostObjectSweepTest; + bool m_useWalkDirection; + btScalar m_velocityTimeInterval; - UpAxis m_upAxis; + UpAxis m_upAxis; - static btVector3* getUpAxisDirections(); + static btVector3* getUpAxisDirections(); - bool recoverFromPenetration ( btCollisionWorld* collisionWorld ); + bool recoverFromPenetration ( btCollisionWorld* collisionWorld ); - btVector3 stepUp( btCollisionWorld* collisionWorld, const btVector3& currentPosition, btScalar& currentStepOffset ); + btVector3 stepUp( btCollisionWorld* collisionWorld, const btVector3& currentPosition, btScalar& currentStepOffset ); btVector3 stepForwardAndStrafe( btCollisionWorld* collisionWorld, const btVector3& currentPosition, const btVector3& walkMove ); btScalar addFallOffset( bool wasJumping, btScalar currentStepOffset, btScalar dt ); btVector3 stepDown( btCollisionWorld* collisionWorld, const btVector3& currentPosition, btScalar currentStepOffset ); @@ -90,7 +90,7 @@ public: /// Using a smaller internalGhostObject can help for removing some flickering but create some /// stopping artefacts when sliding along stairs or small walls. /// Don't forget to scale gravity and fallSpeed if you scale the world. - btKinematicCharacterController( btPairCachingGhostObject* externalGhostObject, + btKinematicCharacterController( btPairCachingGhostObject* externalGhostObject, btPairCachingGhostObject* internalGhostObject, btScalar stepHeight, btScalar constantScale = btScalar( 1.0 ), @@ -99,67 +99,67 @@ public: btScalar jumpVelocity = btScalar( 9.8 ), btScalar recoveringFactor = btScalar( 0.2 ) ); - ~btKinematicCharacterController (); + ~btKinematicCharacterController (); void setVerticalVelocity(float z); - ///btActionInterface interface - virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTime ) - { + ///btActionInterface interface + virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTime ) + { preStep( collisionWorld ); - playerStep( collisionWorld, deltaTime ); - } + playerStep( collisionWorld, deltaTime ); + } - ///btActionInterface interface - void debugDraw( btIDebugDraw* debugDrawer ); + ///btActionInterface interface + void debugDraw( btIDebugDraw* debugDrawer ); void setUpAxis( UpAxis axis ) - { - m_upAxis = axis; - } - - /// This should probably be called setPositionIncrementPerSimulatorStep. - /// This is neither a direction nor a velocity, but the amount to - /// increment the position each simulation iteration, regardless - /// of dt. - /// This call will reset any velocity set by setVelocityForTimeInterval(). - virtual void setWalkDirection(const btVector3& walkDirection); - - /// Caller provides a velocity with which the character should move for - /// the given time period. After the time period, velocity is reset - /// to zero. - /// This call will reset any walk direction set by setWalkDirection(). - /// Negative time intervals will result in no motion. - virtual void setVelocityForTimeInterval(const btVector3& velocity, - btScalar timeInterval); - - void reset(); - void warp( const btVector3& origin ); - - void preStep( btCollisionWorld* collisionWorld ); - void playerStep( btCollisionWorld* collisionWorld, btScalar dt ); - - void setFallSpeed( btScalar fallSpeed ); - void setJumpSpeed( btScalar jumpSpeed ); - void setMaxJumpHeight( btScalar maxJumpHeight ); - bool canJump() const; - - void jump(); - - void setGravity( btScalar gravity ); - btScalar getGravity() const; - - /// The max slope determines the maximum angle that the controller can walk up. - /// The slope angle is measured in radians. - void setMaxSlope( btScalar slopeRadians ); - btScalar getMaxSlope() const; - - void setUseGhostSweepTest( bool useGhostObjectSweepTest ) - { - m_useGhostObjectSweepTest = useGhostObjectSweepTest; - } - - bool onGround() const; + { + m_upAxis = axis; + } + + /// This should probably be called setPositionIncrementPerSimulatorStep. + /// This is neither a direction nor a velocity, but the amount to + /// increment the position each simulation iteration, regardless + /// of dt. + /// This call will reset any velocity set by setVelocityForTimeInterval(). + virtual void setWalkDirection(const btVector3& walkDirection); + + /// Caller provides a velocity with which the character should move for + /// the given time period. After the time period, velocity is reset + /// to zero. + /// This call will reset any walk direction set by setWalkDirection(). + /// Negative time intervals will result in no motion. + virtual void setVelocityForTimeInterval(const btVector3& velocity, + btScalar timeInterval); + + void reset(); + void warp( const btVector3& origin ); + + void preStep( btCollisionWorld* collisionWorld ); + void playerStep( btCollisionWorld* collisionWorld, btScalar dt ); + + void setFallSpeed( btScalar fallSpeed ); + void setJumpSpeed( btScalar jumpSpeed ); + void setMaxJumpHeight( btScalar maxJumpHeight ); + bool canJump() const; + + void jump(); + + void setGravity( btScalar gravity ); + btScalar getGravity() const; + + /// The max slope determines the maximum angle that the controller can walk up. + /// The slope angle is measured in radians. + void setMaxSlope( btScalar slopeRadians ); + btScalar getMaxSlope() const; + + void setUseGhostSweepTest( bool useGhostObjectSweepTest ) + { + m_useGhostObjectSweepTest = useGhostObjectSweepTest; + } + + bool onGround() const; //if set to false, there will be no collision. bool mCollision; diff --git a/bullet/physic.cpp b/bullet/physic.cpp index 986b57be5..8cf7b8eb6 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -15,63 +15,63 @@ namespace OEngine { namespace Physic { - enum collisiontypes { - COL_NOTHING = 0, //setWorldTransform( transform ); + // External capsule + externalGhostObject = new PairCachingGhostObject(name); + externalGhostObject->setWorldTransform( transform ); - btScalar externalCapsuleHeight = 130; - btScalar externalCapsuleWidth = 16; + btScalar externalCapsuleHeight = 130; + btScalar externalCapsuleWidth = 16; - externalCollisionShape = new btCapsuleShapeZ( externalCapsuleWidth, externalCapsuleHeight ); - externalCollisionShape->setMargin( 0.1 ); + externalCollisionShape = new btCapsuleShapeZ( externalCapsuleWidth, externalCapsuleHeight ); + externalCollisionShape->setMargin( 0.1 ); - externalGhostObject->setCollisionShape( externalCollisionShape ); - externalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); + externalGhostObject->setCollisionShape( externalCollisionShape ); + externalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); - // Internal capsule - internalGhostObject = new PairCachingGhostObject(name); - internalGhostObject->setWorldTransform( transform ); - //internalGhostObject->getBroadphaseHandle()->s - btScalar internalCapsuleHeight = 120; - btScalar internalCapsuleWidth = 15; + // Internal capsule + internalGhostObject = new PairCachingGhostObject(name); + internalGhostObject->setWorldTransform( transform ); + //internalGhostObject->getBroadphaseHandle()->s + btScalar internalCapsuleHeight = 120; + btScalar internalCapsuleWidth = 15; - internalCollisionShape = new btCapsuleShapeZ( internalCapsuleWidth, internalCapsuleHeight ); - internalCollisionShape->setMargin( 0.1 ); + internalCollisionShape = new btCapsuleShapeZ( internalCapsuleWidth, internalCapsuleHeight ); + internalCollisionShape->setMargin( 0.1 ); - internalGhostObject->setCollisionShape( internalCollisionShape ); - internalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); + internalGhostObject->setCollisionShape( internalCollisionShape ); + internalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); - mCharacter = new btKinematicCharacterController( externalGhostObject,internalGhostObject,btScalar( 40 ),1,4,20,9.8,0.2 ); - mCharacter->setUpAxis(btKinematicCharacterController::Z_AXIS); + mCharacter = new btKinematicCharacterController( externalGhostObject,internalGhostObject,btScalar( 40 ),1,4,20,9.8,0.2 ); + mCharacter->setUpAxis(btKinematicCharacterController::Z_AXIS); mCharacter->setUseGhostSweepTest(false); mCharacter->mCollision = false; setGravity(0); - } + } - PhysicActor::~PhysicActor() - { - delete mCharacter; - delete internalGhostObject; - delete internalCollisionShape; - delete externalGhostObject; - delete externalCollisionShape; - } + PhysicActor::~PhysicActor() + { + delete mCharacter; + delete internalGhostObject; + delete internalCollisionShape; + delete externalGhostObject; + delete externalCollisionShape; + } void PhysicActor::setGravity(float gravity) { @@ -94,100 +94,100 @@ namespace Physic return mCharacter->mCollision; } - void PhysicActor::setWalkDirection(const btVector3& mvt) - { - mCharacter->setWalkDirection( mvt ); - } + void PhysicActor::setWalkDirection(const btVector3& mvt) + { + mCharacter->setWalkDirection( mvt ); + } - void PhysicActor::Rotate(const btQuaternion& quat) - { - externalGhostObject->getWorldTransform().setRotation( externalGhostObject->getWorldTransform().getRotation() * quat ); - internalGhostObject->getWorldTransform().setRotation( internalGhostObject->getWorldTransform().getRotation() * quat ); - } + void PhysicActor::Rotate(const btQuaternion& quat) + { + externalGhostObject->getWorldTransform().setRotation( externalGhostObject->getWorldTransform().getRotation() * quat ); + internalGhostObject->getWorldTransform().setRotation( internalGhostObject->getWorldTransform().getRotation() * quat ); + } - void PhysicActor::setRotation(const btQuaternion& quat) - { - externalGhostObject->getWorldTransform().setRotation( quat ); - internalGhostObject->getWorldTransform().setRotation( quat ); - } + void PhysicActor::setRotation(const btQuaternion& quat) + { + externalGhostObject->getWorldTransform().setRotation( quat ); + internalGhostObject->getWorldTransform().setRotation( quat ); + } - btVector3 PhysicActor::getPosition(void) - { - return internalGhostObject->getWorldTransform().getOrigin(); - } + btVector3 PhysicActor::getPosition(void) + { + return internalGhostObject->getWorldTransform().getOrigin(); + } - btQuaternion PhysicActor::getRotation(void) - { - return internalGhostObject->getWorldTransform().getRotation(); - } + btQuaternion PhysicActor::getRotation(void) + { + return internalGhostObject->getWorldTransform().getRotation(); + } - void PhysicActor::setPosition(const btVector3& pos) - { - internalGhostObject->getWorldTransform().setOrigin(pos); - externalGhostObject->getWorldTransform().setOrigin(pos); - } + void PhysicActor::setPosition(const btVector3& pos) + { + internalGhostObject->getWorldTransform().setOrigin(pos); + externalGhostObject->getWorldTransform().setOrigin(pos); + } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - RigidBody::RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name) - :btRigidBody(CI),mName(name) - { + RigidBody::RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name) + :btRigidBody(CI),mName(name) + { - }; + }; - /////////////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////////////////// - PhysicEngine::PhysicEngine(BulletShapeLoader* shapeLoader) - { - // Set up the collision configuration and dispatcher - collisionConfiguration = new btDefaultCollisionConfiguration(); - dispatcher = new btCollisionDispatcher(collisionConfiguration); + PhysicEngine::PhysicEngine(BulletShapeLoader* shapeLoader) + { + // Set up the collision configuration and dispatcher + collisionConfiguration = new btDefaultCollisionConfiguration(); + dispatcher = new btCollisionDispatcher(collisionConfiguration); - // The actual physics solver - solver = new btSequentialImpulseConstraintSolver; + // The actual physics solver + solver = new btSequentialImpulseConstraintSolver; - //TODO: memory leak? - btOverlappingPairCache* pairCache = new btSortedOverlappingPairCache(); - pairCache->setInternalGhostPairCallback( new btGhostPairCallback() ); + //TODO: memory leak? + btOverlappingPairCache* pairCache = new btSortedOverlappingPairCache(); + pairCache->setInternalGhostPairCallback( new btGhostPairCallback() ); - broadphase = new btDbvtBroadphase(pairCache); + broadphase = new btDbvtBroadphase(pairCache); - // The world. - dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration); - dynamicsWorld->setGravity(btVector3(0,0,-10)); + // The world. + dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration); + dynamicsWorld->setGravity(btVector3(0,0,-10)); - if(BulletShapeManager::getSingletonPtr() == NULL) - { - new BulletShapeManager(); - } - //TODO:singleton? - mShapeLoader = shapeLoader; + if(BulletShapeManager::getSingletonPtr() == NULL) + { + new BulletShapeManager(); + } + //TODO:singleton? + mShapeLoader = shapeLoader; - isDebugCreated = false; - } + isDebugCreated = false; + } - void PhysicEngine::createDebugRendering() - { - if(!isDebugCreated) - { - Ogre::SceneManagerEnumerator::SceneManagerIterator iter = Ogre::Root::getSingleton().getSceneManagerIterator(); - iter.begin(); - Ogre::SceneManager* scn = iter.getNext(); - Ogre::SceneNode* node = scn->getRootSceneNode()->createChildSceneNode(); - node->pitch(Ogre::Degree(-90)); - mDebugDrawer = new BtOgre::DebugDrawer(node, dynamicsWorld); - dynamicsWorld->setDebugDrawer(mDebugDrawer); - isDebugCreated = true; - dynamicsWorld->debugDrawWorld(); - } - } + void PhysicEngine::createDebugRendering() + { + if(!isDebugCreated) + { + Ogre::SceneManagerEnumerator::SceneManagerIterator iter = Ogre::Root::getSingleton().getSceneManagerIterator(); + iter.begin(); + Ogre::SceneManager* scn = iter.getNext(); + Ogre::SceneNode* node = scn->getRootSceneNode()->createChildSceneNode(); + node->pitch(Ogre::Degree(-90)); + mDebugDrawer = new BtOgre::DebugDrawer(node, dynamicsWorld); + dynamicsWorld->setDebugDrawer(mDebugDrawer); + isDebugCreated = true; + dynamicsWorld->debugDrawWorld(); + } + } void PhysicEngine::setDebugRenderingMode(int mode) { @@ -198,69 +198,69 @@ namespace Physic mDebugDrawer->setDebugMode(mode); } - PhysicEngine::~PhysicEngine() - { - delete dynamicsWorld; - delete solver; - delete collisionConfiguration; - delete dispatcher; - delete broadphase; - delete mShapeLoader; - } - - RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name) - { - //get the shape from the .nif - mShapeLoader->load(mesh,"General"); - BulletShapeManager::getSingletonPtr()->load(mesh,"General"); - BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(mesh,"General"); - - //create the motionState - CMotionState* newMotionState = new CMotionState(this,name); - - //create the real body - btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,shape->Shape); - RigidBody* body = new RigidBody(CI,name); + PhysicEngine::~PhysicEngine() + { + delete dynamicsWorld; + delete solver; + delete collisionConfiguration; + delete dispatcher; + delete broadphase; + delete mShapeLoader; + } + + RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name) + { + //get the shape from the .nif + mShapeLoader->load(mesh,"General"); + BulletShapeManager::getSingletonPtr()->load(mesh,"General"); + BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(mesh,"General"); + + //create the motionState + CMotionState* newMotionState = new CMotionState(this,name); + + //create the real body + btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,shape->Shape); + RigidBody* body = new RigidBody(CI,name); body->collide = shape->collide; - return body; - } + return body; + } - void PhysicEngine::addRigidBody(RigidBody* body) - { + void PhysicEngine::addRigidBody(RigidBody* body) + { if(body->collide) { - dynamicsWorld->addRigidBody(body,COL_WORLD,COL_WORLD|COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL); + dynamicsWorld->addRigidBody(body,COL_WORLD,COL_WORLD|COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL); } else { dynamicsWorld->addRigidBody(body,COL_WORLD,COL_NOTHING); } - body->setActivationState(DISABLE_DEACTIVATION); - RigidBodyMap[body->mName] = body; - } + body->setActivationState(DISABLE_DEACTIVATION); + RigidBodyMap[body->mName] = body; + } - void PhysicEngine::removeRigidBody(std::string name) - { + void PhysicEngine::removeRigidBody(std::string name) + { std::map::iterator it = RigidBodyMap.find(name); if (it != RigidBodyMap.end() ) { RigidBody* body = it->second; if(body != NULL) { - // broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + // broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); /*std::map::iterator it2 = PhysicActorMap.begin(); - for(;it2!=PhysicActorMap.end();it++) - { - it2->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); - it2->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); - }*/ + for(;it2!=PhysicActorMap.end();it++) + { + it2->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + it2->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(body->getBroadphaseProxy(),dispatcher); + }*/ dynamicsWorld->removeRigidBody(RigidBodyMap[name]); } } - } + } - void PhysicEngine::deleteRigidBody(std::string name) - { + void PhysicEngine::deleteRigidBody(std::string name) + { std::map::iterator it = RigidBodyMap.find(name); if (it != RigidBodyMap.end() ) { @@ -271,34 +271,34 @@ namespace Physic } RigidBodyMap.erase(it); } - } - - RigidBody* PhysicEngine::getRigidBody(std::string name) - { - RigidBody* body = RigidBodyMap[name]; - return body; - } - - void PhysicEngine::stepSimulation(double deltaT) - { - dynamicsWorld->stepSimulation(deltaT,1,1/50.); - if(isDebugCreated) - { - mDebugDrawer->step(); - } - } - - void PhysicEngine::addCharacter(std::string name) - { - PhysicActor* newActor = new PhysicActor(name); - dynamicsWorld->addCollisionObject( newActor->externalGhostObject, COL_ACTOR_EXTERNAL, COL_WORLD |COL_ACTOR_EXTERNAL ); - dynamicsWorld->addCollisionObject( newActor->internalGhostObject, COL_ACTOR_INTERNAL, COL_WORLD |COL_ACTOR_INTERNAL ); - dynamicsWorld->addAction( newActor->mCharacter ); - PhysicActorMap[name] = newActor; - } - - void PhysicEngine::removeCharacter(std::string name) - { + } + + RigidBody* PhysicEngine::getRigidBody(std::string name) + { + RigidBody* body = RigidBodyMap[name]; + return body; + } + + void PhysicEngine::stepSimulation(double deltaT) + { + dynamicsWorld->stepSimulation(deltaT,1,1/50.); + if(isDebugCreated) + { + mDebugDrawer->step(); + } + } + + void PhysicEngine::addCharacter(std::string name) + { + PhysicActor* newActor = new PhysicActor(name); + dynamicsWorld->addCollisionObject( newActor->externalGhostObject, COL_ACTOR_EXTERNAL, COL_WORLD |COL_ACTOR_EXTERNAL ); + dynamicsWorld->addCollisionObject( newActor->internalGhostObject, COL_ACTOR_INTERNAL, COL_WORLD |COL_ACTOR_INTERNAL ); + dynamicsWorld->addAction( newActor->mCharacter ); + PhysicActorMap[name] = newActor; + } + + void PhysicEngine::removeCharacter(std::string name) + { //std::cout << "remove"; std::map::iterator it = PhysicActorMap.find(name); if (it != PhysicActorMap.end() ) @@ -307,15 +307,15 @@ namespace Physic if(act != NULL) { /*broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->externalGhostObject->getBroadphaseHandle(),dispatcher); - broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher); - std::map::iterator it2 = PhysicActorMap.begin(); - for(;it2!=PhysicActorMap.end();it++) - { - it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->externalGhostObject->getBroadphaseHandle(),dispatcher); - it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->externalGhostObject->getBroadphaseHandle(),dispatcher); - it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher); - it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher); - }*/ + broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher); + std::map::iterator it2 = PhysicActorMap.begin(); + for(;it2!=PhysicActorMap.end();it++) + { + it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->externalGhostObject->getBroadphaseHandle(),dispatcher); + it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->externalGhostObject->getBroadphaseHandle(),dispatcher); + it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher); + it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher); + }*/ //act->externalGhostObject-> dynamicsWorld->removeCollisionObject(act->externalGhostObject); dynamicsWorld->removeCollisionObject(act->internalGhostObject); @@ -325,17 +325,17 @@ namespace Physic PhysicActorMap.erase(it); } //std::cout << "ok"; - } + } - PhysicActor* PhysicEngine::getCharacter(std::string name) - { - PhysicActor* act = PhysicActorMap[name]; - return act; - } + PhysicActor* PhysicEngine::getCharacter(std::string name) + { + PhysicActor* act = PhysicActorMap[name]; + return act; + } - void PhysicEngine::emptyEventLists(void) - { - } + void PhysicEngine::emptyEventLists(void) + { + } std::pair PhysicEngine::rayTest(btVector3& from,btVector3& to) { diff --git a/bullet/physic.hpp b/bullet/physic.hpp index 0cf6abd4f..d4dfde467 100644 --- a/bullet/physic.hpp +++ b/bullet/physic.hpp @@ -18,19 +18,19 @@ class btKinematicCharacterController; namespace BtOgre { - class DebugDrawer; + class DebugDrawer; } namespace MWWorld { - class World; + class World; } namespace OEngine { namespace Physic { - class CMotionState; - struct PhysicEvent; + class CMotionState; + struct PhysicEvent; /** *This is just used to be able to name objects. @@ -45,179 +45,179 @@ namespace Physic std::string mName; }; - /** - *A physic Actor use a modifed KinematicCharacterController taken in the bullet forum. - */ - class PhysicActor - { - public: - PhysicActor(std::string name); + /** + * A physic Actor use a modifed KinematicCharacterController taken in the bullet forum. + */ + class PhysicActor + { + public: + PhysicActor(std::string name); - ~PhysicActor(); + ~PhysicActor(); - /** - *This function set the walkDirection. This is not relative to the actor orientation. - *I think it's also needed to take time into account. A typical call should look like this: - *setWalkDirection( mvt * orientation * dt) - */ - void setWalkDirection(const btVector3& mvt); + /** + * This function set the walkDirection. This is not relative to the actor orientation. + * I think it's also needed to take time into account. A typical call should look like this: + * setWalkDirection( mvt * orientation * dt) + */ + void setWalkDirection(const btVector3& mvt); - void Rotate(const btQuaternion& quat); + void Rotate(const btQuaternion& quat); - void setRotation(const btQuaternion& quat); + void setRotation(const btQuaternion& quat); void setGravity(float gravity); - + void setVerticalVelocity(float z); void enableCollisions(bool collision); bool getCollisionMode(); - btVector3 getPosition(void); + btVector3 getPosition(void); - btQuaternion getRotation(void); + btQuaternion getRotation(void); - void setPosition(const btVector3& pos); + void setPosition(const btVector3& pos); - btKinematicCharacterController* mCharacter; + btKinematicCharacterController* mCharacter; - PairCachingGhostObject* internalGhostObject; - btCollisionShape* internalCollisionShape; + PairCachingGhostObject* internalGhostObject; + btCollisionShape* internalCollisionShape; - PairCachingGhostObject* externalGhostObject; - btCollisionShape* externalCollisionShape; + PairCachingGhostObject* externalGhostObject; + btCollisionShape* externalCollisionShape; - std::string mName; - }; + std::string mName; + }; - /** - *This class is just an extension of normal btRigidBody in order to add extra info. - *When bullet give back a btRigidBody, you can just do a static_cast to RigidBody, - *so one never should use btRigidBody directly! - */ - class RigidBody: public btRigidBody - { - public: - RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name); - std::string mName; + /** + *This class is just an extension of normal btRigidBody in order to add extra info. + *When bullet give back a btRigidBody, you can just do a static_cast to RigidBody, + *so one never should use btRigidBody directly! + */ + class RigidBody: public btRigidBody + { + public: + RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name); + std::string mName; //is this body used for raycasting only? bool collide; - }; - - /** - *The PhysicEngine class contain everything which is needed for Physic. - *It's needed that Ogre Resources are set up before the PhysicEngine is created. - *Note:deleting it WILL NOT delete the RigidBody! - *TODO:unload unused resources? - */ - class PhysicEngine - { - public: - /** - *Note that the shapeLoader IS destroyed by the phyic Engine!! - */ - PhysicEngine(BulletShapeLoader* shapeLoader); - - /** - *It DOES destroy the shape loader! - */ - ~PhysicEngine(); - - /** - *create a RigidBody.It does not add it to the simulation, but it does add it to the rigidBody Map, - *so you can get it with the getRigidBody function. - */ - RigidBody* createRigidBody(std::string mesh,std::string name); - - /** - *Add a RigidBody to the simulation - */ - void addRigidBody(RigidBody* body); - - /** - *Remove a RigidBody from the simulation. It does not delete it, and does not remove it from the RigidBodyMap. - */ - void removeRigidBody(std::string name); - - /** - *delete a RigidBody, and remove it from RigidBodyMap. - */ - void deleteRigidBody(std::string name); - - /** - *Return a pointer to a given rigid body. - *TODO:check if exist - */ - RigidBody* getRigidBody(std::string name); - - /** - *Create and add a character to the scene, and add it to the ActorMap. - */ - void addCharacter(std::string name); - - /** - *Remove a character from the scene. TODO:delete it! for now, a small memory leak^^ done? - */ - void removeCharacter(std::string name); - - /** - *return a pointer to a character - *TODO:check if the actor exist... - */ - PhysicActor* getCharacter(std::string name); - - /** - *This step the simulation of a given time. - */ - void stepSimulation(double deltaT); - - /** - *Empty events lists - */ - void emptyEventLists(void); - - /** - *Create a debug rendering. It is called by setDebgRenderingMode if it's not created yet. - *Important Note: this will crash if the Render is not yet initialise! - */ - void createDebugRendering(); - - /** - *Set the debug rendering mode. 0 to turn it off. - *Important Note: this will crash if the Render is not yet initialise! - */ - void setDebugRenderingMode(int mode); - - /** - *Return the closest object hit by a ray. If there are no objects, it will return ("",-1). - */ + }; + + /** + * The PhysicEngine class contain everything which is needed for Physic. + * It's needed that Ogre Resources are set up before the PhysicEngine is created. + * Note:deleting it WILL NOT delete the RigidBody! + * TODO:unload unused resources? + */ + class PhysicEngine + { + public: + /** + * Note that the shapeLoader IS destroyed by the phyic Engine!! + */ + PhysicEngine(BulletShapeLoader* shapeLoader); + + /** + * It DOES destroy the shape loader! + */ + ~PhysicEngine(); + + /** + * Create a RigidBody.It does not add it to the simulation, but it does add it to the rigidBody Map, + * so you can get it with the getRigidBody function. + */ + RigidBody* createRigidBody(std::string mesh,std::string name); + + /** + * Add a RigidBody to the simulation + */ + void addRigidBody(RigidBody* body); + + /** + * Remove a RigidBody from the simulation. It does not delete it, and does not remove it from the RigidBodyMap. + */ + void removeRigidBody(std::string name); + + /** + * Delete a RigidBody, and remove it from RigidBodyMap. + */ + void deleteRigidBody(std::string name); + + /** + * Return a pointer to a given rigid body. + * TODO:check if exist + */ + RigidBody* getRigidBody(std::string name); + + /** + * Create and add a character to the scene, and add it to the ActorMap. + */ + void addCharacter(std::string name); + + /** + * Remove a character from the scene. TODO:delete it! for now, a small memory leak^^ done? + */ + void removeCharacter(std::string name); + + /** + * Return a pointer to a character + * TODO:check if the actor exist... + */ + PhysicActor* getCharacter(std::string name); + + /** + * This step the simulation of a given time. + */ + void stepSimulation(double deltaT); + + /** + * Empty events lists + */ + void emptyEventLists(void); + + /** + * Create a debug rendering. It is called by setDebgRenderingMode if it's not created yet. + * Important Note: this will crash if the Render is not yet initialise! + */ + void createDebugRendering(); + + /** + * Set the debug rendering mode. 0 to turn it off. + * Important Note: this will crash if the Render is not yet initialise! + */ + void setDebugRenderingMode(int mode); + + /** + * Return the closest object hit by a ray. If there are no objects, it will return ("",-1). + */ std::pair rayTest(btVector3& from,btVector3& to); - //event list of non player object - std::list NPEventList; + //event list of non player object + std::list NPEventList; - //event list affecting the player - std::list PEventList; + //event list affecting the player + std::list PEventList; - //Bullet Stuff - btBroadphaseInterface* broadphase; - btDefaultCollisionConfiguration* collisionConfiguration; - btSequentialImpulseConstraintSolver* solver; - btCollisionDispatcher* dispatcher; - btDiscreteDynamicsWorld* dynamicsWorld; + //Bullet Stuff + btBroadphaseInterface* broadphase; + btDefaultCollisionConfiguration* collisionConfiguration; + btSequentialImpulseConstraintSolver* solver; + btCollisionDispatcher* dispatcher; + btDiscreteDynamicsWorld* dynamicsWorld; - //the NIF file loader. - BulletShapeLoader* mShapeLoader; + //the NIF file loader. + BulletShapeLoader* mShapeLoader; - std::map RigidBodyMap; - std::map PhysicActorMap; + std::map RigidBodyMap; + std::map PhysicActorMap; - //debug rendering - BtOgre::DebugDrawer* mDebugDrawer; - bool isDebugCreated; - }; + //debug rendering + BtOgre::DebugDrawer* mDebugDrawer; + bool isDebugCreated; + }; }} diff --git a/mangle b/mangle index a05046026..f3c9694bf 160000 --- a/mangle +++ b/mangle @@ -1 +1 @@ -Subproject commit a05046026ec9edb1e528fac2c70f887239302237 +Subproject commit f3c9694bf249a34eae05f0304e6bfc120014ce8c diff --git a/ogre/mouselook.cpp b/ogre/mouselook.cpp index c74f5365c..841bab603 100644 --- a/ogre/mouselook.cpp +++ b/ogre/mouselook.cpp @@ -10,48 +10,48 @@ using namespace OEngine::Render; void MouseLookEvent::event(Type type, int index, const void *p) { - if(type != EV_MouseMove || camera == NULL) return; - - MouseEvent *arg = (MouseEvent*)(p); - - float x = arg->state.X.rel * sensX; - float y = arg->state.Y.rel * sensY; - - camera->getParentSceneNode()->getParentSceneNode()->yaw(Degree(-x)); - camera->getParentSceneNode()->pitch(Degree(-y)); - if(flipProt) - { - // The camera before pitching - /*Quaternion nopitch = camera->getParentSceneNode()->getOrientation(); - - camera->getParentSceneNode()->pitch(Degree(-y)); - - // Apply some failsafe measures against the camera flipping - // upside down. Is the camera close to pointing straight up or - // down? - if(Ogre::Vector3(camera->getParentSceneNode()->getOrientation()*Ogre::Vector3::UNIT_Y)[1] <= 0.1) - // If so, undo the last pitch - camera->getParentSceneNode()->setOrientation(nopitch);*/ - //camera->getU - - // Angle of rotation around the X-axis. - float pitchAngle = (2 * Ogre::Degree(Ogre::Math::ACos(camera->getParentSceneNode()->getOrientation().w)).valueDegrees()); - - // Just to determine the sign of the angle we pick up above, the - // value itself does not interest us. - float pitchAngleSign = camera->getParentSceneNode()->getOrientation().x; - - // Limit the pitch between -90 degress and +90 degrees, Quake3-style. - if (pitchAngle > 90.0f) - { - if (pitchAngleSign > 0) - // Set orientation to 90 degrees on X-axis. - camera->getParentSceneNode()->setOrientation(Ogre::Quaternion(Ogre::Math::Sqrt(0.5f), - Ogre::Math::Sqrt(0.5f), 0, 0)); - else if (pitchAngleSign < 0) - // Sets orientation to -90 degrees on X-axis. - camera->getParentSceneNode()->setOrientation(Ogre::Quaternion(Ogre::Math::Sqrt(0.5f), - -Ogre::Math::Sqrt(0.5f), 0, 0)); - } - } + if(type != EV_MouseMove || camera == NULL) return; + + MouseEvent *arg = (MouseEvent*)(p); + + float x = arg->state.X.rel * sensX; + float y = arg->state.Y.rel * sensY; + + camera->getParentSceneNode()->getParentSceneNode()->yaw(Degree(-x)); + camera->getParentSceneNode()->pitch(Degree(-y)); + if(flipProt) + { + // The camera before pitching + /*Quaternion nopitch = camera->getParentSceneNode()->getOrientation(); + + camera->getParentSceneNode()->pitch(Degree(-y)); + + // Apply some failsafe measures against the camera flipping + // upside down. Is the camera close to pointing straight up or + // down? + if(Ogre::Vector3(camera->getParentSceneNode()->getOrientation()*Ogre::Vector3::UNIT_Y)[1] <= 0.1) + // If so, undo the last pitch + camera->getParentSceneNode()->setOrientation(nopitch);*/ + //camera->getU + + // Angle of rotation around the X-axis. + float pitchAngle = (2 * Ogre::Degree(Ogre::Math::ACos(camera->getParentSceneNode()->getOrientation().w)).valueDegrees()); + + // Just to determine the sign of the angle we pick up above, the + // value itself does not interest us. + float pitchAngleSign = camera->getParentSceneNode()->getOrientation().x; + + // Limit the pitch between -90 degress and +90 degrees, Quake3-style. + if (pitchAngle > 90.0f) + { + if (pitchAngleSign > 0) + // Set orientation to 90 degrees on X-axis. + camera->getParentSceneNode()->setOrientation(Ogre::Quaternion(Ogre::Math::Sqrt(0.5f), + Ogre::Math::Sqrt(0.5f), 0, 0)); + else if (pitchAngleSign < 0) + // Sets orientation to -90 degrees on X-axis. + camera->getParentSceneNode()->setOrientation(Ogre::Quaternion(Ogre::Math::Sqrt(0.5f), + -Ogre::Math::Sqrt(0.5f), 0, 0)); + } + } } diff --git a/ogre/renderer.cpp b/ogre/renderer.cpp index 9ce7a053f..36291864e 100644 --- a/ogre/renderer.cpp +++ b/ogre/renderer.cpp @@ -104,7 +104,7 @@ void OgreRenderer::createScene(const std::string camName, float fov, float nearC mCamera = mScene->createCamera(camName); mCamera->setNearClipDistance(nearClip); mCamera->setFOVy(Degree(fov)); - + // Create one viewport, entire window mView = mWindow->addViewport(mCamera); From d62fd96cd51ab6229a97a7f9bf426e306ef9b532 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Thu, 1 Sep 2011 21:48:36 +0200 Subject: [PATCH 44/56] Issue #168: Configuration cleanup, part 2 Updated configure() method. Signed-off-by: Lukasz Gromanowski --- ogre/renderer.cpp | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/ogre/renderer.cpp b/ogre/renderer.cpp index 36291864e..0cd75c6b6 100644 --- a/ogre/renderer.cpp +++ b/ogre/renderer.cpp @@ -38,37 +38,25 @@ bool OgreRenderer::configure(bool showConfig, const std::string &pluginCfg, bool _logging) { - std::string theLogFile("Ogre.log"); - std::string theCfgFile("ogre.cfg"); + // Set up logging first + new LogManager; + Log *log = LogManager::getSingleton().createLog(logPath + std::string("Ogre.log")); + logging = _logging; - theLogFile.insert(0, logPath); - theCfgFile.insert(0, cfgPath); - - // Set up logging first - new LogManager; - Log *log = LogManager::getSingleton().createLog(theLogFile); - logging = _logging; - - if(logging) + if(logging) // Full log detail log->setLogDetail(LL_BOREME); - else + else // Disable logging log->setDebugOutputEnabled(false); - mRoot = new Root(pluginCfg, theCfgFile, ""); - - // Show the configuration dialog and initialise the system, if the - // showConfig parameter is specified. The settings are stored in - // ogre.cfg. If showConfig is false, the settings are assumed to - // already exist in ogre.cfg. - int result; - if(showConfig) - result = mRoot->showConfigDialog(); - else - result = mRoot->restoreConfig(); + mRoot = new Root(pluginCfg, cfgPath, ""); - return !result; + // Show the configuration dialog and initialise the system, if the + // showConfig parameter is specified. The settings are stored in + // ogre.cfg. If showConfig is false, the settings are assumed to + // already exist in ogre.cfg. + return (showConfig) ? mRoot->showConfigDialog() : mRoot->restoreConfig(); } bool OgreRenderer::configure(bool showConfig, From 0b1d6d4330818ee3e491e1ec78928ff714e9bbaa Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Fri, 2 Sep 2011 19:55:10 +0200 Subject: [PATCH 45/56] Issue #168: Configuration cleanup, part 2 Corrected return code. Signed-off-by: Lukasz Gromanowski --- ogre/renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ogre/renderer.cpp b/ogre/renderer.cpp index 0cd75c6b6..ca263d815 100644 --- a/ogre/renderer.cpp +++ b/ogre/renderer.cpp @@ -56,7 +56,7 @@ bool OgreRenderer::configure(bool showConfig, // showConfig parameter is specified. The settings are stored in // ogre.cfg. If showConfig is false, the settings are assumed to // already exist in ogre.cfg. - return (showConfig) ? mRoot->showConfigDialog() : mRoot->restoreConfig(); + return (showConfig) ? !mRoot->showConfigDialog() : !mRoot->restoreConfig(); } bool OgreRenderer::configure(bool showConfig, From 26b9d0fdc374fac648f6293e1d4a4abdc2c20c19 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 27 Sep 2011 09:44:42 +0200 Subject: [PATCH 46/56] config fix --- ogre/renderer.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/ogre/renderer.cpp b/ogre/renderer.cpp index ca263d815..137b4dd21 100644 --- a/ogre/renderer.cpp +++ b/ogre/renderer.cpp @@ -38,25 +38,31 @@ bool OgreRenderer::configure(bool showConfig, const std::string &pluginCfg, bool _logging) { - // Set up logging first - new LogManager; - Log *log = LogManager::getSingleton().createLog(logPath + std::string("Ogre.log")); - logging = _logging; + // Set up logging first + new LogManager; + Log *log = LogManager::getSingleton().createLog(logPath); + logging = _logging; - if(logging) + if(logging) // Full log detail log->setLogDetail(LL_BOREME); - else + else // Disable logging log->setDebugOutputEnabled(false); - mRoot = new Root(pluginCfg, cfgPath, ""); + mRoot = new Root(pluginCfg, cfgPath, ""); - // Show the configuration dialog and initialise the system, if the - // showConfig parameter is specified. The settings are stored in - // ogre.cfg. If showConfig is false, the settings are assumed to - // already exist in ogre.cfg. - return (showConfig) ? !mRoot->showConfigDialog() : !mRoot->restoreConfig(); + // Show the configuration dialog and initialise the system, if the + // showConfig parameter is specified. The settings are stored in + // ogre.cfg. If showConfig is false, the settings are assumed to + // already exist in ogre.cfg. + int result; + if(showConfig) + result = mRoot->showConfigDialog(); + else + result = mRoot->restoreConfig(); + + return !result; } bool OgreRenderer::configure(bool showConfig, From 51f859651dab6f0beeaba6444820c72d8beaef1c Mon Sep 17 00:00:00 2001 From: Jacob Essex Date: Wed, 9 Nov 2011 23:15:06 +0000 Subject: [PATCH 47/56] Exceptions from input handlers are now caught in OpenEngine as opposed to requring a try/catch in the input handler itself --- input/dispatcher.hpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/input/dispatcher.hpp b/input/dispatcher.hpp index dd6fb6bf6..2cd1ed5ae 100644 --- a/input/dispatcher.hpp +++ b/input/dispatcher.hpp @@ -47,7 +47,23 @@ struct Dispatcher : Mangle::Input::Event const _O &list = map.getList(index); _O::const_iterator it; for(it = list.begin(); it != list.end(); it++) - funcs.call(*it, p); + { + //catch exceptions thrown in the input handlers so that pressing a key + //doesn't cause OpenMw to crash + try + { + funcs.call(*it, p); + } + catch(const std::exception& e) + { + std::cerr << "Exception in input handler: " << e.what() << std::endl; + } + catch(...) + { + std::cerr << "Unknown exception in input handler" << std::endl; + } + + } } }; From 2f5eca9d878526bdd9dce93ece7f42093b481545 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 10 Nov 2011 08:36:38 +0100 Subject: [PATCH 48/56] include fix --- input/dispatcher.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/input/dispatcher.hpp b/input/dispatcher.hpp index 2cd1ed5ae..a8d480d4b 100644 --- a/input/dispatcher.hpp +++ b/input/dispatcher.hpp @@ -1,10 +1,13 @@ #ifndef OENGINE_INPUT_DISPATCHER_H #define OENGINE_INPUT_DISPATCHER_H +#include +#include + +#include + #include "dispatch_map.hpp" #include "func_binder.hpp" -#include -#include namespace OEngine { namespace Input { From 0a55fe0219b60b549c1d8c5e29e37d1f49f92917 Mon Sep 17 00:00:00 2001 From: gugus Date: Mon, 23 Jan 2012 21:49:51 +0100 Subject: [PATCH 49/56] Fixed NPC activation. Might require some more work when NPC physic will be used. Note: some NPC seems to be smaller than other, but for now, the capsule shae size is the same for every NPC --- bullet/physic.cpp | 16 +++++++++------- bullet/physic.hpp | 2 ++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/bullet/physic.cpp b/bullet/physic.cpp index 8cf7b8eb6..8fa54a9e6 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -34,8 +34,8 @@ namespace Physic externalGhostObject = new PairCachingGhostObject(name); externalGhostObject->setWorldTransform( transform ); - btScalar externalCapsuleHeight = 130; - btScalar externalCapsuleWidth = 16; + btScalar externalCapsuleHeight = 120; + btScalar externalCapsuleWidth = 19; externalCollisionShape = new btCapsuleShapeZ( externalCapsuleWidth, externalCapsuleHeight ); externalCollisionShape->setMargin( 0.1 ); @@ -47,8 +47,8 @@ namespace Physic internalGhostObject = new PairCachingGhostObject(name); internalGhostObject->setWorldTransform( transform ); //internalGhostObject->getBroadphaseHandle()->s - btScalar internalCapsuleHeight = 120; - btScalar internalCapsuleWidth = 15; + btScalar internalCapsuleHeight = 110; + btScalar internalCapsuleWidth = 17; internalCollisionShape = new btCapsuleShapeZ( internalCapsuleWidth, internalCapsuleHeight ); internalCollisionShape->setMargin( 0.1 ); @@ -62,6 +62,8 @@ namespace Physic mCharacter->mCollision = false; setGravity(0); + + mTranslation = btVector3(0,0,70); } PhysicActor::~PhysicActor() @@ -113,7 +115,7 @@ namespace Physic btVector3 PhysicActor::getPosition(void) { - return internalGhostObject->getWorldTransform().getOrigin(); + return internalGhostObject->getWorldTransform().getOrigin() -mTranslation; } btQuaternion PhysicActor::getRotation(void) @@ -123,8 +125,8 @@ namespace Physic void PhysicActor::setPosition(const btVector3& pos) { - internalGhostObject->getWorldTransform().setOrigin(pos); - externalGhostObject->getWorldTransform().setOrigin(pos); + internalGhostObject->getWorldTransform().setOrigin(pos+mTranslation); + externalGhostObject->getWorldTransform().setOrigin(pos+mTranslation); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/bullet/physic.hpp b/bullet/physic.hpp index d4dfde467..9f554dd0e 100644 --- a/bullet/physic.hpp +++ b/bullet/physic.hpp @@ -89,6 +89,8 @@ namespace Physic btCollisionShape* externalCollisionShape; std::string mName; + + btVector3 mTranslation; }; /** From 6c15aec5e4c791c01030ea3b6d3e8352a8577a61 Mon Sep 17 00:00:00 2001 From: gugus Date: Mon, 23 Jan 2012 22:16:08 +0100 Subject: [PATCH 50/56] added some comments --- bullet/physic.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bullet/physic.hpp b/bullet/physic.hpp index 9f554dd0e..750761965 100644 --- a/bullet/physic.hpp +++ b/bullet/physic.hpp @@ -90,6 +90,10 @@ namespace Physic std::string mName; + /** + *NPC scenenode is located on there feet, and you can't simply translate a btShape, so this vector is used + *each time get/setposition is called. + */ btVector3 mTranslation; }; From 8affa30ff1e0357ac04566bd64a40849a44545b6 Mon Sep 17 00:00:00 2001 From: gugus Date: Mon, 6 Feb 2012 23:15:19 +0100 Subject: [PATCH 51/56] magic commit that fixe the crash when activating collision after changing cell. To be faire, this commit should break the collision system... there must be something I don't understand with bullet ghost objects :p --- bullet/physic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bullet/physic.cpp b/bullet/physic.cpp index 8fa54a9e6..294b37978 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -157,7 +157,7 @@ namespace Physic //TODO: memory leak? btOverlappingPairCache* pairCache = new btSortedOverlappingPairCache(); - pairCache->setInternalGhostPairCallback( new btGhostPairCallback() ); + //pairCache->setInternalGhostPairCallback( new btGhostPairCallback() ); broadphase = new btDbvtBroadphase(pairCache); From b77f5c06cc3fd818a5efbbb42d6c2a079fa91143 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 18 Feb 2012 18:25:02 +0100 Subject: [PATCH 52/56] added facilities for fading the screen in/out --- ogre/fader.cpp | 104 ++++++++++++++++++++++++++++++++++++++++++++++ ogre/fader.hpp | 54 ++++++++++++++++++++++++ ogre/renderer.cpp | 10 +++++ ogre/renderer.hpp | 7 ++++ 4 files changed, 175 insertions(+) create mode 100644 ogre/fader.cpp create mode 100644 ogre/fader.hpp diff --git a/ogre/fader.cpp b/ogre/fader.cpp new file mode 100644 index 000000000..6e15d91b7 --- /dev/null +++ b/ogre/fader.cpp @@ -0,0 +1,104 @@ +#include "fader.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define FADE_OVERLAY_NAME "FadeInOutOverlay" +#define FADE_OVERLAY_PANEL_NAME "FadeInOutOverlayPanel" +#define FADE_MATERIAL_NAME "FadeInOutMaterial" + +using namespace Ogre; +using namespace OEngine::Render; + +Fader::Fader() : + mMode(FadingMode_None), + mRemainingTime(0.f), + mTargetTime(0.f), + mTargetAlpha(0.f) +{ + + // Create the fading material + MaterialPtr material = MaterialManager::getSingleton().create( FADE_MATERIAL_NAME, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); + Pass* pass = material->getTechnique(0)->getPass(0); + pass->setSceneBlending(SBT_TRANSPARENT_ALPHA); + mFadeTextureUnit = pass->createTextureUnitState(); + mFadeTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(0.f, 0.f, 0.f)); // always black colour + + // Create the overlay + OverlayManager& ovm = OverlayManager::getSingleton(); + + mOverlay = ovm.create( FADE_OVERLAY_NAME ); + + OverlayContainer* overlay_panel; + overlay_panel = (OverlayContainer*)ovm.createOverlayElement("Panel", FADE_OVERLAY_PANEL_NAME); + + // position it over the whole screen + overlay_panel->_setPosition(0, 0); + overlay_panel->_setDimensions(1, 1); + + overlay_panel->setMaterialName( FADE_MATERIAL_NAME ); + overlay_panel->show(); + mOverlay->add2D(overlay_panel); + mOverlay->hide(); +} + +void Fader::update(float dt) +{ + if (mMode == FadingMode_None) return; + + if (mRemainingTime > 0) + { + mOverlay->show(); + float alpha; + if (mMode == FadingMode_In) + alpha = (mRemainingTime/mTargetTime) * 1.f; + else if (mMode == FadingMode_Out) + alpha = (1-(mRemainingTime/mTargetTime)) * 1.f; + else if (mMode == FadingMode_To) + alpha = (1-(mRemainingTime/mTargetTime)) * mTargetAlpha; + + mFadeTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, alpha); + + mRemainingTime -= dt; + } + else + { + mMode = FadingMode_None; + mOverlay->hide(); + } +} + +void Fader::fadeIn(float time) +{ + if (time<=0) return; + + mMode = FadingMode_In; + mTargetTime = time; + mRemainingTime = time; +} + +void Fader::fadeOut(const float time) +{ + if (time<=0) return; + + mMode = FadingMode_Out; + mTargetTime = time; + mRemainingTime = time; +} + +void Fader::fadeTo(const int percent, const float time) +{ + if (time<=0) return; + + mMode = FadingMode_To; + mTargetTime = time; + mRemainingTime = time; + mTargetAlpha = percent/100.f; +} diff --git a/ogre/fader.hpp b/ogre/fader.hpp new file mode 100644 index 000000000..0bc96acfa --- /dev/null +++ b/ogre/fader.hpp @@ -0,0 +1,54 @@ +#ifndef OENGINE_OGRE_FADE_H +#define OENGINE_OGRE_FADE_H + +/* + A class that handles fading in the screen from black or fading it out to black. + + To achieve this, it uses a full-screen Ogre::Overlay + + inspired by http://www.ogre3d.org/tikiwiki/FadeEffectOverlay (heavily adjusted) + */ + +#include + +namespace Ogre +{ + class TextureUnitState; + class Overlay; +} + +namespace OEngine { +namespace Render +{ + class Fader + { + public: + Fader(); + + void update(float dt); + + void fadeIn(const float time); + void fadeOut(const float time); + void fadeTo(const int percent, const float time); + + private: + enum FadingMode + { + FadingMode_In, + FadingMode_Out, + FadingMode_To, + FadingMode_None // no fading + }; + + Ogre::TextureUnitState* mFadeTextureUnit; + Ogre::Overlay* mOverlay; + + FadingMode mMode; + float mRemainingTime; + float mTargetTime; + float mTargetAlpha; + + protected: + }; +}} +#endif diff --git a/ogre/renderer.cpp b/ogre/renderer.cpp index ca263d815..1ce1d2609 100644 --- a/ogre/renderer.cpp +++ b/ogre/renderer.cpp @@ -1,4 +1,5 @@ #include "renderer.hpp" +#include "fader.hpp" #include "OgreRoot.h" #include "OgreRenderWindow.h" @@ -12,6 +13,8 @@ using namespace OEngine::Render; void OgreRenderer::cleanup() { + delete mFader; + if(mRoot) delete mRoot; mRoot = NULL; @@ -22,6 +25,11 @@ void OgreRenderer::start() mRoot->startRendering(); } +void OgreRenderer::update(float dt) +{ + mFader->update(dt); +} + void OgreRenderer::screenshot(const std::string &file) { mWindow->writeContentsToFile(file); @@ -98,4 +106,6 @@ void OgreRenderer::createScene(const std::string camName, float fov, float nearC // Alter the camera aspect ratio to match the viewport mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); + + mFader = new Fader(); } diff --git a/ogre/renderer.hpp b/ogre/renderer.hpp index 982534e6b..0c2f0d3d1 100644 --- a/ogre/renderer.hpp +++ b/ogre/renderer.hpp @@ -19,6 +19,7 @@ namespace Ogre namespace OEngine { namespace Render { + class Fader; class OgreRenderer { Ogre::Root *mRoot; @@ -26,6 +27,7 @@ namespace Render Ogre::SceneManager *mScene; Ogre::Camera *mCamera; Ogre::Viewport *mView; + Fader* mFader; bool logging; public: @@ -66,6 +68,8 @@ namespace Render /// Start the main rendering loop void start(); + + void update(float dt); /// Write a screenshot to file void screenshot(const std::string &file); @@ -80,6 +84,9 @@ namespace Render /// Get the scene manager Ogre::SceneManager *getScene() { return mScene; } + + /// Get the screen colour fader + Fader *getFader() { return mFader; } /// Camera Ogre::Camera *getCamera() { return mCamera; } From eb61ba59e64c332931c12251cac40de5836ff9cd Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 19 Feb 2012 17:45:57 +0100 Subject: [PATCH 53/56] updated the fading calculation (the alpha value stays now, even after the specified time - this is how it is in morrowind) --- ogre/fader.cpp | 82 +++++++++++++++++++++++++++++++++++--------------- ogre/fader.hpp | 11 ++++--- 2 files changed, 64 insertions(+), 29 deletions(-) diff --git a/ogre/fader.cpp b/ogre/fader.cpp index 6e15d91b7..062559e00 100644 --- a/ogre/fader.cpp +++ b/ogre/fader.cpp @@ -18,10 +18,12 @@ using namespace Ogre; using namespace OEngine::Render; Fader::Fader() : - mMode(FadingMode_None), + mMode(FadingMode_In), mRemainingTime(0.f), mTargetTime(0.f), - mTargetAlpha(0.f) + mTargetAlpha(0.f), + mCurrentAlpha(0.f), + mStartAlpha(0.f) { // Create the fading material @@ -50,35 +52,46 @@ Fader::Fader() : } void Fader::update(float dt) -{ - if (mMode == FadingMode_None) return; - +{ if (mRemainingTime > 0) { - mOverlay->show(); - float alpha; if (mMode == FadingMode_In) - alpha = (mRemainingTime/mTargetTime) * 1.f; + { + mCurrentAlpha -= dt/mTargetTime * (mStartAlpha-mTargetAlpha); + if (mCurrentAlpha < mTargetAlpha) mCurrentAlpha = mTargetAlpha; + } else if (mMode == FadingMode_Out) - alpha = (1-(mRemainingTime/mTargetTime)) * 1.f; - else if (mMode == FadingMode_To) - alpha = (1-(mRemainingTime/mTargetTime)) * mTargetAlpha; - - mFadeTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, alpha); + { + mCurrentAlpha += dt/mTargetTime * (mTargetAlpha-mStartAlpha); + if (mCurrentAlpha > mTargetAlpha) mCurrentAlpha = mTargetAlpha; + } + + applyAlpha(); mRemainingTime -= dt; } - else - { - mMode = FadingMode_None; - mOverlay->hide(); - } + + if (mCurrentAlpha == 0.f) mOverlay->hide(); +} + +void Fader::applyAlpha() +{ + mOverlay->show(); + mFadeTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, mCurrentAlpha); } void Fader::fadeIn(float time) { - if (time<=0) return; - + if (time<0.f) return; + if (time==0.f) + { + mCurrentAlpha = 0.f; + applyAlpha(); + return; + } + + mStartAlpha = mCurrentAlpha; + mTargetAlpha = 0.f; mMode = FadingMode_In; mTargetTime = time; mRemainingTime = time; @@ -86,8 +99,16 @@ void Fader::fadeIn(float time) void Fader::fadeOut(const float time) { - if (time<=0) return; - + if (time<0.f) return; + if (time==0.f) + { + mCurrentAlpha = 1.f; + applyAlpha(); + return; + } + + mStartAlpha = mCurrentAlpha; + mTargetAlpha = 1.f; mMode = FadingMode_Out; mTargetTime = time; mRemainingTime = time; @@ -95,10 +116,21 @@ void Fader::fadeOut(const float time) void Fader::fadeTo(const int percent, const float time) { - if (time<=0) return; + if (time<0.f) return; + if (time==0.f) + { + mCurrentAlpha = percent/100.f; + applyAlpha(); + return; + } + + mStartAlpha = mCurrentAlpha; + mTargetAlpha = percent/100.f; + + if (mTargetAlpha == mStartAlpha) return; + else if (mTargetAlpha > mStartAlpha) mMode = FadingMode_Out; + else mMode = FadingMode_In; - mMode = FadingMode_To; mTargetTime = time; mRemainingTime = time; - mTargetAlpha = percent/100.f; } diff --git a/ogre/fader.hpp b/ogre/fader.hpp index 0bc96acfa..f76ac51ef 100644 --- a/ogre/fader.hpp +++ b/ogre/fader.hpp @@ -30,23 +30,26 @@ namespace Render void fadeIn(const float time); void fadeOut(const float time); void fadeTo(const int percent, const float time); - + private: enum FadingMode { FadingMode_In, - FadingMode_Out, - FadingMode_To, - FadingMode_None // no fading + FadingMode_Out }; + + void applyAlpha(); Ogre::TextureUnitState* mFadeTextureUnit; Ogre::Overlay* mOverlay; FadingMode mMode; + float mRemainingTime; float mTargetTime; float mTargetAlpha; + float mCurrentAlpha; + float mStartAlpha; protected: }; From 21b8456453242e132c85f92047cf9bce535c1b22 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 20 Feb 2012 21:09:08 +0100 Subject: [PATCH 54/56] fixed a double-free that can happen if OpenMW exits prematurely (when OgreRenderer is deleted before CreateScene() was called) --- ogre/renderer.cpp | 3 ++- ogre/renderer.hpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ogre/renderer.cpp b/ogre/renderer.cpp index ccbc4e191..399d50d42 100644 --- a/ogre/renderer.cpp +++ b/ogre/renderer.cpp @@ -13,7 +13,8 @@ using namespace OEngine::Render; void OgreRenderer::cleanup() { - delete mFader; + if (mFader) + delete mFader; if(mRoot) delete mRoot; diff --git a/ogre/renderer.hpp b/ogre/renderer.hpp index 0c2f0d3d1..f48383cbc 100644 --- a/ogre/renderer.hpp +++ b/ogre/renderer.hpp @@ -32,7 +32,7 @@ namespace Render public: OgreRenderer() - : mRoot(NULL), mWindow(NULL), mScene(NULL) {} + : mRoot(NULL), mWindow(NULL), mScene(NULL), mFader(NULL) {} ~OgreRenderer() { cleanup(); } /** Configure the renderer. This will load configuration files and From 5aabf22c16dab6a2230845f90fe5fdf67eeeca32 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 2 Mar 2012 16:47:13 +0100 Subject: [PATCH 55/56] collision shape scale fix --- bullet/physic.cpp | 3 ++- bullet/physic.hpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/bullet/physic.cpp b/bullet/physic.cpp index 294b37978..07bad3053 100644 --- a/bullet/physic.cpp +++ b/bullet/physic.cpp @@ -210,12 +210,13 @@ namespace Physic delete mShapeLoader; } - RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name) + RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale) { //get the shape from the .nif mShapeLoader->load(mesh,"General"); BulletShapeManager::getSingletonPtr()->load(mesh,"General"); BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(mesh,"General"); + shape->Shape->setLocalScaling(btVector3(scale,scale,scale)); //create the motionState CMotionState* newMotionState = new CMotionState(this,name); diff --git a/bullet/physic.hpp b/bullet/physic.hpp index 750761965..88e3699ae 100644 --- a/bullet/physic.hpp +++ b/bullet/physic.hpp @@ -135,7 +135,7 @@ namespace Physic * Create a RigidBody.It does not add it to the simulation, but it does add it to the rigidBody Map, * so you can get it with the getRigidBody function. */ - RigidBody* createRigidBody(std::string mesh,std::string name); + RigidBody* createRigidBody(std::string mesh,std::string name,float scale); /** * Add a RigidBody to the simulation From 04a4e20bb30a0c8be28052462f622e626b44b1b2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 4 Mar 2012 12:47:21 +0100 Subject: [PATCH 56/56] fix ogre.log --- ogre/renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ogre/renderer.cpp b/ogre/renderer.cpp index 399d50d42..ecded08d8 100644 --- a/ogre/renderer.cpp +++ b/ogre/renderer.cpp @@ -49,7 +49,7 @@ bool OgreRenderer::configure(bool showConfig, { // Set up logging first new LogManager; - Log *log = LogManager::getSingleton().createLog(logPath); + Log *log = LogManager::getSingleton().createLog(logPath + std::string("Ogre.log")); logging = _logging; if(logging)